2.SpringMVC学习
第一章 学习SpringMVC的切入点
如何切入MVC: ①SpringMVC是JavaWeb的延续 ②MVC(重点是Controller) ③拦截器
Controller: Controller的作用——依据用户发送的请求 ①调用相应的Model ②跳转响应的View
DispatcherServlet: 前端控制器是SpringMVC中心枢纽,它负责协调和控制整个请求处理流程,确保请求能够被正确地处理并生成相应的响应。
处理乱码
文件的上传和下载
拦截器
异常处理器
SpringMVC工作原理
SSM框架如何整合

第二章 其他
第一节 REST风格的CRUD
- 传统风格的CRUD(Create, Read, Update, Delete)
| 功能 | URL | 请求方式 |
|---|---|---|
| 增 | /insertEmp | POST |
| 删 | /deleteEmp?empId=1001 | GET(因为拼接地址栏) |
| 改 | /updateEmp | POST |
| 查 | /selectEmp?empId=1001 | GET |
- REST风格的CRUD
| 功能 | URL | 请求方式 |
|---|---|---|
| 增 | /emp | POST |
| 删 | /emp/1001 | DELETE |
| 改 | /emp | PUT |
| 查 | /emp/1001 | GET |
- REST风格CRUD优势
- 提高网站排名
- 排名方式
- 竞价排名
- 技术排名
- 排名方式
- 便于第三方平台对接
- 提高网站排名
- 如何实现PUT&DELETE提交方式
- 在web.xml中 注册过滤器HiddenHttpMethodFilter
<!-- 创建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>
- 设置表单的提交方式为POST ➕第一个input标签的name为
_method, value为PUT 或 DELETE
<form th:action="@{/emp}" method="post">
<!--value值忽略大小写-->
<input type="hidden" name="_method" value="put">
<input type="submit" name="提交"/>
</form>
- REST风格的URL都一样, 如何区分???
- 依据提交方式来区分, 不同的提交方式跳转不同的Controller方法
第二节 加载静态资源<mvc:annotation-driven/>
- 问题引入: ①我们发现如果直接通过重定向, 且文件, 路径都正确, 但还是无法404, 其问题可能是未加载静态资源 ②DefaultServlet是Servlet用于加载静态资源的类, 它往往是全部拦截的
<url-pattern>/</url-pattern>③但由于我们在web.xml中设置的<url-pattern>/</url-pattern>是SpringMVC的DispatcherServlet, 此时就会使得DefaultServlet无效, 从而导致静态资源无法加载 - 解决方法: 在
springmvc.xml中加上<mvc:default-servlet-handler/>即可 - 注意⚠️: 使用后会导致@Controller注解无法识别, 加上
<mvc:annotation-driven/>可以解决
<!--springmvc.xml-->
<!--解决静态资源加载问题-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!-- 添加上述标签,会导致Controller无法正常使用,需要添加mvc:annotation-driven解决 -->
<mvc:annotation-driven></mvc:annotation-driven>
第三章 Hello SpringMVC
第一节 STEP1: 在Maven项目下搭建WEB工程
第二节 STEP2: Pom.xml配置
- SpringMVC的视图层使用Thymeleaf实现的, 所以得配置①Thymeleaf和②Spring-webmvc两个包, 但又因为Tomcat还得一个③servlet-api
<!--spring-webmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<!-- 导入thymeleaf与spring5的整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
<!--servlet-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
第三节 STEP3: web.xml配置
- 创建DispatcherServlet Servlet
- 为DispatcherServlet初始化参数
- 设置创建DispatcherServlet优先级(Servlet的生命周期默认是有请求才会创建对象, 当SpringMVC要求服务器(Tomcat)一启动就创建, 所以要用
<load-on-starup>标签设置其优先级)
<!--1.创建DispatcherServlet Servlet-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--2.为DispatcherServlet初始化参数-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--3.设置创建DispatcherServlet优先级-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
第四节 STEP4: springmvc.xml配置
- 配置视图解析器本质上就是==配置Thymeleaf==, 其最核心的是==前后缀==, 注意⚠️需要手动要改
- 关于为什么WEB-INF下的资源可以被访问到
- ①因为SpringMVC or Thymeleaf 默认都是转发 ②WEB-INF是服务器的私有目录, 无法从浏览器的请求中获取 ③转发本质上是服务器内部发生的跳转 ④重定向是浏览器发送请求给服务器

