1. 程式人生 > 實用技巧 >JavaEE學習之Spring MVC框架

JavaEE學習之Spring MVC框架

Spring MVC 學習筆記

一、Spring MVC 簡介

二、Spring MVC 入門程式

三、Spring MVC 註解使用

四、Spring MVC 引數繫結

五、Spring MVC 控制器返回值

六、Spring MVC 亂碼問題

七、Spring MVC 自定義轉換器

八、Spring MVC 檔案上傳

九、Spring MVC json資料互動

十、Spring MVC RESTful支援

十一、Spring MVC 異常處理

十二、Spring MVC 攔截器

一、Spring MVC 簡介

  1. 簡介

    Spring Web MVC是一種基於Java的實現了Web MVC設計模式的請求驅動型別的輕量級Web框架,即使用了MVC架構模式的思想,將web層進行職責解耦,基於請求驅動指的就是使用請求-響應模型,框架的目的就是幫助我們簡化開發,Spring Web MVC也是要簡化我們日常Web開發的。

  • 模型封裝了應用程式資料,並且通常它們由 POJO 組成。

  • 檢視主要用於呈現模型資料,並且通常它生成客戶端的瀏覽器可以解釋的 HTML 輸出。

  • 控制器主要用於處理使用者請求,並且構建合適的模型並將其傳遞到檢視呈現。

    DispatcherServlet

    Spring Web 模型-檢視-控制(MVC)框架是圍繞 DispatcherServlet 設計的,DispatcherServlet 用來處理所有的 HTTP 請求和響應。Spring Web MVC DispatcherServlet 的請求處理的工作流程如下圖所示:

    • 收到一個 HTTP 請求後,DispatcherServlet

      根據 HandlerMapping 來選擇並且呼叫適當的控制器

    • 控制器接受請求,並基於使用的 GET 或 POST 方法來呼叫適當的 service 方法。Service 方法將設定基於定義的業務邏輯的模型資料,並返回檢視名稱到 DispatcherServlet 中。

    • DispatcherServlet 會從 ViewResolver 獲取幫助,為請求檢取定義檢視。

    • 一旦確定檢視,DispatcherServlet 將把模型資料傳遞給檢視,最後呈現在瀏覽器中。

  1. Spring MVC和Spring的關係

二、Spring MVC 入門程式

  1. 匯入jar包

  1. 配置web.xml檔案

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name></display-name>
    <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
    <param-name>
    contextConfigLocation
    </param-name>
    <param-value>
    classpath:spring-mvc.xml
    </param-value>
    </init-param>
    </servlet>
    <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
    </servlet-mapping>
    </web-app>

  1. 配置springmvc核心配置檔案

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">


    <!--配置後端控制器(controller) -->
    <bean name="/hello" class="cn.qn.controller.HomeController"></bean>
    <!--配置處理器對映器 -->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
    <!--配置處理器介面卡 -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">
    </bean>
    <!-- 配置檢視解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"></property>
    <property name="suffix" value=".jsp"></property>
    </bean>

    </beans>

  1. 新建後端控制器(HomeController)

    public class HomeController extends AbstractController{
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
    throws Exception {
    return new ModelAndView("index");
    }
    }

  1. 配置tomcat,啟動專案

三、Spring MVC 註解使用

  1. 使用註解的後端處理控制器

    @Controller
    public class IndexController {
    配置url的訪問對映
    @RequestMapping(value="/index")
    public ModelAndView aa()
    {
    return new ModelAndView("/WEB-INF/jsp/index.jsp");
    }
    }

  1. 開啟註解掃描(此處附處理器對映器和介面卡的其他配置方式)

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 處理器對映器和處理器介面卡的配置可以省略
    springMVC框架已經做了處理
    -->
    <!-- 配置處理器對映器 -->
    <!-- <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>-->
    <!-- 使用最新版的 處理器對映器
    若使用最新版的,則處理器對映器和處理器介面卡都要配置最新版的
    -->
    <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>-->

    <!-- 配置處理器介面卡 -->
    <!-- <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>-->
    <!--使用新版的處理器介面卡 -->
    <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>-->

    <!-- springmvc自動配置最新的處理器對映器和處理器介面卡 -->
    <mvc:annotation-driven></mvc:annotation-driven>


    <!-- 配置後端控制器(controller) -->
    <!-- <bean name="/hello" class="cn.edu.dgut.controller.HelloController"></bean>-->
    <!-- 開啟掃描 -->
    <context:component-scan base-package="cn.edu.dgut.controller"></context:component-scan>

    <!-- 配置檢視解析器 若在控制器類寫了完整路徑,則不用配置 -->
    <!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"></property>
    <property name="suffix" value=".jsp"></property>
    </bean>-->

    </beans>

