后端学习 - SpringMVC

文章目录

  • 一 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. 将渲染结果返回给客户端

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307160.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hbase shell远程连接_hbase与phoenix集成

Phoenix是构建在HBase之上的关系型数据库层&#xff0c;作为内嵌的客户端JDBC驱动用以对HBase中的数据进行低延迟访问Phoenix会将用户编写的sql查询编译为一系列的scan操作&#xff0c;最终产生通用的JDBC结果集返回给客户端Phoenix可以看成是mysql准备安装包apache-phoenix-4.…

对精致码农大佬的 [理解 volatile 关键字] 文章结论的思考和寻找真相

一&#xff1a;背景1. 讲故事昨天在园里的编辑头条看到 精致码农大佬 写的一篇题为&#xff1a;[C#.NET 拾遗补漏]10&#xff1a;理解 volatile 关键字 (https://www.cnblogs.com/willick/p/13889006.html) 的文章&#xff0c;大概就是说在 多线程环境下&#xff0c;一个在debu…

后端学习 - SpringBoot

SpringBoot 是整合 Spring 技术栈的一站式框架&#xff0c;是简化 Spring 技术栈的快速开发脚手架约定大于配置 文章目录一 概述1 第一个 SpringBoot 项目2 SpringBoot 特性&#xff1a;依赖管理3 SpringBoot 特性&#xff1a;自动配置二 SpringBoot 的 IOC容器1 组件添加&…

centos rpm 安装 perl_Linux【常用软件安装篇】

摘要&#xff1a;本文介绍Linux常用的软件安装方式以及jdk、vim、mysql、tomcat、redis的安装过程。1 Linux常用软件安装方式常用方式有&#xff1a;rmp包安装、yum指令安装、源码包安装、解压免安装。1.1 rpm包安装rpm是Red-Hat Package Manager&#xff08;RPM软件包管理器&a…

日计不足涓滴成河-自定义响应结果格式化器

什么是响应结果响应结果就是&#xff0c;在客户端向服务器发出请求后&#xff0c;服务器根据客户端的请求参数&#xff0c;给出的结果&#xff0c;这就是一个完整的响应结果过程。响应的结果包含的内容非常多&#xff0c;主要的有 HTTP Status Code&#xff0c;Content-Type,Co…

docker 容器启动顺序_Docker容器启动时初始化Mysql数据库

1. 前言 Docker在开发中使用的越来越多了&#xff0c;最近搞了一个Spring Boot应用&#xff0c;为了方便部署将Mysql也放在Docker中运行。那么怎么初始化 SQL脚本以及数据呢&#xff1f; 我这里有两个传统方案。 第一种方案是在容器启动后手动导入&#xff0c;太low了不行。第二…

后端学习 - JVM(上)内存与垃圾回收

JVM 架构图 文章目录一 JVM 简介二 类加载子系统&#xff1a;1 作用2 类的三个加载过程3 类加载器的分类4 双亲委派机制 & Tomcat为何不遵循5 两个 class 对象为同一个类的必要条件三 运行时数据区&#xff1a;PC寄存器&#xff08;Program Counter Register&#xff09;四…

SM2 国密算法被 Linux 内核社区接受

喜欢就关注我们吧&#xff01;10 月 25 日&#xff0c;有开发者发文称&#xff0c;SM2 国密算法终于被 Linux 内核社区接受了。该作者表示&#xff0c;SM2 的补丁已经更新到了 v7 版本&#xff0c;这个版本的补丁最终被社区接受&#xff0c;目前已经合并到了 Linux 主线的 5.10…

后端学习 - MyBatis

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的 持久层框架 文章目录一 基于配置文件的 MyBatis 搭建1 搭建过程&#xff08;增删改&#xff09;2 查询操作3 特殊操作二 MyBatis 获取参数值的方式1 单个字面量类型的参数2 多个字面量类型的参数3 Map 类型的参数4 实体…

国产操作系统发展离不开人才和市场

日前&#xff0c;中国 1024 程序员节盛大举行&#xff0c;一大批开源大咖齐聚千年岳麓&#xff0c;围绕开源标准、生态、人才发展等主题分享&#xff0c;共议开源软件与操作系统未来。其中&#xff0c;统信软件总经理刘闻欢表示&#xff0c;“有了市场才会被真正的用起来”&…

后端学习 - Redis