- 其他:
HTML超链接<a>是通过GET方式提交的, <form>默认也是GET方式提交
<!--开启组件扫描-->
<context:component-scan base-package="com.mts"/>
<!--配置试图解析器(Thymeleaf)-->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<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="characterEncoding" value="UTF-8"/>
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".html"/>
</bean>
</property>
</bean>
</property>
</bean>
第五节 STEP5:编写请求处理器 @Controller
- html的相关编写省略
// 声明当前类是Controller类
public class HelloController {
// 当在地址栏输入/时(默认打开时)跳转到"前缀"+ index +"后缀" 这个页面
public String toIndex() {
return "index";
}
}
第四章 Controller
第一节 Request—如何对应请求URL
4.1.1 方式一: 使用视图控制器<mvc:view-controller>
- 语法:
<mvc:view-controller path="/" view-name="index"/>springmvc.xml中配置
| 属性 | 作用 | |
|---|---|---|
| path | URL地址栏 | |
| view-name | 指定的视图(html文件等) |
- 注意⚠️: 使用后会导致@Controller无法识别, 在springmvc.xml中加上
<mvc:annotation-driven/>可以解决 - 示例代码:
<!--springmvc.xml-->
<!--配置视图控制器-->
<mvc:view-controller path="/" view-name="index"/>
<!-- 解决Controller等注解无法正常使用 -->
<mvc:annotation-driven/>
4.1.2 方式二: 使用@RequestMapping
- 语法:
@RequestMapping类/方法上增加
| 属性 | 类型 | 作用 |
|---|---|---|
| value/path | String[] | 设置URL信息, 可以写多个(String[ ]) |
| method | String[] | 为当前URL【类或方法】设置请求方式【POST、DELETE、PUT、GET等】 |
| params | String[] | 为当前URL设置请求参数, 如果URL中未携带 报错400 |
| headers | String[] | 为当前URL设置请求头信息, 如URL中未携带相应请求头 报错404 |
- 注意⚠️:
- ①有
@GetMapping等注解, 等同于@RequestMapping(value=”/emps”, method = RequestMethod.GET); - ②这个注解可以用在类上, 比如类上为(“/people”), 方法上为(“/student”), URL=>/people/student;
- ③这个支持Ant风格的路径: /?, /*, /**分别匹配 任意一个字符, 任意多字符, 多层路径;
- ④params属性 case1:
params = "lastName"URL: ….?lastName=Lisi case2:params = "lastName=MTS"URl:必须是 ….?lastName=MTS才行
- ①有
- 示例代码:
public String saveEmpTest(){
System.out.println("添加员工信息!!!!");
return SUCCESS;
}
第二节 Request—如何获取请求参数
4.2.1 地址栏拼接风格的URL@RequestParam
- 语法: ①对于名字一致的=>直接入参相同名字即可 且 支持POJO; ②名字不一致的=>需要用
@RequestParam指定参数的前面
| 属性 | 作用 |
|---|---|
| value/name String | 设置占位符中的参数名 |
| required Boolean | 设置当前参数是否必须入参【默认值:true】 如果必须入参但没入=>报错; 不必须且没入=>装配null值 |
- ! 关于@RequestParam这个注解
- 注意可以不加@RequestParam这个注解(当名字相同时)
- 如果加了, 这个注解required的参数默认是true, 所以前端不传就是400; 可以设为false解决这个问题,
- 建议:如果名称相同, 就不要加了; 如果因为名称不同加了,请把required改为false
- 示例代码: 普通参数
<a th:href="@{/getRequestNormalParam(username='MTS',
password='12341',
age=4,
money=59.6)}">*地址栏拼接*的request信息</a><br>
public String getRequestMsgNormal(String username,
String password,
Integer age,
Double salary) {
System.out.println("username = " + username);
System.out.println("password = " + password);
System.out.println("age = " + age);
System.out.println("salary = " + salary);
return SUCCESS;
}
- 示例代码: 普通参数
/*POJO*/
public class Student {
String studentName;
Integer studNum;
Character sex;
}
<a th:href="@{/getRequestPojoParam(studentName='Tom',
studNum=23443,
otherMsg='太厉害啦!')}">获取pojo</a>
//注意:
//1.对于pojo中在request拿不到的数据会置为默认值null
//2.可以和其他普通的参数一并传过来, SpringMVC很智能,但注意名字不要和pojo中的字段撞了
public String getRequestMsgPojo(Student student, String otherMsg) {
System.out.println("student = " + student);
System.out.println("otherMsg = " + otherMsg);
return SUCCESS;
}
4.2.2 REST风格的URL@PathVariable
- 语法: ①对于名字一致的=>自动; ②名字不一致的=>需要用
@PathVariable指定 - 位置: ①直接入参相同名字即可; ②参数的前面
- 属性: 同上
- 示例代码:
<a th:href="@{/getRequestNormalParam/1001}">*REST风格*的request信息</a><br>
// 这里如果名字相同可以不用注解
public String getRequestMsgREST( Integer id) {
System.out.println(id);
return SUCCESS;
}
第三节 Request—如何处理请求
4.3.1 获取请求头的内容 @RequestHeader
- 语法:
@RequestHeader("想要获取的在请求头中的属性名称")这种只能获取单个, 如果想获取全部的请求头可以用HttpEntity<T>入参(见下) - 属性: 同上
- 示例代码:
<a th:href="@{/getHeaderMsg}">获取请求头的信息</a>
/*获取"请求头"中的参数 @RequestHeader*/
public String getHeaderMsg( String userAgent,
String host) {
System.out.println("userAgent = " + userAgent);
System.out.println("host = " + host);
return SUCCESS;
}
4.3.2 获取请求体的内容@RequsetBody HttpEntity<T>
- 方式一: 使用注解
@RequsetBody放在参数前面- 语法:
@RequsetBody - 属性: required 默认是true, 就是如果请求体中没有内容, 页面报错400, 改为false就不会报错;
- 注意⚠️:请求体👉的是隐藏的, 所以要用POST提交表单
- 示例代码:
- 语法:
<!--注意要以POST的方式, GET是拼接地址栏, 是获取不到请求体的内容的-->
<form th:action="@{/useRequestBody}" method="post">
lastName:<input type="text" name="lastName"/><br>
password:<input type="text" name="password"/>
<input type="submit" value="使用@RequsetBody注解获取request体"/>
</form>
public String useRequestBody( String body) {
System.out.println("body = " + body);
return SUCCESS;
}
- 方式二: 使用
HttpEntity<T>作为入参变量
<!--同样需要注意用POST的方式-->
<form th:action="@{/useHttpEntity}" method="post">
lastName:<input type="text" name="lastName"/><br>
password:<input type="text" name="password"/>
<input type="submit" value="使用@RequsetBody注解获取request体"/>
</form>
public String useHttpEntity(HttpEntity<String> httpEntity) {
System.out.println("请求头:"+httpEntity.getHeaders());
System.out.println("请求体:"+httpEntity.getBody());
return SUCCESS;
}
第四节 Repond—跳转到相应的视图 【面向用户】
- 从Controller传回DispatchServlet的, 无论String, View的返回值🔙, 最后都会封装为ModelAndView类型
- 其中Model保存数据, View保存视图
4.4.1 方式一: 使用String返回
public String toSuccess() {
return "success";
}
4.4.2 方式二: 使用ModelAndView返回ModelAndView
public ModelAndView moduleAndViewRespond() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("username", "Tom"); // 在request域中存值
//跳转到哪个视图 (等同于原来返回类型String , return "success";
modelAndView.setViewName("success");
return modelAndView;
}
第五节 Repond—返回JSON格式或流【面向前端开发人员】
4.5.1 返回流直接打印在页面中@ResponseBody
- 语法:
@ResponseBody, 方法只能返回String类型 - 位置: 书写在class类上面【当前类所有方法,均返回文本,不跳转页面】or 书写在方法上面
<h2>使用@ResponseBody注解的方式🔙获取响应体</h2>
<h3>响应体, 可以理解为在页面上展示文字</h3>
<a th:href="@{/responseBody}"> 跳转</a>
public String responseBody(HttpServletRequest request, HttpServletResponse response) {
// 因为使用了@ResponseBody注解, 所以这个方法的返回值回直接打印在页面上(仅限String)
return "HelloWord";
}
4.5.2 返回JSON格式的页面信息@ResponseBody
- 语法:
@ResponseBody配置了JSON相关jar包后, 可以返回任意Object类型的数据, 这些数据都会以JOSN页面(content-type=application/json;charset=UTF-8) 的形式返回 - 步骤
- STEP1: 配置pom.xml导入jackson-databind jar包
<!-- jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
- STEP2: 在springmvc.xml中添加
<mvc:annotation-driven/> - STEP3: 在添加了
@ResponseBody注解的类or方法上使用
<h2>转换为Json格式</h2>
<a th:href="@{/toJson}">跳转</a>
public Employee toJson(){
Employee employee = new Employee("Tom", "234@qq.dcom", 23.3);
return employee;
}
第六节 Repond—如何向Request域中存值
4.6.1 方式一: 使用原生servlet-api
- 语法: 这个可以向四大域中存(毕竟是原生api)
public String toSuccess(HttpServletRequest request,
HttpServletResponse response) {
// 在request域中存值
request.setAttribute("key", "value");
//在session域中存值
request.getSession().setAttribute("key", "value");
// 在application域中存值
request.getServletContext().setAttribute("key", "value");
// 添加新的cookie
Cookie cookie = new Cookie("key", "value");
response.addCookie(cookie);
return "success";
}
4.6.2 方式二: ModelAndView作为返回值
- 语法: 默认存在request域中;
public ModelAndView moduleAndViewRespond() {
ModelAndView modelAndView = new ModelAndView();
// 在request域中存值
modelAndView.addObject("username", "Tom");
modelAndView.setViewName("success");
return modelAndView;
}
4.6.3 方式三: 使用Map, Model, ModelMap入参
- 语法: 三种都是默认存在request域中;
// java.util.Map
public String mapRespond(Map<String, Object> map, Model model, ModelMap modelMap) {
map.put("password", 123412); // 在request域中存值
model.addAttribute("gender", "♂"); // 在request域中存值
modelMap.addAttribute("class", "1001"); // 在request域中存值
return "success";
}
第七节 Repond—响应的方式
4.7.1 转发
- 语法: 默认就是转发
4.7.2 重定向
- 语法: return “**redirect:/**xxx.html”;
- 注意⚠️: 重新向用的不是Thymeleaf所以**不能只传递逻辑路径,**
redirect:/中的/会被解析为servletContext;
/*@Controller*/
public String redirectToSuccess() {
return "redirect:/pages2/success.html";
}
<!-springmvc.xml--->
<mvc:view-controller path="/redirectToSuccess" view-name="redirect:/pages2/success.html"/>
第五章 处理请求和响应乱码
第一节 实现SpringMVC处理请求和响应乱码CharacterEncodingFilter
- 思路: SpringMVC处理源码和JavaWeb我们手动处理的思路一致, 都是写个Filter设置字符编码集
- 步骤: 在web.xml中创建这个CharacterEncodingFilter并设置参数
- 注意⚠️: 必须是第一过滤器位置
<!--web.xml-->
<!--必须是第一过滤器位置-->
<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>
<!--只用配置request的编码, respond已在底层配置好了-->
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
第六章 文件的上传和下载
第一节 实现文件下载ResponseEntity<T>
6.1.1 STEP1: 编写Controller
- STEP1: 获取文件的以字节数组byte[]的形式
- STEP2: 设置响应头
- STEP3: 创建ResponseEntity并设置状态码
<h1>文件下载</h1>
<!--这里注意,Thymeleaf拼接地址栏等于号=后面要用引号, -->
<a th:href="@{/downloadFile(filename='chang(2).mp4')}">"chang(2).mp4"</a><br>
<a th:href="@{/downloadFile(filename='cover.png')}">"cover.png"</a><br>
<a th:href="@{/downloadFile(filename='遗留问题.md')}">"遗留问题.md"</a>
public ResponseEntity<byte[]> downloadFile(HttpServletRequest request, String filename) {
ResponseEntity<byte[]> responseEntity = null;
/*STEP1: 获取文件的以字节数组byte[]的形式*/
//使用ServletContext上下文路径获取指定文件的正式绝对路径
String fileRealPath = request.getServletContext().
getRealPath("WEB-INF/download/" + filename);
try (InputStream inputStream = new FileInputStream(fileRealPath)) {
// 创建合适大小的byte[]数组
byte[] bytes = new byte[inputStream.available()];
// 将文件以字节的形式读入bytes数组
inputStream.read(bytes);
/*STEP2: 设置响应头*/
HttpHeaders headers = new HttpHeaders();
//设置要下载的文件名,并告诉浏览器是下载不是打开
headers.add("Content-Disposition", "attachment;filename=" + filename);
headers.setContentDispositionFormData("attachment",
new String(filename.getBytes("utf-8"), "ISO-8859-1"));
/*STEP3: 创建ResponseEntity并设置状态码*/
responseEntity = new ResponseEntity<>(bytes, headers, HttpStatus.OK);
} catch (Exception e) {
System.out.println(e);
}
return responseEntity;
}
第二节 实现文件上传MultipartFile
6.2.1 STEP1: 配置pom.xml
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
6.2.2 STEP2: 在springmvc.xml中创建并配置CommonsMultipartResolve解析器
- 注意⚠️: 这个<bean>的id必需是multipartResolver
<!--springmvc.xml-->
<!--当前bean 的id 值必须是 multipartResolver-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置字符集-->
<property name="defaultEncoding" value="utf-8"></property>
</bean>
6.2.3 STEP3: 准备文件上传的HTML表单(三必须)
- 表单提交方式 必须为POST
- 表单属性 必须有enctype=multipart/form-data
- 表单内容 必须包含文件域【type=file】
<form th:action="@{/uploadFile}"
method="post"
enctype="multipart/form-data">
<!--这里的名字要和MultipartFile userUploadFile一致, @PathVariable的知识-->
上传文件: <input type="file" name="userUploadFile"/>
<input type="submit" name="提交"/>
</form>
6.2.4 STEP4: 编写Controller
- STEP1: 获取目标文件的原文件名称
- STEP2: 获取目标文件需要保存的地址
- STEP3: 将用户目标文件移动到需要保存的位置
public String uploadFile(MultipartFile userUploadFile, HttpServletRequest request) throws IOException {
// 目标文件=用户上传的文件, 在这里是SpringMVC封装为MultipartFile这个类了
// STEP1: 获取目标文件的原文件名称
System.out.println(userUploadFile);
String filename = userUploadFile.getOriginalFilename();
/* STEP2: 获取目标文件需要保存的地址
e.g.最终文件被保存在
D://IntelliJIDEAWorkBench//StudySpringMVC//Project_7.25_Afternoon//target//Project_7.25_Afternoon//WEB-INF//upload//遗留问题.md
*/
String savePath = request.getServletContext().getRealPath("/WEB-INF/upload/") + "/" + filename;
// STEP3: 将用户目标文件移动到需要保存的位置
userUploadFile.transferTo(new File(savePath));
return "success";
}
第三节 优化文件上传
6.3.1 允许同名文件上传
- 使用UUID解决文件名字重复的问题
UUID uuid = UUID.randomUUID(); // 使用UUID解决文件名字重复的问题
String savePath = request.getServletContext().getRealPath("/WEB-INF/upload/") + "/" + uuid + filename;
- 使用时间戳解决文件名字重复的问题
//自1970年1月1日00:00:00 GMT(UTC时间)起至 当前时间的 毫秒数(ms)
long l = System.currentTimeMillis();
String savePath = request.getServletContext().getRealPath("/WEB-INF/upload/") + "/" + l + filename;
6.3.2 文件上传大小
- 位置: STEP2的springmvc.xml CommonsMultipartResolver
- 语法: maxUploadSize; 单位为byte
- 1 KB = 1024 bytes
- 1 MB = 1024 KB = 1,048,576 bytes
- 1 GB = 1024 MB = 1,073,741,824 bytes
<!--springmvc.xml-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置字符集-->
<property name="defaultEncoding" value="utf-8"></property>
<!-- 设置总文件的大小(byte)-->
<property name="maxUploadSize" value="102400"></property>
</bean>
第七章 拦截器

