文章目录

  • 一 SpringMVC 简介
    • 1 MVC
    • 2 SpringMVC
    • 3 创建第一个 SpringMVC 项目
  • 二 @RequestMapping
    • 1 注解类与方法的区别
    • 2 value 属性
    • 3 method 属性
    • 4 params 属性
    • 5 headers 属性
    • 6 SpringMVC 支持路径中的占位符
  • 三 获取 Request 的一系列参数
    • 1 通过控制器方法的形参
    • 2 控制器方法形参 映射 Request 参数 - @RequestParam
    • 3 控制器方法形参 映射 Request 请求头 - @RequestHeader
    • 4 控制器方法形参 映射 cookie数据 - @CookieValue
    • 5 通过 POJO 获取 Request 参数
    • 6 解决获取参数的乱码问题
  • 四 域对象共享数据
    • 1 使用 ServletAPI 向 request 域对象共享数据(不建议)
    • 2 使用 ModelAndView 向 request 域对象共享数据
    • 3 使用 Model 向 request 域对象共享数据
    • 4 使用 Map 向 request 域对象共享数据
    • 5 使用 ModelMap 向 request 域对象共享数据
    • 6 使用 ServletAPI 向 Session 域对象共享数据
    • 7 使用 ServletAPI 向 Application 域对象共享数据
  • 五 SpringMVC 视图
    • 1 Thymeleaf 视图
    • 2 转发视图
    • 3 重定向视图
    • 4 使用 view-controller 代替 控制器方法
  • 六 RESTful
  • 七 HttpMessageConverter
    • 1 @RequestBody
    • 2 RequestEntity
    • 3 @ResponseBody
    • 4 ResponseEntity
    • 5 RestController
  • 八 拦截器
    • 1 配置方法
    • 2 HandlerInterceptor 接口的三个方法
    • 3 多个拦截器的执行顺序
  • 九 异常处理器
    • 1 基于配置
    • 2 基于注解
  • 十 使用注解配置 SpringMVC
    • 1 初始化类:代替 web.xml
    • 2 SpringConfig 类:代替 Spring 配置文件(略)
    • 3 WebConfig 类:代替 SpringMVC 配置文件
  • 十一 SpringMVC 执行流程
    • 1 常用组件
    • 2 流程总结

一 SpringMVC 简介

1 MVC

  • Model 模型层:工程中的 JavaBean,包含实体 Bean(Customer、Student…) 和 业务处理 Bean(Service、DAO)
  • View 视图层:指工程中的 html 或 jsp 等页面,与用户进行交互,展示数据
  • Controller 控制层:指工程中的 servlet,作用是接收请求和响应浏览器
  • MVC 的工作流程 View <—> Controller <—> Model :用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller 调用相应的 Model 层处理请求,处理完毕将结果返回到 Controller,Controller 再根据请求处理的结果找到相应的 View 视图,渲染数据后最终响应给浏览器

2 SpringMVC

  • 是 Spring 的子项目
  • 主要作用是在 Spring 项目中进行表述层开发(是三层架构中的概念,三层架构:表述层(或表示层)、业务逻辑层、数据访问层,表述层表示前台页面和后台 servlet)

3 创建第一个 SpringMVC 项目

目录结构如下

  1. 配置 maven 依赖,这里遇到了一个奇怪的版本问题
    <dependencies><!-- SpringMVC --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.9</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.11.RELEASE</version></dependency></dependencies>
  1. 配置 web.xml 的 Servlet 及 mapping
    <!--注册springMVC的前端控制器,对浏览器所发送的请求统一进行处理在此配置下,springMVC的配置文件具有默认的位置和名称默认的位置:WEB-INF默认的名称:<servlet-name>-servlet.xml若要为springMVC的配置文件设置自定义的位置和名称(推荐)需要在servlet标签中添加init-param<init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springMVC.xml</param-value></init-param>--><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:springMVC.xml</param-value>  <!--对应resources目录下的文件--></init-param><load-on-startup>1</load-on-startup>  <!--服务器启动时初始化DispatcherServlet--></servlet><servlet-mapping><servlet-name>springMVC</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
  1. 在 resources 目录下,配置 SpringMVC 的 xml:开启组件扫描、加入 thymeleaf 的名称空间并配置视图解析器(Thymeleaf 是服务器端的模板引擎,在服务器端获取模板和数据,生成结果输出给浏览器呈现结果)