文章目录一 Redis 概述Redis 为什么是单线程&#xff0c;单线程为什么这么快&#xff1f;数据存储结构二 常用数据类型1 String2 HashHash 的扩容机制&#xff1a;渐进式 rehash*3 List4 Set5 Zset三 Redis 事务1 乐观锁与 watch 命令2 事务的三个特性四 Redis 持久化1 RDB(Red…

再被补刀!Flash又遭抛弃,你会怀念它吗?

喜欢就关注我们吧&#xff01;微软近日发布通知&#xff0c;称更新了关于 Adobe Flash Player 的删除。微软更新目录站点可下载更新 KB4577586&#xff0c;用于删除 Flash Player。此更新适用于所有受支持的操作系统版本。重要版本 Windows 10 和 Windows 8.1 的可选更新也将在…

4位加法器的设计代码verilog_HDLBits:在线学习Verilog(六 · Problem 25-29)

本系列文章将和读者一起巡礼数字逻辑在线学习网站 HDLBits 的教程与习题&#xff0c;并附上解答和一些作者个人的理解&#xff0c;相信无论是想 7 分钟精通 Verilog&#xff0c;还是对 Verilog 和数电知识查漏补缺的同学&#xff0c;都能从中有所收获。附上传送门&#xff1a;M…

译 | 将数据从Cosmos DB迁移到本地JSON文件

点击上方蓝字关注“汪宇杰博客”原文&#xff1a;Azure Tips and Tricks翻译&#xff1a;汪宇杰在Cosmos DB中使用数据迁移工具有一项重复的任务是将数据从一种数据库格式迁移到另一种数据库格式。我最近使用Cosmos DB作为数据库来存储Ignite大会发出的所有推文。然而一旦获得了…

在线教育后端开发项目总结

文章目录一 数据库访问接口1 MyBatis2 Spring Data JPA3 Spring Data MongoDB二 数据库1 MySQL2 MongoDB3 Redis三 开发规范化、响应格式与异常处理1 开发规范2 响应格式3 异常处理四 RabbitMQ五 Spring Cloud 相关工具1 Eureka2 Ribbon3 Feign4 Zuul 网关六 搜索服务1 Elastic…

通讯故障_掌握PLC必备知识,人机界面和 PLC 出现通讯故障如何分析解决

此次主要在阐述人机界面和 PLC 通讯时的模式状态&#xff0c;并列举了通讯故障实例。帮助大伙加深对这俩者的了解&#xff0c;掌握起来也不再是难题&#xff0c;解决掉拦路虎。一 台数 显 四 辊 卷 板 机PLC 控 制 系 统 核 心 与 人机界面在使用过程中&#xff0c;出现人机界面…

后端学习 - 设计模式与设计原则

文章目录设计原则1 单一职责原则2 开闭原则3 Liskov 替换原则4 依赖倒置原则5 接口隔离原则6 迪米特法则设计模式&#xff1a;创建型模式1 工厂模式2 抽象工厂模式3 单例模式设计模式&#xff1a;行为型模式1 观察者模式2 模板模式3 备忘录模式设计模式&#xff1a;结构型模式1…

ai的预览模式切换_AI字体制作,用AI制作创意阶梯式文字

本篇教程通过AI制作一款创意阶梯式文字&#xff0c;教程中有很多知识点需要掌握&#xff0c;比如路径分割为网络&#xff0c;3D效果应用等&#xff0c;我们要利用他们创造出我们需要的文字出来&#xff0c;具体是如何制作的&#xff0c;我们通过教程一起来学习一下吧。效果图&a…

新版本 Swashbuckle swagger 组件中的 坑

新版本 Swashbuckle swagger 组件中的 Servers 坑Intro上周做了公司的项目升级&#xff0c;从 2.2 更新到 3.1&#xff0c; swagger 直接更新到了最新&#xff0c;swagger 用的组件是 Swashbuckle.AspNetCore&#xff0c;然后遇到一个 swagger 的问题&#xff0c; 在本地测试是…

后端学习 - MySQL存储引擎、索引与事务

文章目录一 存储引擎1 MyISAM 与 InnoDB 的差异二 索引1 主键索引与二级索引、索引覆盖、延迟关联2 聚簇索引与非聚簇索引3 数据结构3.1 哈希表3.2 B树3.3 B树3.4 跳表3.5 为什么不使用红黑树3.6 为什么不使用B树**4 索引下推 ICP **5 索引失效&#xff08;索引不命中&#xff…