第一节 SpringMVC拦截器
- 语法: 实现
HandlerInterceptor接口+spingmvc.xml中装配; 实现拦截器两种方式 - 实现接口:Handlerinterceptor
继承适配器类:HandlerinterceptorAdapter过时!- 辨析: 拦截器与过滤器区别
| 名称 | 归属 | 作用 | 执行时机及次数 |
|---|---|---|---|
| Filter | web服务器组件 | 过滤Servlet请求 | 1.Servlet前 2.Servlet后 |
| Interceptor | SpringMVC框架组件 | 拦截Controller请求 | 1.Servlet之后, Controller之前 2.Controller之后, Servlet之前执行 3.DispatcherServlet之后 |
- 多个拦截器的执行流程

- 关于拦截器preHandle()方法返回值对拦截器的影响 【对于某一个拦截器来说, 遵循以下规定(所有前面加上”当前”两个字)】
| preHandle() | postHandle() | afterCompletion() |
|---|---|---|
| 返回True | ①在其之后如果没有返回false的preHandle()就会执行,否则不执行 ②如果有期间Controller有异常, 不会执行 |
一定执行 |
| 返回false | 不执行 | 不执行 |
第二节 实现SpringMVC拦截器 HandlerInterceptor
7.2.1 STEP1: 实现HandlerInterceptor接口, 并重写其三个方法
public class TestInterceptor1 implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
System.out.println("TestInterceptor11111=>preHandle()");
return false;
}
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("TestInterceptor11111=>postHandle()");
}
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
System.out.println("TestInterceptor11111=>afterCompletion()");
}
}
7.2.2 STEP2: 在springmvc.xml中装配<mvc:interceptors>
- 一个拦截器拦截一个Controller
<!--springmvc.xml-->
<!--装配了一个拦截器, 用于拦截/interceptor_page的Controller-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/interceptor_page"/>
<ref bean="testInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
- 多个拦截器拦截一个Controller
<!--springmvc.xml-->
<!--装配了两个拦截器, 都是用于拦截/interceptor_page的Controller-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/interceptor_page"/>
<ref bean="testInterceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/interceptor_page"/>
<ref bean="testInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
- 一个拦截器拦截所有Controller
<!--springmvc.xml-->
<!--因为没有写是拦截哪个URL(哪个Controller)所以拦截所有Controller-->
<mvc:interceptors>
<ref bean="testInterceptor1"/>
</mvc:interceptors>
第八章 异常处理器
SpringMVC中有两个异常处理器实现类
- DefaultHandleExceptionResolver:默认异常处理器,默认开启,可以支持10+多种异常处理
- SimpleMappingExceptionResolver: 自定义异常处理, ==将指定的异常映射到指定页面==
第一节 实现SpringMVC异常处理器SimpleMappingExceptionResolver
- 语法:
SimpleMappingExceptionResolver类中有两个关键成员变量private Properties exceptionMappings;是配置xxx异常=>跳转xxx页面的private String exceptionAttribute;异常信息的key会放到request域中(默认名字是exception)
- 注意⚠️: 配置后任意Controller中出现对应的问题都会跳转
8.1.1 STEP1: 在springmvc.xml中装配SimpleMappingExceptionResolver
<!--springmvc.xml-->
<!--配置异常处理器 SimpleMappingExceptionResolver-->
<bean id="simpleMappingExceptionResolver"
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<!--配置xxx异常=>跳转xxx页面, 注意使用<prop>标签配置properties属性-->
<props>
<prop key="java.lang.ArithmeticException">error_page</prop>
<prop key="java.lang.NullPointerException">error_page</prop>
</props>
</property>
<!-- 默认的名字为exception, 这里是起别名为ex-->
<property name="exceptionAttribute" value="ex"></property>
</bean>
8.1.2 STEP2: 可以①跳转到指定页面 ②在页面中获取错误信息
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>异常处理器</title>
</head>
<body>
<h1>异常处理器</h1>
<!--从request域中获取错误信息-->
异常信息: <p th:text="${ex}">异常信息s</p>
</body>
</html>
第九章 SpringMVC工作原理