<?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 https://www.springframework.org/schema/context/spring-context.xsd"><!--开启组件扫描--><context:component-scan base-package="com.atguigu.mvc.controller"></context:component-scan><!-- 配置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>
</beans>
  1. 定义 Controller 类,并用注解标注类和方法;在 templates 中定义 index.html, target.html
@Controller
public class HelloController {/* 通过@RequestMapping注解,可以通过请求路径匹配要处理的具体的请求/表示的当前工程的上下文路径 http://localhost:8080/project_context/返回字符串即可,thymeleaf自动为返回值配置前后缀方法名可以随意,根据注解进行解析*/@RequestMapping("/")public String index(){return "index";}@RequestMapping("/target")public String toTarget(){return "target";}
}

总结:

  • 浏览器发送请求,若请求地址符合前端控制器的url-pattern,该请求就会被前端控制器 DispatcherServlet 处理
  • 前端控制器会读取 SpringMVC 的核心配置文件,通过扫描组件找到控制器,将请求地址和控制器中@RequestMapping 注解的 value 属性值进行匹配(要求每个方法的 value 值唯一)
  • 若匹配成功,该注解所标识的控制器方法就是处理请求的方法,处理请求的方法需要返回一个字符串类型的视图名称
  • 该视图名称会被视图解析器解析,加上前缀和后缀组成视图的路径,通过 Thymeleaf 对视图进行渲染,最终转发到视图所对应页面

二 @RequestMapping

作用是关联 请求处理请求的控制器方法。SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处理这个请求。

1 注解类与方法的区别

  • @RequestMapping标识一个类:设置映射请求的请求路径的初始信息
  • @RequestMapping标识一个方法:设置映射请求请求路径的具体信息
@Controller
@RequestMapping("/test")
public class RequestMappingController {//此时请求映射所映射的请求的请求路径为:/test/testRequestMapping@RequestMapping("/testRequestMapping")public String testRequestMapping(){return "success";}
}

2 value 属性

  • 通过请求的请求地址匹配请求映射
  • 是一个字符串类型的数组,和其中任意字符串匹配则选择该方法,满足其中一个即可
  • @RequestMapping 必须设置的属性
<!--以下均能匹配 testRequestMapping()-->
<a th:href="@{/testRequestMapping}"> value1 </a>
<a th:href="@{/test}"> value2 </a>@RequestMapping(
value = {"/testRequestMapping", "/test"}
)
public String testRequestMapping(){return "success";
}

3 method 属性

  • 根据请求方法 GET / POST / PUT / DELETE匹配请求映射
  • 默认任意请求方式均可匹配
  • RequestMethod 枚举类型的数组,表示该请求映射能够匹配多种请求方式的请求,满足其中一个即可
  • @RequestMapping(value="/idx", method={RequestMethod.GET}) 等于 @GetMapping(value="/idx"),其它方式同理
  • 如果 value 匹配而 method 不匹配,出现405错误

4 params 属性

  • 根据请求携带的的参数匹配请求映射
  • 是一个字符串类型的数组,需要同时满足所有条件,可以通过四种表达式设置请求参数和请求映射的匹配关系:
    “param”:要求请求映射所匹配的请求必须携带 param 请求参数
    “!param”:要求请求映射所匹配的请求必须不能携带 param 请求参数
    “param=value”:要求请求映射所匹配的请求必须携带 param 请求参数且 param=value
    “param!=value”:要求请求映射所匹配的请求必须携带 param 请求参数但 param!=value
<a th:href="@{/test(username='admin',password=123456)">测试</a>@RequestMapping(value = {"/testRequestMapping", "/test"},method = {RequestMethod.GET, RequestMethod.POST},params = {"username","password!=123456"}
)
public String testRequestMapping(){return "success";
}

