1. 程式人生 > 其它 >ACWING 368 銀河

ACWING 368 銀河

一、簡介

(一)MVC的概念

MVC是一種軟體架構思想,將軟體劃分為『模型』、『檢視』、『控制器』

M:Model,模型層

​ 指工程中的『 JavaBean 』,作用是處理資料

​ JavaBean有兩種:

​ ❶實體類Bean:指pojo物件,儲存業務資料

​ ❷業務處理Bean:指Service或Dao物件,處理業務邏輯和資料訪問

V:View,檢視層

​ 指工程中的『 頁面 』,作用是與使用者進行互動,展示資料

C:Controller,控制層

​ 指工程中的『 Servlet 』,作用是接收請求和響應瀏覽器

(二)SpringMVC的概念

SpringMVC是Spring的一個後續產品,是Spring的一個子專案

SpringMVC是Spring為 表述層 開發提供的一整套的完備的解決方案

注:三層架構分別為表述層、業務邏輯層、資料訪問層。表述層包含前臺頁面和後臺servlet

(三)SpringMVC的特點

  1. Spring家族原生產品,與IOC容器等基礎設施無縫對接
  2. 基於原生的Servlet,通過了功能強大的的前端控制器DispathcherServlet,對請求和響應進行統一處理
  3. 表述層各細分領域需要解決的問題全方位覆蓋,提供全面解決方案
  4. 程式碼清新簡潔,大幅度提升開發效率
  5. 內部元件化程度高,可插拔式元件即插即用
  6. 效能卓著,尤其適用現代大型、超大型網際網路專案要求

二、開發流程

(一)引入依賴

<dependencies> 
    <!-- SpringMVC --> 
    <dependency> 
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.1</version>
    </dependency>
    <!-- 日誌 --> 
    <dependency> 
        <groupId>ch.qos.logback</groupId> 
        <artifactId>logback-classic</artifactId> 
        <version>1.2.3</version> 
    </dependency> 
    <!-- ServletAPI --> 
    <dependency> 
        <groupId>javax.servlet</groupId> 
        <artifactId>javax.servlet-api</artifactId> 
        <version>3.1.0</version> 
        <scope>provided</scope> 
    </dependency> 
    <!-- Spring5和Thymeleaf整合包 --> 
    <dependency> 
        <groupId>org.thymeleaf</groupId> 
        <artifactId>thymeleaf-spring5</artifactId> 
        <version>3.0.12.RELEASE</version> 
    </dependency> 
</dependencies>

(二)配置web.xml

註冊SpringMVC的前端控制器DispatcherServlet

1、預設配置方式

位置預設,位於WEB-INF下

名稱預設,<servlet-name>-servlet.xml