四、Spring MVC 引數繫結

  1. 預設支援普通servlet的方式

    @RequestMapping(value="/itemEdit")
    public ModelAndView itemEdit(HttpServletRequest req, HttpServletResponse response, HttpSession session) {
    String id = req.getParameter("id");
    Product product = productservice.getProductById(Integer.parseInt(id));
    ModelAndView mv = new ModelAndView();
    mv.setViewName("productItem");
    mv.addObject("item", product);
    return mv;
    }

  1. Spring 的 BeanFactory 容器

    這是一個最簡單的容器,它主要的功能是為依賴注入 (DI) 提供支援,這個容器介面在 org.springframework.beans.factory.BeanFactor 中被定義。BeanFactory 和相關的介面,比如BeanFactoryAware、DisposableBean、InitializingBean,仍舊保留在 Spring 中,主要目的是向後相容已經存在的和那些 Spring 整合在一起的第三方框架。

  1. Spring ApplicationContext 容器

    Application Context 是 BeanFactory 的子介面,也被成為 Spring 上下文。

    Application Context 是 spring 中較高階的容器。和 BeanFactory 類似,它可以載入配置檔案中定義的 bean,將所有的 bean 集中在一起,當有請求的時候分配 bean。 另外,它增加了企業所需要的功能,比如,從屬性檔案中解析文字資訊和將事件傳遞給所指定的監聽器。這個容器在 org.springframework.context.ApplicationContext interface 介面中定義。

    ApplicationContext 包含 BeanFactory 所有的功能,一般情況下,相對於 BeanFactory,ApplicationContext 會更加優秀。當然,BeanFactory 仍可以在輕量級應用中使用,比如移動裝置或者基於 applet 的應用程式。

  1. Bean

    被稱作 bean 的物件是構成應用程式的支柱也是由 Spring IoC 容器管理的。bean 是一個被例項化,組裝,並通過 Spring IoC 容器所管理的物件。

  • Bean 的作用域

    當在 Spring 中定義一個 bean 時,你必須宣告該 bean 的作用域的選項。例如,為了強制 Spring 在每次需要時都產生一個新的 bean 例項,你應該宣告 bean 的作用域的屬性為 prototype。同理,如果你想讓 Spring 在每次需要時都返回同一個bean例項,你應該宣告 bean 的作用域的屬性為 singleton

    作用域描述
    singleton 在spring IoC容器僅存在一個Bean例項,Bean以單例方式存在,預設值
    prototype 每次從容器中呼叫Bean時,都返回一個新的例項,即每次呼叫getBean()時,相當於執行newXxxBean()
    request 每次HTTP請求都會建立一個新的Bean,該作用域僅適用於WebApplicationContext環境
    session 同一個HTTP Session共享一個Bean,不同Session使用不同的Bean,僅適用於WebApplicationContext環境
    global-session 一般用於Portlet應用環境,該運用域僅適用於WebApplicationContext環境
  1. 簡單型別(引數名要與jsp中name屬性值對應)

    @RequestMapping(value="/updateitem")
    public ModelAndView update(Integer id, String name, float price, String detail)
    {
    Product product = new Product();
    product.setId(id);
    product.setName(name);
    product.setPrice(price);
    product.setDetail(detail);
    product.setCreatetime(new Date());

    productservice.update(product);

    ModelAndView mv = new ModelAndView();
    mv.setViewName("test");
    return mv;
    }

  1. 實體物件(jsp中name屬性名要與實體中屬性對應)

    @RequestMapping(value="/updateitem")
    public ModelAndView update(Product product)
    {
    productservice.update(product);
    ModelAndView mv = new ModelAndView();
    mv.setViewName("test");
    return mv;
    }

五、Spring MVC 控制器返回值

  1. ModelAndView

    modelAndView.addObject("itemList", list); //指定返回頁面的資料
    modelAndView.setViewName("itemList");	  //指定返回的頁面

  1. String(推薦使用)

    返回普通字串,就是頁面去掉副檔名的名稱, 返回給頁面資料通過Model來完成

    • 普通跳轉(jsp頁面)

      @RequestMapping(value="/updateProduct")
      public String updateProduct(Product product,Model model) throws ServletException {	
          productservice.update(product);			
          model.addAttribute("xxx",”xxxx”);
          return " productItem ";
      }
    • 請求轉發(請求)

      @RequestMapping(value="/updateProduct")
      public String updateProduct(Product product,Model model) throws ServletException {	
          productservice.update(product);
          model.addAttribute("msg","今天天氣不錯呀");
          return "forward:list";
      }
    • 重定向(請求)

      @RequestMapping(value="/updateProduct")
      public String updateProduct(Product product,Model model) throws ServletException {	
          productservice.update(product);
          model.addAttribute("msg","今天天氣不錯呀");
          //return "forward:list";
          return "redirect:list";
      }

  1. void(破壞了springMvc的結構,不建議使用)

    • 可以使用request.setAttribut 來給頁面返回資料

    • 可以使用request.getRquestDispatcher().forward()來指定返回的頁面

    • 如果controller返回值為void則不走springMvc的元件,所以要寫頁面的完整路徑名稱