5 headers 属性

  • 根据请求的请求头信息匹配请求映射
  • 类似 params 属性,是一个字符串类型的数组,需要同时满足所有条件,可以通过四种表达式设置请求参数和请求映射的匹配关系:
    “header”:要求请求映射所匹配的请求必须携带 header 请求头信息
    “!header”:要求请求映射所匹配的请求必须不能携带 header 请求头信息
    “header=value”:要求请求映射所匹配的请求必须携带 header 请求头信息且 header=value
    “header!=value”:要求请求映射所匹配的请求必须携带 header 请求头信息且 header!=value

6 SpringMVC 支持路径中的占位符

  • 将请求携带的参数以请求路径的形式,向服务器传递参数
  • 如果 @RequestMappingvalue 属性中有路径的占位符,则请求时必须有占位符对应的参数,否则出现404
<a th:href="@{/goods/123}">访问goods,参数123</a>@Controller
public class MyController {@RequestMapping("/goods/{id}")public String goodsPage(@PathVariable("id") int param_id) {System.out.println(param_id);return "goods";}
}

三 获取 Request 的一系列参数

1 通过控制器方法的形参

  • 将形参名和 Request 参数名对应即可(如果不同名,则需要使用 @RequestParam),如此只能获取 Request 参数,而不能获得请求头信息等
  • 如果有多个同名的参数,则将形参类型设置为字符串数组
<a th:href="@{/testParam(username='admin',password=123456)}">测试</a>@RequestMapping("/testParam")
public String testParam(String username, String password){System.out.println("username:"+username+",password:"+password);return "success";
}

2 控制器方法形参 映射 Request 参数 - @RequestParam

  • value:Request 中的参数的 name 属性
  • required:标明该参数是否必须,如果是必须且未设置 defaultValue,则必须由 Request 传入
  • defaultValue:默认值
@Controller
public class MyController {@RequestMapping("/goods/diff")// request 传递参数为 name, passwdpublic String diff(@RequestParam(value = "name") String n,@RequestParam(value = "passwd", required = false) String pwd) {System.out.println(n + pwd);return "goods";}
}

3 控制器方法形参 映射 Request 请求头 - @RequestHeader

  • 同样具有 value, required, defaultValue,用法相同

4 控制器方法形参 映射 cookie数据 - @CookieValue

  • 同样具有 value, required, defaultValue,用法相同

5 通过 POJO 获取 Request 参数

将控制器方法形参设置为实体类类型,此时若浏览器传输的请求参数的参数名,和实体类中的属性名一致,那么请求参数就会为此属性赋值

<form th:action="@{/testpojo}" method="post">用户名:<input type="text" name="username"><br>密码:<input type="password" name="password"><br>性别:<input type="radio" name="sex" value="男">男<input type="radio"name="sex" value="女">女<br>年龄:<input type="text" name="age"><br>邮箱:<input type="text" name="email"><br><input type="submit">
</form>
@RequestMapping("/testpojo")
public String testPOJO(User user){  // 根据request参数创建对象,前提是属性名和请求参数名相同System.out.println(user);  return "success";
}

6 解决获取参数的乱码问题

  • GET 请求的乱码问题可以通过更改 Tomcat 的配置文件 server.xml 解决
  • POST 请求的乱码问题必须在请求参数获取之前设置编码,要比 Servlet 启动更早
  • 服务器启动时,初始化顺序是 Listener -> Filter -> Servlet,可以使用 Filter 设置编码格式(不使用 Listener 是因为监听器只执行一次,负责初始化 / 销毁的动作,而 Filter 可以过滤所有符合路径请求),在 web.xml 中配置,并设置为首个 Filter
<!--配置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、Session、Application(ServletContext)

1 使用 ServletAPI 向 request 域对象共享数据(不建议)

@Controller
public class TestController {@RequestMapping("/servlet")public String m1(HttpServletRequest httpServletRequest) {httpServletRequest.setAttribute("k", "v");return "index";}
}
index.html:
<p th:text="${k}"></p>

2 使用 ModelAndView 向 request 域对象共享数据

  • 向 request 域对象共享数据的所有方式,本质是对使用 ModelAndView 进行共享的一种封装
  • 方法的返回值必须是 ModelAndView 类型