<!-- 配置SpringMVC的前端控制器 -->
<servlet>
    <servlet-name>springMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <!--  /      不匹配.jsp請求路徑的請求 -->
    <!--  /*     匹配所有請求路徑的請求 -->
    <url-pattern>/</url-pattern>
</servlet-mapping>

2、擴充套件配置方式

<init-param>,設定配置檔案的『位置』和『名稱』

<load-on-startup>,設定初始化時間

<servlet>
    <servlet-name>springMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 通過初始化引數指定SpringMVC配置檔案的位置和名稱 -->
    <init-param>
        <!-- contextConfigLocation為固定值 -->
        <param-name>contextConfigLocation</param-name>
        <!-- 配置檔案的存放路徑 src/main/resources -->
        <param-value>classpath:springMVC.xml</param-value>
    </init-param>
    <!-- DispatcherServlet的初始化時間提前到伺服器啟動時 -->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

(三)建立請求控制器

@Controller
public class HelloController {

    @RequestMapping("/")	//設定訪問路徑
    public String index() {
        return "index";		//返回檢視名稱
    }
}

(四)建立MVC配置檔案

<!-- 自動掃描包 -->
<context:component-scan base-package="com.atguigu.mvc.controller"/>

<!-- 配置Thymeleaf檢視解析器 -->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
    <property name="order" value="1"/>
    <property name="characterEncoding" value="UTF-8"/>
    <property name="templateEngine">
        <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
            <property name="templateResolver">
                <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
                    <!-- 檢視字首 -->
                    <property name="prefix" value="/WEB-INF/templates/"/>
                    <!-- 檢視字尾 -->
                    <property name="suffix" value=".html"/>
                    <property name="templateMode" value="HTML5"/>
                    <property name="characterEncoding" value="UTF-8" />
                </bean>
            </property>
        </bean>
    </property>
</bean>

<!-- 開啟mvc註解驅動 -->
<mvc:annotation-driven>
    <mvc:message-converters>
        <!-- 處理響應中文內容亂碼 -->
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="defaultCharset" value="UTF-8"/>
            <property name="supportedMediaTypes">
                <list>
                    <value>text/html</value>
                    <value>application/json</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

三、@RequestMapping

(一)概述

功能作用:將 請求處理請求的控制器方法 關聯起來,建立對映關係

註解位置

​ ❶標識一個類:設定對映請求的 請求路徑的 初識資訊

​ ❷標識一個方法:設定對映請求的 請求路徑的 具體資訊

(二)屬性

1、value屬性

該屬性必須設定

註解的value屬性 通過請求的 請求地址 匹配請求對映

註解的value屬性 是一個字串型別的陣列,可以對映多個請求地址

2、method屬性

註解的method屬性 通過請求的 請求方式 匹配請求對映

註解的method屬性 是一個RequestMethod型別的陣列,可以匹配多個

1、請求地址滿足value屬性,不滿足method屬性,405錯誤:Request method ‘POST’ not support

2、對於處理指定請求的控制器方法,SpringMVC中提供了@RequestMapping的派生註解

​ @GetMapping、@PostMapping、@PutMapping、@DeleteMapping

3、params屬性

註解的params屬性 通過請求的 請求引數 匹配請求對映

註解的params屬性 是一個字串型別的陣列,有四種設定表示式

​ ❶『 param 』:請求必須攜帶param引數

​ ❷『 !param 』:請求必須不能攜帶param引數

​ ❸『 param=value 』:請求必須攜帶param引數,且值為value

​ ❹『 param!=value 』:請求必須不能攜帶param引數,且值不為value

請求地址滿足value和method屬性,不滿足params屬性,400錯誤,Parameter conditions ... not met for actual request parameters

4、headers屬性

註解的headers屬性 通過請求的 請求頭資訊 匹配請求對映

註解的headers屬性 是一個字串型別的陣列,有四種設定表示式

​ ❶『 header 』:請求必須攜帶header請求頭資訊

​ ❷『 !header 』:請求必須不能攜帶header請求頭資訊

​ ❸『 header=value 』:請求必須攜帶header請求頭資訊,且值為value

​ ❹『 header!=value 』:請求必須不能攜帶header請求頭資訊,且值不為value

請求地址滿足value和method屬性,不滿足headers屬性,404錯誤,資源未找到

(三)value屬性補充

1、支援ant風格的路徑

即 模糊匹配

​ 『 ? 』:表示任意的單個字元

​ 『 * 』 :表示任意的0個或多個字元

​ 『 ** 』:表示任意的0層或多層目錄【只能使用 /**/xxx 的方式】

2、支援路徑中的佔位符

SpringMVC路徑中的佔位符常用於RESTful風格中,當請求路徑中將某些資料通過路徑的方式傳輸到伺服器中

就可以在相應的@RequestMapping註解的value屬性中通過佔位符{xxx}表示傳輸的資料

再通過@PathVariable註解,將佔位符所表示的資料賦值給控制器方法的形參

//請求路徑:/testRest/1/admin
@RequestMapping("/testRest/{id}/{username}")
public String testRest(@PathVariable("id")Integer id, @PathVariable("username")String username) {
    System.out.println("id = " + id);
    System.out.println("username = " + username);
    return "success";
}

四、獲取引數

1、通過ServletAPI獲取

前提:將HttpServletRequest作為控制器的形參,就可以從中獲取引數

@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request) {
    String username = request.getParameter("username");
    System.out.println("username = " + username);
    return "success";
}

+++

2、通過控制器方法的形參獲取