六、Spring MVC 亂碼問題

  1. 解決post亂碼問題(在web.xml中加入過濾器配置)

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
        	<param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

  1. get亂碼問題

    • 修改tomcat配置檔案新增編碼與工程編碼一致,如下:

      <Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
    • 也可以對引數進行重新編碼

      String username= new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8");

七、Spring MVC 自定義轉換器

  1. 編寫自定義轉換器類

    public class CustomerConveter implements Converter<String, Date>{
    	@Override
    	public Date convert(String source) {
    		try {
    			Date date = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(source);
    			return date;
    		} catch (ParseException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return null;
    	}
    
    }

  1. 在springmvc.xml中配置自定義轉換器

    	<!--配置自定義轉換器 -->
    	<bean name="conversionService"
    		class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    		<property name="converters">
    			<set>
    				<bean class="com.shop.conveter.CustomerConveter"></bean>
    			</set>
    		</property>
    	</bean>

  1. 將配置好的自定義轉換器掛載(springmvc.xml)

    <mvc:annotation-driven
    		conversion-service="conversionService"></mvc:annotation-driven>

八、Spring MVC 檔案上傳

  1. 準備jar包

  1. jsp客戶端準備

    • 提供一個File上傳表單控制元件

    • 指定表單型別

      !-- 上傳圖片是需要指定屬性 enctype="multipart/form-data" -->
      <form id="itemForm" action="${pageContext.request.contextPath}/updateProduct" method="post" enctype="multipart/form-data">

  1. 配置SpringMVC檔案上傳

    <!-- 配置檔案上傳 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
      <!-- 配置上傳圖片最大上限 5M -->
      <property name="maxUploadSize">
        <value>5242880</value>
      </property>
    </bean>

  1. 上傳後臺程式碼實現

    @RequestMapping(value="/updateProduct")
    	public ModelAndView updateProduct(MultipartFile  pictureFile,Product product) throws IllegalStateException, IOException
    	{
    if(!pictureFile.isEmpty())
    		{
    		// 獲取圖片的完整路徑
    		String fileName = pictureFile.getOriginalFilename();
    		
    		// 使用隨機生成的字串   + 原圖片的副檔名 組成
    		
    		String  NewFileName = UUID.randomUUID().toString()+fileName.substring(fileName.lastIndexOf("."));
    		
    		// 將圖片儲存在伺服器  (硬碟)
    		pictureFile.transferTo(new File("D:\\images\\"+NewFileName));
    		// 儲存在資料庫
    		
    	    product.setPic(NewFileName);
    }
    		
    		//product.setCreatetime(new Date());
    		//執行修改功能
    		
    		productservice.update(product);
    		
    		ModelAndView mv = new ModelAndView();
    		mv.setViewName("test");
    	    return mv;     	
    	}

九、Spring MVC json資料互動

  1. 匯入jar包

  1. 配置json轉換器(如果使用<mvc:annotation-driven />則不用配置以下的內容)

    <!--註解介面卡 -->
    	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    		<property name="messageConverters">
    		<list>
    		<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
    		</list>
    		</property>
    	</bean>

  1. 編寫前端

    • 匯入jquery檔案

      <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.4.4.min.js"></script>
    • 編寫Ajax方法

      <script type="text/javascript">
      //請求json響應json
      	function sendjson()
      	{
      	  $.ajax({
      			type:"post",
      			url:"${pageContext.request.contextPath}/sendjson",
      			contentType:"application/json;charset=utf-8",
      			data:'{"name":"iphoneX爆款手機","price":8000.9}',
      			success:function(data){
      				alert(data);
      			}
      		});
      	}
      </script>
      <input type="button" value="傳送json" onclick="sendjson()">

  1. controller編寫

    @RequestMapping(value="/sendjson")
    @ResponseBody //將物件轉成json格式
    public Product sendjson(@RequestBody Product product) {
        System.out.println("product:"+product);
        return product; 
    }

十、Spring MVC RESTful支援

  1. RESTful概念

    Representational State Transfer,即表述性轉移,是一種軟體架構的風格(一個規範),不是一門技術。

  1. REST和傳統方式對比

  1. REST風格好處

    • 使用傳統url方式進行引數引數的時候,如果需要傳遞引數,那麼中文亂碼很頭疼

    • n 傳統url方式,對於各大搜索引擎的收錄,並不是很友好,但是rest風格方式,搜尋引擎就更加酷愛

  1. RESTful使用

    <%-- <td><a href="${pageContext.request.contextPath }/itemEdit?id=${item.id}">修改</a></td> --%>
    	
    	<td><a href="${pageContext.request.contextPath }/itemEdit/${item.id}">修改</a></td>
    @RequestMapping(value="/itemEdit/{id}")
    public ModelAndView getProductById(@PathVariable("id")Integer aa,HttpServletRequest req, HttpServletResponse response, HttpSession ss) {
        //String id = req.getParameter("id");
        //Product product = productservice.getProductById(Integer.parseInt(id));
    
        Product product = productservice.getProductById(aa);
        ...

十一、Spring MVC 異常處理(自定義異常)

  1. 新建一個自定義異常類

    public class MyException extends Exception{
    	 private String msg;
    
    	public MyException(String msg) {
    		super();
    		this.msg = msg;
    	}
    
    	public MyException() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    
    	public String getMsg() {
    		return msg;
    	}
    
    	public void setMsg(String msg) {
    		this.msg = msg;
    	}
    	 
    }

  2. 定義異常處理器

    public class GoableException implements HandlerExceptionResolver{
    
    	@Override
    	public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse response, Object handler,
    			Exception exception) {		
    		String res = "出bug了,請聯絡管理員";
    		
    		if(exception instanceof MyException)
    		{
    			res = ((MyException)exception).getMsg();
    		}
    		ModelAndView mv = new ModelAndView();
    		mv.addObject("msg", res);
    		mv.setViewName("error");
    		return mv;
    		
    		
    	}
    
    }

  1. 測試方法

    	@RequestMapping(value="/list")
        public void getList(HttpServletRequest req,HttpServletResponse response) throws ServletException, IOException, MyException
        {	
    		
    		if(true)
    		{
    			throw new MyException("您沒有找到一些商品哈哈哈");
    		}
    		
    		
    		// 製造異常情況
    		int i = 1/0;
    		
    		
    	  List<Product> list = productservice.getProductList();	

十二、Spring MVC 攔截器

Spring Web MVC 的處理器攔截器類似於Servlet 開發中的過濾器Filter,用於對處理器進行預處理和後處理。

  1. 定義攔截器

    Public class HandlerInterceptor1 implements HandlerInterceptor{
    
    	/**
    	 * controller執行前呼叫此方法
    	 * 返回true表示繼續執行,返回false中止執行
    	 * 這裡可以加入登入校驗、許可權攔截等
    	 */
    	@Override
    	Public boolean preHandle(HttpServletRequest request,
    			HttpServletResponse response, Object handler) throws Exception {
    		// TODO Auto-generated method stub
    		Return false;
    	}
    	/**
    	 * controller執行後但未返回檢視前呼叫此方法
    	 * 這裡可在返回使用者前對模型資料進行加工處理,比如這裡加入公用資訊以便頁面顯示
    	 */
    	@Override
    	Public void postHandle(HttpServletRequest request,
    			HttpServletResponse response, Object handler,
    			ModelAndView modelAndView) throws Exception {
    		// TODO Auto-generated method stub
    		
    	}
    	/**
    	 * controller執行後且檢視返回後呼叫此方法
    	 * 這裡可得到執行controller時的異常資訊
    	 * 這裡可記錄操作日誌,資源清理等
    	 */
    	@Override
    	Public void afterCompletion(HttpServletRequest request,
    			HttpServletResponse response, Object handler, Exception ex)
    			throws Exception {
    		// TODO Auto-generated method stub
    		
    	}
    
    }

  1. 配置攔截器(springmvc.xml)

    • 針對某種mapping配置攔截器

      <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
      	<property name="interceptors">
      		<list>
      			<ref bean="handlerInterceptor1"/>
      			<ref bean="handlerInterceptor2"/>
      		</list>
      	</property>
      </bean>
      	<bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>
      	<bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
    • 針對所有mapping配置全域性攔截器

      <!--攔截器 -->
      <mvc:interceptors>
      	<!--多個攔截器,順序執行 -->
      	<mvc:interceptor>
      		<mvc:mapping path="/**"/>
      		<bean class="com.shop.springmvc.filter.HandlerInterceptor1"></bean>
      	</mvc:interceptor>
      	<mvc:interceptor>
      		<mvc:mapping path="/**"/>
      		<bean class="com.shop.springmvc.filter.HandlerInterceptor2"></bean>
      	</mvc:interceptor>
      </mvc:interceptors>

本文是學習spring mvc的筆記總結,歡迎大家批評指正,有什麼問題可以評論區交流。

參考連結:https://www.w3cschool.cn/wkspring/9pf81ha5.html