@Controller
public class TestController {@RequestMapping("/modelandview")public ModelAndView m2() {ModelAndView modelAndView = new ModelAndView();// 设置键值对modelAndView.addObject("k", "v");// 设置视图名称modelAndView.setViewName("index");return modelAndView;}
}

3 使用 Model 向 request 域对象共享数据

  • 类似于 ServletAPI
@Controller
public class TestController {@RequestMapping("/model")public String m3(Model model) {model.addAttribute("k", "v");return "index";}
}

4 使用 Map 向 request 域对象共享数据

@Controller
public class TestController {@RequestMapping("/map")public String m4(Map<String, Object> map) {map.put("k", "v");return "index";}
}

5 使用 ModelMap 向 request 域对象共享数据

  • 类似于 ServletAPI
@Controller
public class TestController {@RequestMapping("/modelmap")public String m5(ModelMap modelMap) {modelMap.addAttribute("k", "v");return "index";}
}

6 使用 ServletAPI 向 Session 域对象共享数据

@RequestMapping("/testSession")
public String testSession(HttpSession session){session.setAttribute("testSessionScope", "hello,session");return "index";
}

7 使用 ServletAPI 向 Application 域对象共享数据

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

五 SpringMVC 视图

  • 默认的有:转发视图、重定向视图

1 Thymeleaf 视图

  • 实现了转发视图的功能
  • 当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被 SpringMVC 配置文件中所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发的方式实现跳转
@RequestMapping("/testHello")
public String testHello(){return "hello";  // 没有任何前缀
}

Spring 配置文件中的视图解析器:

    <!-- 配置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="/templates/"/><property name="suffix" value=".html"/><property name="templateMode" value="HTML5"/><property name="characterEncoding" value="UTF-8" /></bean></property></bean></property></bean>

2 转发视图

  • SpringMVC中默认的转发视图是 InternalResourceView
  • 当控制器方法中所设置的视图名称以"forward:"为前缀时,创建 InternalResourceView 视图,此时的视图名称不会被 SpringMVC 配置文件中所配置的视图解析器解析,而是会将前缀"forward:"去掉,剩余部分作为最终路径通过转发的方式实现跳转
@RequestMapping("/testForward")
public String testForward(){return "forward:/testHello";  // 先创建 InternalResourceView 再创建 Thymeleaf View
}

3 重定向视图

  • SpringMVC 中默认的重定向视图是 RedirectView
  • 当控制器方法中所设置的视图名称以"redirect:"为前缀时,创建 RedirectView 视图,此时的视图名称不会被 SpringMVC 配置文件中所配置的视图解析器解析,而是会将前缀"redirect:"去掉,剩余部分作为最终路径通过重定向的方式实现跳转
  • 重定向视图在解析时,会先将 redirect: 前缀去掉,然后会判断剩余部分是否以 / 开头,若是,则自动拼接上下文路径
@RequestMapping("/testRedirect")
public String testRedirect(){return "redirect:/testHello";
}

4 使用 view-controller 代替 控制器方法

  • 当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法用 view-controller 标签表示
  • 当SpringMVC 中设置任何一个 view-controller 时,其他控制器中的请求映射将全部失效,可以使用标签<mvc:annotation-driven />开启
<mvc:view-controller path="/testView" view-name="success"></mvc:view-controller>

六 RESTful

  • Representational State Transfer,表现层资源状态转移
  • REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性
  • 对于 HTTP 的四种请求:
操作 HTTP 请求 RESTful
插入 POST /user(请求为 POST)
删除 DELETE /user/id(请求为 DELETE)
更新 PUT /user(请求为 PUT)
查询 GET /user/id(请求为 GET)
  • SpringMVC 中提供了两个过滤器:CharacterEncodingFilterHiddenHttpMethodFilter
  • 使用 HiddenHttpMethodFilter 模拟 DELETE 和 PUT
  • 在 web.xml 中注册时,必须先注册 CharacterEncodingFilter,再注册 HiddenHttpMethodFilter,因为CharacterEncodingFilter要求前面不能有任何获取请求参数的操作,而 CharacterEncodingFilter 获取了 request 参数

七 HttpMessageConverter