前提:在控制器方法的形參位置,設定和請求引數同名的形參,可以自動匹配引數和賦值

//請求地址:/testParam?username=admin&hobby=a&hobby=b
@RequestMapping("/testParam")
public String testParam(String username, String[] hobby) {
    System.out.println("username = " + username);
    System.out.println("hobby = " + Arrays.toString(hobby));
    return "success";
}

若請求中有多個同名的請求引數,形參可以設定為字串型別字串陣列型別

字串型別:使用逗號進行拼接

3、@RequestParam

作用:將請求引數控制器方法的形參建立對映關係

註解有三個屬性:

​ ❶『value』:指定請求引數中的引數名

​ ❷『required』:設定是否必須傳輸,預設為true

​ ❸『defaultValue』:設定沒有傳入或傳入""時的預設值

@RequestMapping("/testParam")
public String testParam(
        @RequestParam(value = "user_name", required = false, defaultValue = "he") 
    		String username) {
    
    System.out.println("username = " + username);
    return "success";
}

4、@RequestHeader

作用:將請求頭資訊控制器方法的形參建立對映關係

@RequestMapping("/testParam")
public String testParam(@RequestHeader(value = "Host") String host) {
    System.out.println("host = " + host);
    return "success";
}

5、@CookieValue

作用:將cookie資料控制器方法的形參建立對映關係

@RequestMapping("/testParam")
public String testParam(@CookieValue("JSESSIONID") String JSESSIONID) {
    System.out.println("JSESSIONID = " + JSESSIONID);
    return "success";
}

6、通過POJO獲取

前提:當瀏覽器傳輸的請求引數的引數名實體類中的屬性名一致,那麼請求引數就會為此賦值

@RequestMapping("/testBean")
public String testBean(User user) {
    System.out.println(user);
    return "success";
}
//User{id=null, username='張三', password='123', age=23, sex='男'}

7、解決亂碼問題

Tomcat8中,GET請求的編碼預設為UTF-8

為解決POST請求中亂碼問題,要在web.xml檔案中註冊CharacterEncodingFilter

編碼過濾器一定要配置到其他過濾器之前,否則無效

<!-- 配置springMVC的編碼過濾器 -->
<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>
    <init-param>
        <param-name>forceResponseEncoding</param-name>
        <param-value>true
        </param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

五、域物件共享資料

(一)Request域物件

1、使用ServletAPI

@RequestMapping("/testServletAPI")
public String testRequestByServletAPI(HttpServletRequest request) {
    request.setAttribute("testRequestScope", "Hello ServletAPI");
    return "success";
}

2、使用ModelAndView

@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
    ModelAndView mav = new ModelAndView();
    //共享資料
    mav.addObject("testRequestScope", "Hello ModelAndView");
    //設定檢視,實現頁面跳轉
    mav.setViewName("success");
    return mav;
}

3、使用Model

@RequestMapping("/testModel")
public String testModel(Model model) {
    model.addAttribute("testRequestScope", "Hello Model");
    return "success";
}

4、使用Map

@RequestMapping("/testMap")
public String testMap(Map<String, Object> map) {
    map.put("testRequestScope", "Hello Map");
    return "success";
}

5、使用ModelMap

@RequestMapping("/testModelMap")
public String testModelMap(ModelMap modelMap) {
    modelMap.addAttribute("testRequestScope", "Hello ModelMap");
    return "success";
}

6、補充

  1. 以上5種共享資料的方法,返回值最後都被DispatcherServlet封裝成了ModelAndView物件
  2. Model、ModelMap、Map的關係

(二)Session域物件

@RequestMapping("/testSession")
public String testSession(HttpSession session) {
    session.setAttribute("testSessionScope", "Hello Session");
    return "success";
}

(三)Application域物件

@RequestMapping("/testApplication")
public String testApplication(HttpSession session) {
    ServletContext application = session.getServletContext();
    application.setAttribute("testApplicationScope", "Hello Application");
    return "success";
}

六、檢視

檢視的作用:渲染資料,將Model中的資料展示給使用者

SpringMVC中的檢視是view檢視

(一)ThymeleafView

當控制器方法所設定的檢視名稱沒有任何字首時,最終會被處理成ThymeleafView,並轉發

