SpringMVC学习之路
本篇文章记录于尚硅谷学习!!!
一、SpringMVC简介
1.1 什么是MVC
MVC是一种软件架构的思想,将软件按照模型、视图、控制器划分
M:指的是Model层(模型层),指的是工程里的JavaBean。
JavaBean分两类:
- 实体类Bean:存储业务数据
- 业务处理Bean:Service或者Dao对象
V: 视图层, 指的是前端显示界面,与用户交互的
C: Controller、控制层,指的是工程中的Servlet,作用是请求和响应服务器
MVC的工作流程:
用户通过视图层发送请求到服务器,服务器中的请求被Controller接收,C调用响应的Model层处理请求,将结果返回给C,然后C在将结果传给View层,进行渲染。
二、HolleWord
2.1 创建Maven工程,引入依赖
引入的依赖如下:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.13</version>
</dependency>
2.2 配置web.xml
注意/与/*的区别
/:不匹配jsp
/*匹配所有文件
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<!--配置SpringMVC的前端控制器,对浏览器发送的请求进行统一处理-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--配置SpringMVC的配置文件的位置和名称-->
<init-param>
<param-name>contextConfigLocation</param-name>
<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>
<!--注意/与/*的区别-->
<!-- /:不匹配jsp。 /*匹配所有文件 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2.3 创建请求控制器
配置@Controller
在配置文件中配置包扫描注解
package com.jzq.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
// 通过注解标识 (bean)
@Controller
public class HelloController {
@RequestMapping(value = "/")
public String index() {
// 返回视图的名称
return "index";
}
@RequestMapping(value = "/page1")
public String page1() {
return "page1";
}
}
配置文件
<?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: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">
<!-- 配置扫描组件 -->
<context:component-scan base-package="com.jzq.mvc.controller"></context:component-scan>
<!-- 配置视图解析器 -->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"></property>
<property name="characterEncoding" value="UTF-8"></property>
<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>
<!-- 视图后缀 -->
<property name="suffix" value=".html"></property>
<property name="templateMode" value="HTML 5"></property>
<property name="characterEncoding" value="UTF-8"></property>
</bean>
</property>
</bean>
</property>
</bean>
</beans>
三、@RequestMapping注解
3.1 @RequestMapping注解的功能
@RequestMapping的功能是将请求和处理请求的控制器方法关联起来,建立映射关系。
3.2 @RequestMapping注解的位置
- 标识一个类: 设置映射请求的请求路径的初始信息
- 表示一个方法: 色湖之映射请求的请求路径的具体信息
3.3 @RequestMapping注解的value属性
@RequestMapping注解的value属性是:请求地址匹配请求映射
@RequestMapping注解的value属性是:一个字符串类型的数组,表示该请求映射能够匹配的多个地址所对应的请求。
@RequestMapping注解的value属性必须设置。至少一个!
3.4 @RequestMapping注解的method属性
@RequestMapping注解的method: 通过请求的方式
@RequestMapping注解的method是一个RequestMethod类型的数组,也可以匹配多个请求。
@RequestMapping(value = {"/page1","/page2"}, method = {RequestMethod.GET, RequestMethod.POST})
public String page1() {
return "page1";
}
- 对于处理指定的请求方式的控制器方法,SpringMVC提供了@RequestMapping的派生注解
处理GET:@GetMapping
处理POST:@PostMapping
。。。- 目前浏览器只支持,post,get。
发送其他请求,例如put时, 需要通过Spring提供的过滤器HiddenHttpMethodFilter,在restful时。
3.5@RequestMapping注解的params属性
携带参数
“param”: 表示请求映射所匹配的params必须携带param请求参数
“!param”: 表示请求映射所匹配的params必须不能携带param请求参数
“param=value”: 表示请求映射所匹配的params必须携带param请求参数,并且等于value
“param!=value”: 表示请求映射所匹配的params必须携带param请求参数,但是不能等于value
@GetMapping
@RequestMapping(value = {"/page1","/page2"}, params = "username!=12")
public String page1() {
return "page1";
}
3.5@RequestMapping注解的headers属性
携带请求头
“header”: 表示请求映射所匹配必须携带header请求参数
“!header”: 表示请求映射所匹配必须不能携带header请求参数
“header=value”: 表示请求映射所匹配必须携带header请求参数,并且等于value
“header!=value”: 表示请求映射所匹配必须携带header请求参数,但是不能等于value
如果当前的@RequestMapping注解的满足value和method,但是不满足headers属性,此时页面报404,资源未找到!
3.6 SpringMVC支持ant风格的路径
? : 表示任意单个字符串
*:表示任意的0个或者多个字符
:表示任意的一层或多层目录
注意 使用时,只能用/**/xxx的方式
3.7 SpringMVC支持路径中的占位符
原始方式:/add?user=123
restful: /add/123
SpringMVC路径中的占位符经常用于restful风格中,通过 占位符{xxx} 占位,表示传输的数据,再通过@PathVariable注解,将占位符表示的数据赋值给控制器方法的形参。
@GetMapping
@RequestMapping(value = {"/page1","/page2/{id}"})
public String page1(@PathVariable("id") String id) {
System.out.println("id:"+id);
return "page1";
}
四、SpringMVC获取请求参数
4.1 通过ServletAPI获取
@RequestMapping("/param")
public String param(HttpServletRequest httpServletRequest) {
System.out.println(httpServletRequest.getParameter("name"));
return "param";
}
4.2 通过控制器方法的形参获取请求参数
在控制器方法中设置和请求参数同名的形参,当浏览器发送请求的时候,匹配到请求映射时,在DispatcherServlet中就将会将请求参数赋值给相应的形参。
@RequestMapping("/param2")
public String param2(String name) {
System.out.println(name);
return "param";
}
4.3 @RequestParam
此注解一共三个属性
value: 指定形参赋值时请求参数名。
required:设置是否必须传送该请求参数, 默认为true,必须传送,不传报400。
defaulValue:不管是否设置了required,当value没传送时,默认为这个值。
4.4 @RequestHeader
该注解是将请求头信息和控制器方法的形参创建映射关系。 (获取token)
属性同 @RequestParam的一致。
4.5 @CookieValue
该注解是将cookie和控制器方法的形参创建映射关系。
属性同 @RequestParam的一致。
4.6 获取参数直接为实体类
传的参数名字一致的和控制器方法的实体类参数名一样的进行映射。
@RequestMapping("/param3")
public String param3(
User user
) {
System.out.println(user);
return "param";
}
五、域对象共享数据
5.1 使用servletAPI向request域对象共享数据
@RequestMapping("/param")
public String param(HttpServletRequest httpServletRequest) {
System.out.println(httpServletRequest.getParameter("name"));
httpServletRequest.setAttribute("name", httpServletRequest.getParameter("name"));
return "param";
}
5.2 使用ModelAndView向request域对象共享数据
ModelAndView 包括了 Model: 数据 , View: 视图
addObject(“健”, “值”) 设置数据
setviewName(“页面”) 设置请求页面
@RequestMapping("/param4")
public ModelAndView param3(@RequestParam("name") String name) {
/**
* ModelAndView 包括了 Model: 数据 , View: 视图
* addObject("健", "值") 设置数据
* setviewName("页面") 设置请求页面
*/
ModelAndView mav = new ModelAndView();
mav.addObject("name", name);
mav.setViewName("param");
return mav;
}
5.3 使用Model向request域对象共享数据
@RequestMapping("/param5")
public String param5(Model model, @RequestParam("name") String name) {
model.addAttribute("name", name);
return "param";
}
5.4 使用map向request域对象共享数据
@RequestMapping("/param6")
public String param6(Map<String, Object> map, @RequestParam("name") String name) {
map.put("name", name);
return "param";
}
5.5 使用ModelMap向request域对象共享数据
@RequestMapping("/param7")
public String param7(ModelMap modelMap, @RequestParam("name") String name) {
modelMap.addAttribute("name", name);
return "param";
}
5.6 向session域共享数据
@RequestMapping("/param8")
public String param8(HttpSession httpSession, @RequestParam("name") String name) {
httpSession.setAttribute("name", name);
return "param";
}
5.7 向application域共享数据
@RequestMapping("/param9")
public String param9(HttpSession httpSession, @RequestParam("name") String name) {
ServletContext application = httpSession.getServletContext();
application.setAttribute("name", name);
return "param";
}
六、 SpringMVC的视图
6.1 转发视图
⭐ 请求的视图
此时的请求带了参数: httpServletRequest.setAttribute(“name”, “大傻子”);
@GetMapping
@RequestMapping(value = {"/page1","/page2/{id}"})
public String page1(HttpServletRequest httpServletRequest) {
//System.out.println("id:"+id);
httpServletRequest.setAttribute("name", "大傻子");
return "forward:/api/param";
}
⭐ 被转发的视图
转发的视图通过httpServletRequest.getAttribute(“name”)能够取到数据
@RequestMapping("/param")
public String param(HttpServletRequest httpServletRequest) {
System.out.println(httpServletRequest.getAttribute("name"));
httpServletRequest.setAttribute("name", httpServletRequest.getAttribute("name"));
return "param";
}
6.2 重定向视图
SpringMVC中默认的重定向视图为 RedirectView
当控制器方法中设置的视图名称为"redirect:"为前缀的时候,创建RedirectView视图,此时的视图名称不会被SpringMVC配置文件中配置的视图解析器解析,而是将前缀"redirect:"去掉,剩余的部分作为路径通过重定向的方式实现跳转
⭐ 请求的视图
此时的请求带了参数: httpServletRequest.setAttribute(“name”, “大傻子”);
@GetMapping
@RequestMapping(value = {"/page1","/page2/{id}"})
public String page1(HttpServletRequest httpServletRequest) {
//System.out.println("id:"+id);
httpServletRequest.setAttribute("name", "大傻子");
return "redirect:/api/param";
}
⭐ 重定向的视图
重定向的视图是一个新的请求,由服务器发出,取不到数据
@RequestMapping("/param")
public String param(HttpServletRequest httpServletRequest) {
System.out.println(httpServletRequest.getAttribute("name"));
httpServletRequest.setAttribute("name", httpServletRequest.getAttribute("name"));
return "param";
}
6.3 视图控制器view-controller
当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用view-controller标签进行表示
path : 设置处理的请求地址
view-name: 设置请求地址所对应的视图名称
⭐在springMVC.xml中配置
<!-- 配置视图控制器 -->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
⭐设置mvc注解驱动的标签(在springMVC.xml中配置)
⭐ 当SpringMVC中设置任何一个view-controller时,其他的控制器的请求映射将全部失效,此时需要在SpringMVC的核心配置文件中设置mvc注解驱动的标签
<!-- 开启MVC的注解驱动 -->
<mvc:annotation-driven/>
七、 RESTFul请求 和静态资源处理
7.1 HiddenHttpMethodFilter
由于浏览器只发送get和post请求。
SpringMVC提供了HiddenHttpMethodFilter帮助我们将POST转换成DELETE或PUT请求。
处理条件: 1. 当前请求方式必须为post, 当前请求必须传送亲求参数_method
(⭐)当然这不包括ajax,只是页面请求的form
<from method="post" action="路径">
!!!必须包括
<input type="hidden" name="_method" value="PUT">
</from>
⭐ 处理put或者delete的xml配置
加入有编码过滤器,一定放在编码过滤器的下面
<!-- 配置HiddenHttpMethodFilter -->
<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>
7.2 静态资源处理
开启对静态资源的访问,<mvc:default-servlet-handler/>
注意必须和MVC的注解驱动一块使用
<!--开放对静态资源的访问-->
<mvc:default-servlet-handler/>
<!-- 开启MVC的注解驱动 -->
<mvc:annotation-driven/>
八、 HttpMessageConverter
HttpMessageConverter, 报文信息转换器, 将请求报文转换为java对象,或将java对象转化为响应报文。
HttpMessageConverter提供了两个注解和两个类型: @RequestBody,@ResponseBody,RquestEntity,ResponseEntity
8.1 @RequestBody
@RequestBody可以获取请求体,需要在控制器方法设置一个形参,使用@RequestBody进行标识,当前请求的请求体就会为当前所标识的形参赋值
@RequestMapping(value = {"/requestbody"})
public String page2(@RequestBody String requestBody) {
System.out.println("requestBody:"+requestBody);
return "page1";
}
8.2 RequestEntity
RequestEntity封装请求报文的一种类型,需要在控制器方法的形参中设置该类型的形参,当前请求的请求报文就慧赋值给该形参,通过getHeaders()获取请求头信息,通过getBody()获取请体信息。
@RequestMapping(value = {"/requestbody2"})
public String page3(RequestEntity<String> requestEntity) {
System.out.println("requestH:"+requestEntity.getHeaders());
System.out.println("requestB:"+requestEntity.getBody());
return "page1";
}
8.3 @ResponseBody(最常用)
@ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器
@RequestMapping(value = {"/requestbody3"})
@ResponseBody
public String page4() {
return "page1";
}
页面结果显示: page1
8.4 @ResponseBody响应json(SpringMVC处理)
@ResponseBody处理json的步骤:
- 添加jackson依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
- 在SpringMVC的核心配置文件中开启mvc的注解驱动,此时在HandlerAdaptor中会自动装配一个消息转换器:Mappinggiackson2HttpMessageConverter,可以将响应到浏览器的Java对象转换成json格式的字符串
<!-- 开启MVC的注解驱动 -->
<mvc:annotation-driven/>
- 在处理器方法上使用@ResponseBody注解
- 将java对象直接作为控制器方法的返回值进行返回,就会自动转换为json格式的字符串
@RequestMapping(value = {"/requestbody4"})
@ResponseBody
public User page5() {
return new User("急啊急啊就", "dasa", 15);
}
8.5 @RestController注解
@RestController注解 是SpringMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解
8.6 ResponseEntity
ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文。
九、文件下载
有一点问题的代码,后期解决,postman的时候打不通
在springMVC的配置文件内配置文件上传解析器
<!-- 配置文件上传解析器,将上传的文件封装成MultipartFile -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
只在配置文件配置往往找不到bean, 需要配置jar, 在pom中引入commons-fileuploa
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
代码逻辑
@RequestMapping("/upload")
@PostMapping
@ResponseBody
public Map<String, String> upload(MultipartFile multipartFile, HttpSession httpSession) throws IOException {
// 获取文件的名字
System.out.println("这是说的啥好的稍等哈是");
// 这里有问题,postman跑不动
String fileName = multipartFile.getOriginalFilename();
System.out.println("ffffffffffffff"+fileName);
// 获取项目路径
ServletContext servletContext = httpSession.getServletContext();
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
// 判断是否存在路径
if(!file.exists()) {
// 路径不存在,创建路径
file.mkdir();
}
// 最终文件保存路径(文件路 + 文件分隔符/(linux)或者\(win) + 文件名)
String finalPath = photoPath + File.separator + fileName;
multipartFile.transferTo(new File(finalPath));
Map<String, String> result = new HashMap<>();
result.put("msg", "添加成功");
result.put("data", finalPath);
return result;
}
十、 拦截器
10.1 拦截器配置
SpringMVC 中的拦截器用于拦截控制器方法的执行
SpringMVC 中的拦截器需要实现HandlerInterceptor或者是继承HandlerInterceptorAdapter类(过时)
SpringMVC 的拦截器必须在SpringMVC的配置文件中配置
⭐所有请求都会被拦截
<!-- 配置拦截器 -->
<mvc:interceptors>
<!--<bean class="com.jzq.mvc.interceptors.FirstInterceptors"></bean>-->
<ref bean="firstInterceptors"/>
</mvc:interceptors>
⭐ 指定拦截器
<mvc:mapping> : 设置被拦截的请求
<mvc:exclude-mapping: 设置不需要被拦截得路由
<!-- 配置拦截器(配置请求) -->
<mvc:interceptors>
<mvc:interceptor>
<!-- /* 标识一级目录 /** 标识多级目录 -->
<mvc:mapping path="/*"/>
<!-- 不被拦截得路由 -->
<mvc:exclude-mapping path="/index"/>
<ref bean="firstInterceptors"/>
</mvc:interceptor>
</mvc:interceptors>
10.2 拦截器的三个抽象方法
SpringMVC中的拦截器有三个抽象方法:
preHandle: 控制器方法执行之前执行preHandle(), 其中boolean类型的返回值表示拦截或者放行,true:放行;false:拦截(不调用控制器方法)。
postHandle:控制器方法执行之后执行postHandle()
afterCompletion: 处理完视图和模型数据,渲染视图完毕之后执行afterCompletion()
package com.jzq.mvc.interceptors;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FirstInterceptors implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
10.3 多个拦截器的执行顺序
⭐如果每个拦截器的preHandle()都返回true;
此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关。
preHandle()会按照配置的顺序执行,而postHandle()和afterComplation()会按照配置的反顺序执行。
⭐如果每个拦截器的preHandle()都返回false;
preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回fasle的拦截器之前的拦截器的afterComplation()会执行。
十一、异常处理器
11.1 基于配置的异常处理
SpringMVC提供了一个处理控制器方法执行过程中出现的异常的接口:HandlerExceptionResover。
HandlerExceptionResover的实现类有DefaultHandlerExceptionResover和SimpleMappingExceptionResover
⭐SimpleMappingExceptionResover的使用方式:
<!-- 配置异常处理 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--
properties的健表示处理器方法执行过程中出现的异常
properties的值表示若出现指定异常时,设置一个新的视图名称(被视图解析器解析),跳转到指定界面
-->
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
<!-- 设置将异常信息共享在请求域(可以取到) -->
<property name="exceptionAttribute" value="ex"></property>
</bean>
11.2 基于注解的异常处理
@ControllerAdvice标识类
@ExceptionHandler(value = {ArithmeticException.class, NullPointerException.class}):标识方法,传入异常类,在方法中写处理逻辑
可以通过参数Exception ex获取异常信息,在携带信息(这里用的Model)给转发界面
package com.jzq.mvc.controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(value = {ArithmeticException.class, NullPointerException.class})
public String testException(Exception ex, Model model){
model.addAttribute("ex", ex);
return "error";
}
}
十二、 注解配置SpringMVC
12.1 创建初始化类, 代替web.xml
getRootConfigClasses : 指定spring的配置类
getServletConfigClasses: 指定SpringMVC的配置类
getServletMappings: 指定DispatcherServlet的映射规则,即url-pattern
getServletFilters: 注册过滤器
package com.jzq.mvc.config;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import javax.servlet.Filter;
// web工程的初始化类,用来代替web.xml
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* 指定spring的配置类
* @return
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
/**
* 指定SpringMVC的配置类
* @return
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
/**
* 指定DispatcherServlet的映射规则,即url-pattern
* @return
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
/**
* 注册过滤器
* @return
*/
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceResponseEncoding(true);
// 配置HiddenHttpMethodFilter
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[] {characterEncodingFilter, hiddenHttpMethodFilter};
}
}
12.2 代替SpringMCV.xml的配置类
分别代替的方法如下java
- 扫描组件
- 视图解析器
- view-controller
- default-servlet-handler
- mvc注解驱动
- 文件上传解析器
- 异常处理
- 拦截器
package com.jzq.mvc.config;
import com.jzq.mvc.interceptors.FirstInterceptors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import java.util.List;
import java.util.Properties;
/**
* 代替SpringMVC的配置文件
* 1. 扫描组件
* 2. 视图解析器
* 3. view-controller
* 4. default-servlet-handler
* 5. mvc注解驱动
* 6. 文件上传解析器
* 7. 异常处理
* 8. 拦截器
*/
// 将当前类标识为配置类
@Configuration
// 1.扫描组件
@ComponentScan("com.jzq.mvc.controller")
// 5. mvc注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
//3. view-controller
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/index").setViewName("index");
}
// 4. default-servlet-handler
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
// 6. 文件上传解析器
@Bean
public MultipartResolver multipartResolver(){
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
return commonsMultipartResolver;
}
// 7. 异常处理
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
Properties properties = new Properties();
/**
* 键是 异常类型
* 值是 页面名
*/
properties.setProperty("java.lang.ArithmeticException", "error");
simpleMappingExceptionResolver.setExceptionMappings(properties);
simpleMappingExceptionResolver.setExceptionAttribute("exception");
resolvers.add(simpleMappingExceptionResolver);
}
// 8. 拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加拦截器并设置路径
FirstInterceptors firstInterceptors = new FirstInterceptors();
registry.addInterceptor(firstInterceptors).addPathPatterns("/**");
}
}
十三、SpringMVC执行流程
13.1 SpringMVC常用组件
13.2 DispatcherServlet初始化过程
DispatcherServlet本质就是一个Servlet,所以天然的遵守Servlet的生命周期。所以宏观上是Servlet的生命周期来调度。
⭐ 步骤流程
⭐ a. 初始化 WebApplicationContext
略
⭐ b. 创建 WebApplicationContext
⭐ c. DispatherServlet初始化策略
FrameworkServlet创建WebApplicationContext后,刷新容器,调用onRefresh(wac), 此方法在DispatherServlet中进行了重写,调用了initStrategies(ApplicationContext context),初始化策略,即初始DispatherServlet的各个组件
所在类为org.springframework.web.servlet.DispatherServlet
protected void initStrategies(ApplicationContext context) {
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
13.3 DispatcherServlet调用组件处理请求
⭐ a. processRequest()
FrameworkServlet重写HtppSrvlet中的service()和doXXX(), 这些方法中调用了processRequest(request, response)
所在类 org.springframework.web.servlet.FrameworkServlet
⭐ b. doService()
所在类 org.springframework.web.servlet.DispatcherServlet
⭐ c. doDispatch()
所在类 org.springframework.web.servlet.DispatcherServlet
13.4 SpringMVC的执行流程