  • 报文信息转换器,将 请求报文 转换为Java对象,或将Java对象转换为 响应报文
  • HttpMessageConverter提供了两个注解和两个类型:@RequestBody,@ResponseBody,RequestEntity,ResponseEntity

1 @RequestBody

  • @RequestBody 可以获取请求体(仅仅是请求体而非整个 HTTP 报文,POST 具有请求体,而 GET 不具有)
  • 需要在控制器方法设置一个形参,使用 @RequestBody 进行标识,当前请求的请求体就会为当前注解所标识的形参赋值
  • 可以将前端传来的 json 转为对象
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String requestBody){System.out.println(requestBody);return "success";
}// 输出 requestBody:username=admin&password=123456
@Override
@PostMapping("/add")
public CmsPageResult add(@RequestBody CmsPage cmsPage) {  // @RequestBody将json转为对象return this.pageService.add(cmsPage);
}

2 RequestEntity

  • RequestEntity 封装 HTTP 请求报文,需要在控制器方法的形参中的 泛型位置 设置要将报文转换的目标类型,当前请求的请求报文就会赋值给该形参
  • 通过 getHeaders() 获取请求头信息,通过 getBody() 获取请求体信息
@RequestMapping("/request_entity")
public String requestEntityTest(RequestEntity<String> entity) {System.out.println(entity.getHeaders());System.out.println(entity.getBody());return "success";
}

3 @ResponseBody

  • @ResponseBody 用于标识一个 控制器方法,可以将该方法的 返回值 直接作为响应报文的 响应体 响应到浏览器
@RequestMapping("/response_body")
@ResponseBody
public String responseBodyTest() {return "TIGER YEAR";
}
  • 如果需要以 json 格式,打印 Java对象的响应体,需要导入 jackson 依赖并开启 mvc 注解驱动
pom.xml:<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.12.1</version></dependency>mvc核心配置文件:
<mvc:annotation-driven />
@RequestMapping("/response_body_json")
@ResponseBody
public User responseBodyJsonTest() {return new User("my_name", "my_passwd");
}

4 ResponseEntity

  • 用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文
  • 可以实现文件下载的功能

5 RestController

  • 复合注解,标识控制器类,就相当于为类添加了 @Controller 注解,并且为其中的每个方法添加了 @ResponseBody 注解

八 拦截器

  • 拦截的是控制器方法执行
  • 和过滤器 filter 的主要区别是,filter 作用于浏览器到 Servlet 的过程中,而拦截器作用于 Controller 执行前(Servlet 到 Controller 的过程中),以及 Controller 返回后 的过程中

1 配置方法

在 SpringMVC 配置文件中:

    <!-- 前两种对DispatcherServlet所处理的*所有的请求*进行拦截 --><mvc:interceptors><!--方式一:--><bean class="interceptor.MyInterceptor"></bean><!--方式二:--><ref bean="myInterceptor"></ref><!--方式三:可以自定义拦截路径--><!--可以通过ref或bean标签设置拦截器,通过mvc:mapping设置需要拦截的请求,通过mvc:exclude-mapping设置需要排除的请求,即不需要拦截的请求--><mvc:interceptor><mvc:mapping path="/**"/><mvc:exclude-mapping path="/testRequestEntity"/><ref bean="myInterceptor"></ref></mvc:interceptor></mvc:interceptors>

拦截器类:

@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("pre");return true;  // 返回 true 放行}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("post");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("after");}
}

2 HandlerInterceptor 接口的三个方法

  • preHandle:返回值为 bool 类型,返回 true 放行,false 拦截
  • postHandle:控制器方法执行之后执行
  • afterComplation:渲染视图完毕之后执行

3 多个拦截器的执行顺序

  • 如果所有拦截器的 preHandle() 都返回 true,则 preHandle() 按照配置的顺序执行,postHandle()afterComplation() 按照配置的反序执行
  • 如果某个拦截器的 preHandle() 返回 false,preHandle() 返回 false 的拦截器和它之前的拦截器的 preHandle() 都会执行,postHandle() 都不执行,返回 false 的拦截器之前的拦截器的 afterComplation() 会倒序执行
  • 下图是所有拦截器的 preHandle() 都返回 true 的情况,如果拦截器3返回 false,则方法的执行顺序是: 1.prehandle->2.prehandle->3.prehandle->2.afterCompletion->1.afterCompletion