DispatcherServlet --> processDispatchResult
					 --> render 
						--> resolveViewName

(二)轉發檢視

SpringMVC中預設的轉發檢視InternalResourceView

當控制器方法所設定的檢視名稱以“ forward: ”為字首時,建立InternalResourceView檢視,此時的檢視名稱不會被解析,而是會將字首去掉,剩餘部分作為最終路徑通過轉發的方式實現跳轉

(三)重定向檢視

SpringMVC中預設的重定向檢視RedirectView

當控制器中所設定的檢視名稱以“ redirect: ”為字首時,建立RedirectView檢視,此時的檢視名稱不會被解析,而是會將字首去掉,剩餘部分作為最終路徑通過重定向的方式實現跳轉,若剩餘部分以 / 開頭,則會自動拼接上下文路徑

(四)檢視控制器

當控制器方法中,僅僅用來實現頁面跳轉,可以進行如下設定

<!-- 
	path:設定處理的請求地址
	view-name:設定請求地址所對應的檢視名稱
-->
<mvc:view-controller path="/" view-name="index"/>
<mvc:annotation-driven/>

注:

當存在以上設定時,其他控制器中的請求對映將全部失效

此時需要在SpringMVC核心配置檔案中設定開啟mvc註解驅動

<mvc:annotation-driven/>

七、RESTful

(一)簡介

REST:Representational State Transfer,表現層資源狀態轉移

(二)實現

通過HTTP協議裡面的四種請求:GET、POST、PUT、DELETE

它們分別對應四種基本操作:GET—獲取資源,POST—新建資源,PUT—更新資源,DELETE—刪除資源

操作 傳統方式 REST風格
查詢 getUserById?id=1 user/1,GET
儲存 saveUser user,POST
刪除 deleteUser?id=1 user/1,DELETE
更新 updateUser user,PUT

(三)HiddenHTTPMethodFilter

通過HiddenHttpMethodFilter過濾器,可以將POST請求轉換為DELETE請求或PUT請求

轉化條件

​ ❶當前請求的 請求的方式 必須為post

​ ❷設定請求中的 引數『_method』 (=put/delete)

在web.xml檔案中註冊

<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

(四)刪除案例

思路:超連結通過繫結點選事件,控制form表單

<a @click="deleteEmployee" th:href="@{|/employee/${employee.id}|}">delete</a>

<form id="deleteForm" method="post">
    <input type="hidden" name="_method" value="delete">
</form>
<script type="text/javascript">
    var vue = new Vue({
        el: "#dataTable",
        methods: {
            deleteEmployee: function (event) {
                var deleteForm = document.getElementById("deleteForm");
                deleteForm.action = event.target.href;
    			//提交表單
                deleteForm.submit();
    			//阻止超連結的跳轉行為
                event.preventDefault();
            }
        }
    });
</script>

八、HttpMessageConverter

HttpMessageConverter,報文資訊轉換器

將請求報文轉換為Java物件,或將Java物件轉換為響應報文

(一)@RequestBody

@RequestBody可以獲取請求體

需要在控制器方法設定一個形參,使用註解標識,當前請求的請求體就會對引數自動賦值

@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String requestBody) {
    System.out.println(requestBody);
    //username=admin&password=123
    return "success";
}

(二)RequestEntity

RequestEntity封裝報文的一種型別

需要在控制器方法的形參中設定該型別的形參,當前請求報文就會賦值給該形參

@RequestMapping("/testRequestEntity")
public String testRequestEntity(RequestEntity<String> requestEntity) {
    System.out.println("請求頭 = " + requestEntity.getHeaders());
    System.out.println("請求體 = " + requestEntity.getBody());
    return "success";
}

(三)@ResponseBody

@ResponseBody用於標識一個控制器方法

可以將該方法的返回值直接作為響應報文的響應體響應到瀏覽器

@RequestMapping("/testResponseBody")
@ResponseBody
public String testResponseBody() {
    return "success";
}

1、處理json

匯入依賴

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.1</version>
</dependency>

開啟註解驅動

<mvc:annotation-driven />

註解標識控制器

