课程来自b站尚硅谷springmvc相关视频教程SpringMVC 2021新版教程
课程主要内容:
1. springMVC 简介
2 入门案例
2.1 实现案例
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.coderhao</groupId>
<artifactId>springMVC</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<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>
<!--范围provided表示已被提供,当打包时该依赖不会打到包里-->
<!--因为tomcat里面带着servlet的api-->
<scope>provided</scope>
</dependency>
<!-- Spring5和Thymeleaf整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
</dependencies>
</project>
建一个webapp文件夹:
新建web.xml,注意路径:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 配置SpringMVC的前端控制器,对浏览器发送的请求统一进行处理 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 通过初始化参数指定SpringMVC配置文件的位置和名称 -->
<init-param>
<!-- contextConfigLocation为固定值 -->
<param-name>contextConfigLocation</param-name>
<!-- 使用classpath:表示从类路径查找配置文件,例如maven工程中的
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>
<!--
设置springMVC的核心控制器所能处理的请求的请求路径
/所匹配的请求可以是/login或.html或.js或.css方式的请求路径
但是/不能匹配.jsp请求路径的请求
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
创建springMVC.xml:
springMVC:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns: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.coderhao.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>
</beans>
创建控制器:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping("/")
public String index() {
return "index";
}
}
根据springmvc的前缀在相应位置创建页面:
配置tomcat:
启动测试,出现index-page就算成功:
在index页面里加个跳转,测试一下跳转:
target页面写好:
controller也写上:
测试,可以跳转就算成功。
2.2 总结
3 @RequestMapping注解
3.1 介绍
3.2 注解参数详解
点进注解里面,按alt+7看所有参数:
匹配路径如果不填占位符位置的数据,会404,因为没这个路径。
4 springmvc获取请求参数
4.1 原生servlet:
4.2 springmvc的方法:
4.2.1 controller方法中形参的注解
当请求参数名和控制器的形参名不一致时,用@RequestParam可以指定请求参数和形参的对应关系:
第一次创建cookie是服务器创建放在响应报文中传回来,之后就一直使用这个cookie无论是请求报文还是响应报文:
甚至可以接收实体类:
4.2.2 乱码问题
使用的过滤器解决的乱码问题,因为过滤器执行在servlet之前(顺序:监听器、过滤器、servlet):
<!--配置springMVC的编码过滤器-->
<!--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>
这个可以解决post请求的乱码问题,get请求的乱码问题是tomcat造成的,可以在tomcat的配置中解决:
5 域对象共享数据
有些数据需要往页面中发送,就需要域对象共享。
三个域对象,从小到大是request域、session域、servletcontext(application)域。一般使用满足条件的最小域,大了浪费资源。
- request的生命周期是针对客户端的一次请求,当请求完毕,request里边的内容也将被清空。
- session表示一个会话。(从客户端浏览器连接服务器开始,到客户端浏览器与服务器断开,这个过程就是一个会话)。session的生命周期是设置的会话周期(一般20~30分钟),在会话周期内,session中的内容会一直存在,即使关闭了浏览器,session也不一定会被立马清空。
- application域,存活范围最大的对象,只要服务器没有关闭,application对象中的数据就会一直存在。在整个服务器运行过程当中,application对象只有一个。
往域对象中发送信息后页面怎么接收不同的前端框架有不同的操作,这里不具体展示。
5.1 request域
5.1.1 原生servlet
5.1.2 springmvc的ModelAndView、Model、Map、ModelMap方式
这个ModelAndView类很重要,不管使用什么方式返回数据springmvc都要处理成ModelAndView。
5.2 session域
原生的比springmvc提供的简单,这里建议使用原生的就够了:
5.3 application域
6 springmvc的视图
SpringMVC中的视图是View接口,视图的作用渲染数据,将模型Model中的数据展示给用户
SpringMVC视图的种类很多,默认有转发视图和重定向视图
当工程引入jstl的依赖,转发视图会自动转换为JstlView
若使用的视图技术为Thymeleaf,在SpringMVC的配置文件中配置了Thymeleaf的视图解析器,由此视图解析器解析之后所得到的是ThymeleafView。
转发重定向区别:
1、请求次数
重定向是浏览器向服务器发送一个请求并收到响应后再次向一个新地址发出请求,转发是服务器收到请求后为了完成响应跳转到一个新的地址;重定向至少请求两次,转发请求一次;
2、地址栏不同
重定向地址栏会发生变化,转发地址栏不会发生变化;
3、是否共享数据
重定向两次请求不共享数据,转发一次请求共享数据(在request级别使用信息共享,使用重定向必然出错);
4、跳转限制
重定向可以跳转到任意URL,转发只能跳转本站点资源;
5、发生行为不同
重定向是客户端行为,转发是服务器端行为。
补充:jsp访问页面
7 RESTful
7.1 简介
看不懂无所谓,我也似懂非懂,不影响使用。
7.2 实现
debug码源,发现实现需要以下条件:
get请求方式就是get
put、delete、post请求方式需要post方式,带个属性_method=真正的请求方式;还要配HiddenHttpMethodFilter
(1)首先搭个基础框架:
- 首先新建一个maven项目,导入依赖
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.coderhao</groupId>
<artifactId>springMVC</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<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>
</project>
- 添加web功能
- 编写web.xml:
配置上2个filter(编码和restful)和1个servlet(总控制器DispatcherServlet)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<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>
<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>
<servlet>
<servlet-name>DispatcherServlet</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>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
根据servlet的配置在resources下面新建个springMVC.xml:
4. 配置springMVC.xml:
配置1个包扫描和1个bean(视图解析器)
<?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.coderhao"></context:component-scan>
<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>
根据配置的视图解析器中的视图前缀创建管理页面的文件夹template:
5. 配置tomcat:
(2)实现get\post\put\delete:
index.html:
delete操作这里写不出来,因为需要post操作而且要在url上带上id参数,在vue前端框架中操作简单,但在这里操作麻烦,所以就不写出,等以后学习vue+springboot的项目时再实现。
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<a th:href="@{/user}">查询全部</a>
<a th:href="@{/user/1}">查询1个,id:1</a>
<form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="post"><br>
id:<input type="text" name="id"><br>
<input type="submit" value="add"><br>
</form>
<form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="put"><br>
id:<input type="text" name="id"><br>
<input type="submit" value="update"><br>
</form>
</body>
</html>
success.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>success</title>
</head>
<body>
<h1>success-page</h1>
</body>
</html>
IndexController:
package com.coderhao.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/")
public class IndexController {
// index 页
@RequestMapping(method = RequestMethod.GET)
public String getIndex() {
return "index";
}
}
RestFulController:
package com.coderhao.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/user")
public class RestFulController {
// user get 查询全部
@RequestMapping(method = RequestMethod.GET)
public String getUsers() {
System.out.println("查询全部");
return "success";
}
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
// user/1 get 查询单个
public String getUser(@PathVariable("id") int id) {
System.out.println("查询单个id:" + id);
return "success";
}
// user post 保存
@RequestMapping(method = RequestMethod.POST)
public String addUser(int id) {
System.out.println("保存操作,id:" + id);
return "success";
}
// user/1 delete 删除
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public String deleteUser(@PathVariable("id") int id) {
System.out.println("删除操作,id:" + id);
return "success";
}
// user put 更新
@RequestMapping(method = RequestMethod.PUT)
public String updateUser(int id) {
System.out.println("更新操作,id:" + id);
return "success";
}
}
7.3 静态资源放行
当引入一些静态资源(如图片、前端框架vue.js)时,在html中引入会使得前端控制器当成路径访问:
需要放行,在springmvc.xml中配置:
需要这两个配置一起用,因为配置defaultServlet会导致DispatcherServlet失效,需要手动开启。
处理顺序:先DispatcherServlet,路径找不到,就交给DefaultServlet,看看静态资源什么的,再找不到就报错。
8 HttpMessageConverter
请求的用的少,响应的用的多。
8.1 @RequestBody
想要接收一个带请求体的请求,需要是post请求。
8.2 RequestEntity
8.3 @ResponseBody
8.4 @ResponseBody返回json
json是一种javascript里面的一种数据格式,用的比较多。
8.5 @ResponseBody处理ajax
ajax,异步通信,在不发生页面跳转的过程中返回请求。
8.6 @RestController:@Controller+@ResponseBody
@RestController注解是springMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解
8.7 ResponseEntity
ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文,可以实现文件的下载。
详见第九章。
9 文件上传和下载
9.1 ResponseEntity实现文件下载
@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws
IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/static/img/1.jpg");
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename=1.jpg");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers,
statusCode);
//关闭输入流
is.close();
return responseEntity;
}
9.2 文件上传
文件上传要求form表单的请求方式必须为post,并且添加属性enctype=“multipart/form-data”。
SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息。
- 添加依赖
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --
>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
- springmvc添加配置
<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
- 前端和控制层代码示例
前端name是photo,后端接收形参的名也得是photo:
@RequestMapping("/testUp")
public String testUp(MultipartFile photo, HttpSession session) throws
IOException {
//获取上传的文件的文件名
String fileName = photo.getOriginalFilename();
//处理文件重名问题
//hzName:后缀名
String hzName = fileName.substring(fileName.lastIndexOf("."));
fileName = UUID.randomUUID().toString() + hzName;
//获取服务器中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";
}
10 拦截器
SpringMVC中的拦截器用于拦截控制器方法的执行
10.1 拦截器的使用
- 写一个实现HandlerInterceptor的方法作为拦截器
SpringMVC中的拦截器有三个抽象方法:
- preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法
- postHandle:控制器方法执行之后执行postHandle()
- afterComplation:处理完视图和模型数据,渲染视图完毕之后执行afterComplation()
package com.coderhao.filter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestFilter implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
//返回false表示拦截,返回true表示放行
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");
}
}
- 将写的拦截器配置到springMVC.xml里。
<bean id="testFilter" class="com.coderhao.filter.TestFilter"></bean>
<mvc:interceptors>
<!--方法1:bean的配置方法-->
<bean class="com.coderhao.filter.TestFilter"></bean>
<!--方法2:引用方式,需要之前配过bean-->
<ref bean="testFilter"></ref>
<!--方法3:可以带路径的拦截-->
<mvc:interceptor>
<!--拦截所有路径-->
<mvc:mapping path="/**"/>
<!--放行首页-->
<mvc:exclude-mapping path="/"/>
<!--拦截器配置-->
<ref bean="testFilter"></ref>
</mvc:interceptor>
</mvc:interceptors>
10.2 多个拦截器的执行顺序
- 若每个拦截器的preHandle()都返回true
此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关:
preHandle()会按照配置的顺序执行,而postHandle()和afterComplation()会按照配置的反序执行
- 若某个拦截器的preHandle()返回了false
preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回false
的拦截器之前的拦截器的afterComplation()会执行
11 异常处理器
SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver
HandlerExceptionResolver接口的实现类有:DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver
SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver
11.1 xml方式:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--
properties的键表示处理器方法执行过程中出现的异常
properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面
-->
<prop key="ArithmeticException">error</prop>
</props>
</property>
<!--
exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享
-->
<property name="exceptionAttribute" value="ex"></property>
</bean>
11.2 注解方式:
//@ControllerAdvice将当前类标识为异常处理的组件
@ControllerAdvice
public class ExceptionController {
//@ExceptionHandler用于设置所标识方法处理的异常
@ExceptionHandler(ArithmeticException.class)
//ex表示当前请求处理中出现的异常对象
public String handleArithmeticException(Exception ex, Model model) {
model.addAttribute("ex", ex);
return "error";
}
}
12 注解化配置文件web.xml、springMVC.xml
12.1 WebInit代替web.xml
package com.coderhao.config;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import javax.servlet.Filter;
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 encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceRequestEncoding(true);
//restful风格过滤器
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[]{encodingFilter, hiddenHttpMethodFilter};
}
}
12.2 WebConfig代替springMVC.xml
package com.coderhao.config;
import com.coderhao.filter.FirstInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import java.util.List;
import java.util.Properties;
@Configuration
//扫描组件
@ComponentScan("com.coderhao")
//开启MVC注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
//使用默认的servlet处理静态资源
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
//配置异常映射
@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);
}
//配置拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
FirstInterceptor firstInterceptor = new FirstInterceptor();
registry.addInterceptor(firstInterceptor).addPathPatterns("/**");
}
//配置生成模板解析器
@Bean
public ITemplateResolver templateResolver() {
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
// ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext());
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
}
//生成模板引擎并为模板引擎注入模板解析器
//参数都是自动装配的,类似@autowired
@Bean
public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
return templateEngine;
}
//生成视图解析器并为解析器注入模板引擎
@Bean
public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setCharacterEncoding("UTF-8");
viewResolver.setTemplateEngine(templateEngine);
return viewResolver;
}
//配置文件上传解析器
@Bean
public CommonsMultipartResolver multipartResolver(){
return new CommonsMultipartResolver();
}
}
12.3 SpringConfig,代替spring的配置文件
package com.coderhao.config;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig {
//ssm整合之后,spring的配置信息写在此类中
}
13 springmvc执行流程