九 异常处理器

1 基于配置

在 SpringMVC 的核心配置文件中:

  1. 设置异常类型与视图名称的映射
  2. 保存异常信息到 request 域(可选)
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings">  <!--properties类型,键值对的结构--><props><!--1. key表示处理器方法执行过程中出现的异常,全类名value(写在双标签之内)表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面--><prop key="java.lang.ArithmeticException">error</prop></props></property><!--2. exceptionAttribute:将出现的异常信息在请求域中进行共享,value属性是信息的key--><property name="exceptionAttribute" value="info_key"></property>
</bean>

出现异常后,跳转到 error.html 访问异常信息:

<body><p th:text="${info_key}"></p>
</body>

2 基于注解

  • 使用 @ControllerAdvice 注解异常处理类
  • 使用 @ExceptionHandler(异常类的class对象) 注解异常处理方法
// 标识为异常处理组件
@ControllerAdvice
public class AnnotationExceptionController {// 处理的异常类型,处理多种异常时 @ExceptionHandler(value = {...})@ExceptionHandler(ArithmeticException.class)public String divide0(Exception exception, Model model) {// 向 request 域中写入键值对model.addAttribute("info_key", exception);// 交由 thymeleaf 解析return "fail";}
}

十 使用注解配置 SpringMVC

  • 目的是使用配置类和注解代替 web.xml 和 SpringMVC 配置文件的功能

1 初始化类:代替 web.xml

  • 继承自 AbstractAnnotationConfigDispatcherServletInitializer
/*
* 需要完成的功能:
* 1.servlet
* 2.servlet-mapping
* 3.过滤器
* 4.Spring配置类
* 5.SpringMVC配置类*/
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {// 指定 Spring 配置类@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[]{MySpringConfig.class};  // 创建长度为1的Class数组,放入MySpringConfig.class}// 指定SpringMVC的配置类@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{MyWebConfig.class};  // 同上}// 指定DispatcherServlet的映射规则,即url-pattern@Overrideprotected String[] getServletMappings() {return new String[]{"/"};  // 设置servlet-mapping}// 过滤器@Overrideprotected Filter[] getServletFilters() {// 过滤器1CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();encodingFilter.setEncoding("UTF-8");encodingFilter.setForceRequestEncoding(true);// 过滤器2HiddenHttpMethodFilter hiddenHttpMethodFilter = newHiddenHttpMethodFilter();return new Filter[]{encodingFilter, hiddenHttpMethodFilter};}
}

2 SpringConfig 类:代替 Spring 配置文件(略)

@Configuration
public class MySpringConfig {// ...
}

3 WebConfig 类:代替 SpringMVC 配置文件

  • @Bean 的作用是,将方法返回值(Java 对象)交给 IOC 容器