- 请求【浏览器向服务器发送请求,携带URL (/testSpringMVCWorking) 】
- 通过DispatcherServlet加载SpringMVC容器对象,从而加载Controller【请求处理器】
- 加载三个对象【HandlerMapping、 HandlerExecutionChain、HandlerAdapter】
第一节 SpringMVC工作原理1【URL不存在】
- 判断URL是否存在【不存在】
- 不存在:判断是否配置mvc:default-servlet-handler
- 配置:出现404现象,同时提示URL不可用
- 未配置:出现404现象,但不会提示
- 不存在:判断是否配置mvc:default-servlet-handler
第二节 SpringMVC工作原理2 【URL存在】
- 判断URL是否存在【存在】
- 执行Interceptor【拦截器】第一个方法【preHandle()】
//DispatcherServlet的1056行代码
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
- 执行Controller 【请求处理器】中的相应方法【处理请求,做出响应】
//DispatcherServlet的1061代码
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
- 判断Controller中是否存在异常
- 存在异常
- 通过HandlerExceptionResolver异常处理器处理异常, 并返回ModelAndView
- 不存在异常
- Controller返回ModelAndView
- 触发拦截器第二个方法【postHandle()】
- 存在异常
- 通过ViewResolver 【视图解析器对象】将View 【视图对象】从ModelAndView中解析出来
//DispatcherServlet的1435行代码
if (this.viewResolvers != null) {
for (ViewResolver viewResolver: this.viewResolvers) {
view view = viewResolver.resolveviewName(viewName, locale);
if (view != null) {
return view;
}
}
}
- View对象开始渲染视图
- 将数据共享
- 路径跳转
- 执行拦截器第三个方法【afterCompletion()】
//DispatcherServlet的1157行代码
if (mappedHandler != null) {
// Exception (if any) is already handled..
mappedHandler.triggerAftercompletion(request, response, null);
}
- 响应
第十章 SSM框架整合
第一节 Spring+SpringMVC整合步骤
10.1.1 导入jar包
- springmvc的jar包
<!--spring-webmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<!-- 导入thymeleaf与spring5的整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
<!--servlet-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
10.1.2 配置文件
- web.xml
- 注册CharacterEncodingFilter,解决请求乱码问题
- 注册HiddenHttpMethodFilter,支持PUT&DELETE提交【REST风格】
- 注册DispatcherServlet 【前端控制器】,管理springMVC容器对象
- 注册一个上下文参数【contextConfigLocation】 ,设置applicationContext.xml配置文件路径
- 注册ContextLoaderListener,管理spring容器对象
<!--注册CharacterEncodingFilter,解决请求乱码问题-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--注册HiddenHttpMethodFilter,支持PUT&DELETE提交【REST风格】-->
<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>
<!--注册DispatcherServlet 【前端控制器】,管理springMVC容器对象-->
<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>
<!--注册一个上下文参数【contextConfigLocation】 ,设置applicationContext.xml配置文件路径-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--注册ContextLoaderListener,管理spring容器对象-->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
- springmvc.xml
- 开启组件扫描【只扫描Controller层】
- 装配视图解析器
- 装配视图控制器【view-controller】
- 装配default-servlet-handler,解决静态资源加载问题
- 装配annotation-driven,解决后续问题
<!--开启组件扫描【只扫描Controller层】-->
<context:component-scan base-package="com.mts">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--装配视图解析器-->
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<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="characterEncoding" value="UTF-8"/>
<property name="prefix" value="WEB-INF/pages"/>
<property name="suffix" value=".html"/>
</bean>
</property>
</bean>
</property>
</bean>
<!--装配视图控制器【view-controller】-->
<mvc:view-controller path="/index" view-name="index"/>
<!--装配default-servlet-handler,解决静态资源加载问题-->
<mvc:default-servlet-handler/>
<!--装配annotation-driven,解决后续问题-->
<mvc:annotation-driven/>
<!---->
<!---->
<!---->
- applicationContex.xml
- 开启组件扫描【排除Controller层】
<!--开启组件扫描【排除Controller层】-->
<context:component-scan base-package="com.mts">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
第二节 Spring+Mybatis整合步骤
10.2.1 导入jar包
- spring的jar包
- mybatis的jar包
- spring与mybatis整合jar包
<!--spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.1</version>
</dependency>
<!--spring-orm-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.1</version>
</dependency>
<!--spring-aspects-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.1</version>
</dependency>
<!--导入druid的jar包-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--导入mysql的jar包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!--mybatis核心包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!--pagehelper分页 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.8</version>
</dependency>
<!--mybatis-spring-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
10.2.2 配置文件
- applicationContex.xml
- 开启组件扫描【排除Controller层】
- 加载外部属性文件【db.properties】
- 装配数据源【DruidDataSource】
- 装配事务管理器【DataSourceTransactionManager】
- 开启声明式事务管理注解支持
- 装配SqlSessionFactoryBean,管理SqlSessionFactory
- 装配MapperScannerConfigurer,管理Mapper代理对象
#key=value
db.driverClassName=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/test_mybatis?serverTimezone=UTC
db.username=root
db.password=root
# I advise you better add following into you configuration (2024-07-28)
# Initialize connection
db.initialSize=10
# Maximum number of connections
db.maxActive=50
# Minimum free connection
db.minIdle=5
# Timeout wait time(ms)
db.maxWait=5000
<!--开启组件扫描【排除Controller层】-->
<context:component-scan base-package="com.mts">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--加载外部属性文件【db.properties】-->
<context:property-placeholder location="classpath:db.properties"/>
<!--装配数据源【DruidDataSource】-->
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="driverClassName" value="${db.driverClassName}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
<property name="initialSize" value="${db.initialSize}"/>
<property name="maxActive" value="${db.maxActive}"/>
<property name="minIdle" value="${db.minIdle}"/>
<property name="maxWait" value="${db.maxWait}"/>
</bean>
<!--装配事务管理器【DataSourceTransactionManager】-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--开启声明式事务管理注解支持-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!--装配SqlSessionFactoryBean,管理SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--设置数据源-->
<property name="dataSource" ref="dataSource"></property>
<!--设置mybatis-config.xml 核心配置文件路径-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--设置类型别名-->
<property name="typeAliasesPackage" value="com.mts.pojo"></property>
<!--设置映射文件路径-->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
</bean>
<!--装配MapperScannerConfigurer,管理Mapper代理对象-->
<mybatis-spring:scan base-package="com.mts.mapper"/>
- mybatis-config.xml
- settings 标签
- pluggins 标签
<configuration>
<!--settings 标签-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
<!--pluggins 标签-->
<plugins>
<!--配置PageHelper分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
</configuration>
第一节 Spring+SpringMVC整合步骤
10.1.1 导入jar包
- springmvc的jar包
10.1.2 配置文件
- web.xml
* 注册CharacterEncodingFilter,解决请求乱码问题
* 注册HiddenHttpMethodFilter,支持PUT&DELETE提交【REST风格】
* 注册DispatcherServlet 【前端控制器】,管理springMVC容器对象
* 注册一个上下文参数【contextConfigLocation】 ,设置applicationContext.xml配置文件路径
* 注册ContextLoaderListener,管理spring容器对象 - springmvc.xml
* 开启组件扫描【只扫描Controller层】
* 装配视图解析器
* 装配视图控制器【view-controller】
* 装配default-servlet-handler,解决静态资源加载问题
* 装配annotation-driven,解决后续问题 - applicationContex.xml
* 开启组件扫描【排除Controller层】
第二节 Spring+Mybatis整合步骤
10.2.1 导入jar包
- spring的jar包
- mybatis的jar包
- spring与mybatis整合jar包
10.2.2 配置文件
- applicationContex.xml
* 开启组件扫描【排除Controller层】
* 加载外部属性文件【db.properties】
* 装配数据源【DruidDataSource】
* 装配事务管理器【DataSourceTransactionManager】
* 开启声明式事务管理注解支持
* 装配SqlSessionFactoryBean,管理SqlSessionFactory
* 装配MapperScannerConfigurer,管理Mapper代理对象 - mybatis-config.xml
* settings 标签
* pluggins 标签
- Title: 2.SpringMVC学习
- Author: 明廷盛
- Created at : 2026-02-02 05:32:25
- Updated at : 2025-02-15 16:42:00
- Link: https://blog.20040424.xyz/2026/02/02/😼Java全栈工程师/第三部分 SSM/2.SpringMVC学习/
- License: All Rights Reserved © 明廷盛