//將java物件直接返回,會自動轉換為json格式的字串
@RequestMapping("/testResponseUser")
@ResponseBody
public User testResponseUser() {
    return new User(1001, "admin", "123", 15, "male");
}

2、處理ajax

請求超連結

<div id="app">
    <a th:href="@{/testAjax}" @click="testAjax">SpringMVC處理ajax</a>
</div>

vue和axios處理點選事件

<script type="text/javascript">
    var vue = new Vue({
        el:"#app",
        methods:{
            testAjax:function (event) {
                axios({
                    method:"post",
                    url:event.target.href,
                    params:{
                        username:"admin",
                        password:"12345"
                    }
                }).then(function (response) {
                    alert(response.data);
                });
                event.preventDefault();
            }
        }
    });
</script>

控制器方法

@RequestMapping("/testAjax")
@ResponseBody
public String testAjax(String username, String password) {
    System.out.println("username = " + username);
    System.out.println("password = " + password);
    return "Hello Ajax";
}

(四)@RestController

@RestController註解是一個複合註解,可以作用在控制器中

作用:相當於給控制器添加了@Controller註解,並且為其中的所有方法添加了@ResponseBod註解

(五)ResponseEntity

用於控制器方法的返回值型別,該方法的返回值就是響應到瀏覽器的響應報文

1、檔案下載

@RequestMapping("/testDown")
public ResponseEntity<byte[]> testDown(HttpSession session) throws IOException {
    //獲取ServletContext物件
    ServletContext servletContext = session.getServletContext();
    //獲取伺服器中檔案的真實路徑
    String realPath = servletContext.getRealPath("/static/img/1.png");
    //建立輸入流
    FileInputStream is = new FileInputStream(realPath);
    //建立位元組陣列
    byte[] bytes = new byte[is.available()];
    //讀取資料到位元組陣列中
    is.read(bytes);
    //建立HttpHeader物件設定響應頭資訊
    MultiValueMap<String, String> headers = new HttpHeaders();
    //設定下載方式和檔名字
    headers.add("Content-Disposition", "attachment;filename=1.png");
    //設定響應狀態碼
    HttpStatus statusCode = HttpStatus.OK;
    //建立ResponseEntity物件
    ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
    is.close();
    return responseEntity;
}

2、檔案上傳

新增依賴

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

註冊檔案解析器

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

頁面表單

<form th:action="@{/testUp}" method="post" enctype="multipart/form-data">
    <input type="file" name="photo">
    <input type="submit" value="上傳">
</form>

控制器方法

@RequestMapping("/testUp")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
    //獲取上傳的檔名
    String fileName = photo.getOriginalFilename();
    //獲取檔案字尾名
    String suffixName = fileName.substring(fileName.lastIndexOf("."));
    //處理檔案重名問題
    fileName = UUID.randomUUID().toString() + suffixName;
    //獲取伺服器中photo目錄的路徑
    ServletContext servletContext = session.getServletContext();
    String photoPath = servletContext.getRealPath("photo");
    File file = new File(photoPath);
    if (!file.exists()) {
        file.mkdir();
    }
    String finalPath = photoPath + File.separator + fileName;
    //實現上傳
    photo.transferTo(new File(finalPath));
    return "success";
}

九、攔截器

作用:攔截控制器方法的執行

(一)配置

❶建立一個類,實現HandlerInterceptor介面,重寫三個方法

❷在SpringMVC配置檔案中進行配置

<mvc:interceptors>
    <!-- 對DispatcherServlet所處理的所有請求進行攔截 -->
    <ref bean="firstInterceptor"/>
    <bean class="com.atguigu.mvc.interceptors.FirstInterceptor"/>
   	<!-- 
 		mvc:mapping  設定需要攔截的請求
		mvc:exclude-mapping  設定不需要攔截的請求
	-->
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/"/>
        <ref bean="firstInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

(二)三個抽象方法

preHandle

​ 執行時間:控制器執行之前

​ 說明:返回true,放行;返回false,攔截

postHandle

​ 執行時間:控制器執行之後

afterCompletion

​ 執行時間:渲染檢視完畢之後

(三)執行順序