/*
* 需要完成的功能:
* 1.组件扫描
* 2.thymeleaf视图解析器
* 3.视图控制器
* 4.mvc注解驱动
* 5.拦截器
* 6.异常处理器
* 7.default-servlet-handler
* 8.文件上传解析器*/@Configuration  // 标注当前类为配置类
@ComponentScan(value = {"config", "controller", "interceptor"})  // 开启组件扫描
@EnableWebMvc  // 开启注解驱动
public class MyWebConfig implements WebMvcConfigurer {/*************************** 重写WebMvcConfigurer类的方法 ***************************/// 使用默认的servlet处理静态资源@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}// 拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {MyInterceptor myInterceptor = new MyInterceptor();registry.addInterceptor(myInterceptor).addPathPatterns("/**");}// 视图控制器@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("index");}// 异常处理器,一种实现方式,也可以配置为 @bean@Overridepublic void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {// 写法参考之前的 SpringMVC 配置文件Properties properties = new Properties();properties.setProperty("java.lang.ArithmeticException", "fail"); // (异常全类名,跳转视图名称)SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();simpleMappingExceptionResolver.setExceptionMappings(properties);  // 设置异常映射simpleMappingExceptionResolver.setExceptionAttribute("info_key");  // 设置异常信息的keyresolvers.add(simpleMappingExceptionResolver);}/************************* 配置 thymeleaf 视图解析器 *******************************/// 1.配置生成模板解析器@Bean  // @Bean的返回值放入IOC容器public ITemplateResolver templateResolver() {WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();// ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext());templateResolver.setPrefix("/templates/");templateResolver.setSuffix(".html");templateResolver.setCharacterEncoding("UTF-8");templateResolver.setTemplateMode(TemplateMode.HTML);return templateResolver;}// 2.生成模板引擎并为其注入模板解析器@Beanpublic SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {  // !!!参数进行了自动装配SpringTemplateEngine templateEngine = new SpringTemplateEngine();templateEngine.setTemplateResolver(templateResolver);return templateEngine;}// 3.生成视图解析器并为其注入模板引擎@Beanpublic ViewResolver viewResolver(SpringTemplateEngine templateEngine) {ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();viewResolver.setCharacterEncoding("UTF-8");viewResolver.setTemplateEngine(templateEngine);return viewResolver;}/************************* 其它插件 *******************************/// 配置文件上传解析器
//    @Bean
//    public CommonsMultipartResolver multipartResolver(){//        return new CommonsMultipartResolver();
//    }}

十一 SpringMVC 执行流程

1 常用组件

  • DispatcherServlet:前端控制器,不需要工程师开发,由框架提供
    作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求

  • HandlerMapping:处理器映射器,不需要工程师开发,由框架提供
    作用:根据请求的url、method等信息查找Handler,即控制器方法

  • Handler:处理器
    作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理

  • HandlerAdapter:处理器适配器,不需要工程师开发,由框架提供
    作用:通过HandlerAdapter对处理器(控制器方法)进行执行

  • ViewResolver:视图解析器,不需要工程师开发,由框架提供
    作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、RedirectView

  • View:视图
    作用:将模型数据通过页面展示给用户

2 流程总结

  1. 用户向服务器发送请求,被 SpringMVC 前端控制器 DispatcherServlet 捕获
  2. DispatcherServlet 解析 URL(统一资源定位器),得到URI(请求资源标识符),并与配置的 servlet-mapping 进行匹配,判断请求 URI 对应的映射:
    (1) 可以匹配,则交给具体的 Servlet,前往步骤3
    (2) 不能匹配,如果配置了 mvc:default-servlet-handler ,访问目标资源(一般为静态资源,如:JS, CSS, HTML),找不到展示404错误
    (3) 不能匹配,没有配置 mvc:default-servlet-handler,展示404错误
  3. 根据 URI,调用 HandlerMapping 获得该 Handler 配置的所有相关的对象(包括 Handler 对象以及Handler 对象对应的拦截器),最后以 HandlerExecutionChain 执行链对象的形式返回
  4. DispatcherServlet 根据获得的 Handler,选择一个合适的 HandlerAdapterHandler 执行需要依赖HandlerAdapter
  5. 如果成功获得 HandlerAdapter,此时将开始执行拦截器的 preHandler() 方法
  6. 向控制器方法传递客户端请求 Request 携带的参数,执行控制器方法,此处可以配置一些额外操作:
    (1) HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
    (2) 数据格式化、数据验证…
  7. 控制器方法执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象
  8. 执行拦截器的 postHandle() 方法
  9. DispatcherServlet 根据返回的 ModelAndView(首先判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver 进行异常处理)选择一个适合的 ViewResolver 进行视图解析,根据 Model 和 View,渲染视图
  10. 执行拦截器的 afterCompletion() 方法
  11. 将渲染结果返回给客户端

后端学习 - SpringMVC相关推荐

  1. 【java后端学习路线3】SSM+Linux+Git学习指南,985本海硕自学转码

    JAVA后端学习路线 路线总览 javase->Mysql->计算机网络->JavaWeb->Maven(1)->Spring->SpringMVC->Myb ...

  2. 从零开始学习springmvc(5)——Spring国际化和全局异常处理

    [项目地址] 从零开始学习springmvc 如果觉得有用可以关注一下公众号:码字不易,求赞求关注 五.Spring国际化和全局异常处理 五.Spring国际化和全局异常处理 5.1 国际化介绍 5. ...