若每個攔截器的preHandle都返回true

​ preHandle:按照配置的 順序 執行

​ postHandler:按照配置順序的 反序 執行

​ afterCompletion:按照配置順序的 反序 執行

若某個攔截器(A)的preHandle返回了false

​ preHandler:攔截器A之前,包括A,都會執行

​ postHandler:一個都不會執行

​ afterCompletion:攔截器A之前,不包括A,都會執行

十、異常處理器

SpringMVC提供了一個處理控制器方法執行過程中所出現的異常介面:HandlerExceptionResolver

HandlerExceptionrResolver介面的實現類有DefaultHandlerExceptionResolverSimpleMappingExceptionResolver

SpringMVC提供了自定義的異常處理器SimpleMappingExceptionResolver

(一)基於配置

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <!--
                property的鍵表示處理的異常
                property的值表示出現異常時,跳轉的檢視名稱
            -->
            <prop key="java.lang.ArithmeticException">error</prop>
        </props>
    </property>
    <!-- 將異常資訊共享在請求域中 -->
    <property name="exceptionAttribute" value="ex"/>
</bean>

(二)基於註解

@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler(value = {ArithmeticException.class, NullPointerException.class})
    public String testException(Exception exception, Model model) {
        model.addAttribute("ex", exception);
        return "error";
    }
}

十一、完全註解配置

使用配置類和註解代替web.xml和SpringMVC配置檔案的功能

(一)代替web.xml

public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {

    //指定spring的配置類
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    //指定springMVC的配置類
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    //指定DispatcherServlet的對映規則,即url-pattern
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    //新增過濾器
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceResponseEncoding(true);
        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
        return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter};
    }
}

(二)代替MVC配置檔案

/**
 * 代替SpringMVC的配置檔案
 * 1、掃描元件  2、檢視解析器  3、view-controller  4、default-servlet-handler
 * 5、mvc註解驅動  6、檔案上傳解析器  7、異常處理  8、攔截器
 */
@Configuration
//1、掃描元件
@ComponentScan("com.atguigu.mvc.controller")
//5、mvc註解驅動
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    //3、view-controller
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello").setViewName("hello");
    }

    //4、default-servlet-handler
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    //6、檔案上傳解析器
    @Bean
    public CommonsMultipartResolver multipartResolver() {
        return new CommonsMultipartResolver();
    }

    //7、異常處理
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
        Properties prop = new Properties();
        prop.setProperty("java.lang.ArithmeticException", "error");
        exceptionResolver.setExceptionMappings(prop);
        exceptionResolver.setExceptionAttribute("ex");
        resolvers.add(exceptionResolver);
    }

    //8、攔截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        FirstInterceptor firstInterceptor = new FirstInterceptor();
        registry.addInterceptor(firstInterceptor).addPathPatterns("/**");
    }

    //2、檢視解析器
    //2.1、配置生成模板解析器
    @Bean
    public ITemplateResolver templateResolver() {
        WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext());
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }
    //2.2、生成模板引擎併為模板引擎引入模板解析器
    @Bean
    public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        return templateEngine;
    }
    //2.3、生成檢視解析器併為解析器注入模板引擎
    @Bean
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setCharacterEncoding("UTF-8");
        viewResolver.setTemplateEngine(templateEngine);
        return viewResolver;
    }
}

十二、MVC執行流程

(一)常用元件

  • DispatcherServlet:前端控制器(框架提供)

    作用:統一處理請求和響應,整個流程控制的中心,由它呼叫其他元件處理使用者請求

  • HandlerMapping:處理器對映器(框架提供)

    作用:根據請求的url、method等資訊查詢Handler

  • Handler:處理器

    作用:在DispatcherServlet的控制下,對具體的使用者請求進行處理

  • HandlerAdapter:處理器介面卡(框架提供)

    作用:對處理器(控制器方法)進行執行

  • ViewResolver:檢視解析器(框架提供)

    作用:進行檢視解析,得到相應的檢視,例如ThymeleafView、InternalResourceView、

    RedirectView

  • View:檢視

    作用:將模型資料通過頁面展示給使用者

(二)執行流程