  3. Java后端学习路线分享

    Java后端学习路线?最近有些网友问我如何学习 Java 后端,还有些是想从别的方向想转过来,但都不太了解 Java 后端究竟需要学什么,究竟要从哪里学起,哪些是主流的 Java 后端技术等等,导致想 ...

  4. Java——Web后端学习路线

    文章目录 Java后端学习路线 第一部分: Java基础 第二部分: Java高级 第三部分: JavaWEB 第四部分: 主流框架和项目管理 第五部分: 分布式 微服务 并行架构 第六部分 : De ...

  5. 大厂招聘-校招生/实习生 后端学习路线-Java

    大厂招聘-校招生/实习生 后端学习路线-Java 我是一个Java后端开发人员,校招生,在面试过程中深感Java作为红海,找工作投简历的人那是一个多呀,打个比喻,100人找工作,20个是算法,10个是 ...

  6. 框架写mysql插入为空_学习springMVC框架配置遇到的问题-数据写入不进数据库时的处理办法...

    Idea简单SpringMVC框架配置 前边已经介绍过了Struts在Idea上的配置,相对于Struts来说,我觉得SpringMVC有更多的优势,首先Struts是需要对action进行配置,页面 ...

  7. C/C++后端学习秘籍

    C/C++后端学习秘籍 文章目录 C/C++后端学习秘籍 前言 一.算法训练 1.拓扑顺序 2.功夫传人 3.二叉树中的最低公共祖先 二.工程项目训练 day1.Qt(串口的使用) 三.总结 前言 今 ...

  8. 大学四年Java后端学习路线规划,所有私藏资料我都贡献出来了,不看毕业肯定后悔!!!

    一定要走在学校前面自学,规划好自己的时间,按照自己的路线走. 大学四年Java后端学习路线规划,所有私藏资料我都贡献出来了,不看毕业肯定后悔!!! 学习路线与资源方法 一.第一件事,很重要!!! 二. ...

  9. 前后端分离实现在线记账功能,前端使用vue,后端使用springmvc

    前后端分离实现在线记账功能 前端采用vue 后端采用springmvc 前端目录 后端目录 运行结果 双击单元格可以对每一项内容进行修改

最新文章

  1. Dijkstra算法.
  2. 深化对KMP算法的理解
  3. 导出Excel java
  4. linux显卡内核修改,iTOP-4412开发板-驱动-linux显卡驱动的修改方法
  5. synchronized 中的 4 个优化,你知道几个?
  6. 在Global中Application_Error事件处理错误信息
  7. 技术简报 2014-1-27
  8. Linux 下编译安装 PHP 5.6
  9. 手机后盖透明并不美观
  10. u8服务器修改数据源,用友U8服务器修改数据库端口
  11. yum安装wget命令
  12. Office 2010 Excel 多窗口同时单独打开多个文件设置教程
  13. 大数据时代的变革与顺势而为——读《大数据时代》
  14. abandon connection问题分析
  15. 手机 android.downloader病毒,downloader病毒是什么
  16. 手机服务器异常修复,手机服务器异常
  17. 机器学习15-k-均值算法表述
  18. 45、优惠券秒杀(实现一人一单)
  19. 计算机主机是什么系统吗,电脑RAM和ROM的区别是什么?RAM和ROM有哪些作用?
  20. 深度学习——模型构建

热门文章

  1. 微软HTTP API指南
  2. 【给中高级开发者】构建高性能ASP.NET应用的几点建议
  3. linux脚本打印循环次数,shell脚本编程基础(3)——循环用法
  4. C语言,C#语言求100-999内的水仙花数源程序
  5. Android之解决PC浏览器上传表单文件到手机服务器read数据错误导致有时候下载到手机的文件打开文字错乱问题
  6. Android之HandlerThread源码分析和简单使用(主线程和子线程通信、子线程和子线程通信)
  7. *p++,(*p)++,*++p,++*p有什么不同
  8. [python opencv 计算机视觉零基础到实战] 一 opencv的helloworld
  9. C++入门指南及实战 第一步 概述及经典HelloWorld
  10. sql between...and 用法(mysql)