1. SpringMVC 快速入门
1.1 导入 SpringMVC 相关坐标
pom.xml:
<dependencies>
<!--Spring坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--SpringMVC坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--Servlet坐标-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!--Jsp坐标-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
1.2 创建 Controller 类并使用注解配置映射地址
UserServlet.java:
@Controller("userServlet")
public class UserServlet {
@RequestMapping("/quick")
public String running() {
System.out.println("service...");
return "/index.jsp";
}
}
1.3 配置 SpringMVC 核心文件 spring-mvc.xml
spring-mvc.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 只扫描controller层下的Servlet组件 -->
<context:component-scan base-package="com.one.controller"/>
</beans>
1.4 配置 SpringMVC 核心控制器 DispatcherServlet
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!--SCHEME约束-->
<!--xmlns: xml namespace-->
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
...
...
...
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 将spring-mvc.xml加载进DispatcherServlet控制器 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.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>
1.5 客户端发起请求测试
2. SpringMVC 组件解析
2.1 SpringMVC 执行流程
- 用户发送请求至前端控制器 DispatcherServlet
- DispatcherServlet 收到请求调用 HandlerMapping 处理器映射器
- 处理器映射器找到具体的处理器(可以根据 xml 配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet
- DispatcherServlet 调用 HandlerAdapter 处理器适配器
- HandlerAdapter 经过适配调用具体的处理器(Controller:也叫后端控制器)
- Controller 执行完成返回 ModelAndView
- HandlerAdapter 将 controller 执行结果 ModelAndView 返回给 DispatcherServlet
- DispatcherServlet 将 ModelAndView 传给 ViewResolver 视图解析器
- ViewResolver 解析后返回具体 View
- DispatcherServlet 根据 View 进行渲染视图(即将模型数据填充至视图中),DispatcherServlet 响应用户
2.2 SpringMVC 组件解析
-
前端控制器 DispatcherServlet:用户请求到达前端控制器,它就相当于 MVC 模式中的 C,DispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,DispatcherServlet 的存在降低了组件之间的耦合性。
-
处理器映射器 HandlerMapping:HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
-
处理器适配器 HandlerAdapter:通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
-
处理器 Handler:它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由Handler 对具体的用户请求进行处理。
-
视图解析器 ViewResolver:View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
-
视图 View:SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView等。最常用的视图就是 jsp。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面
2.3 @RequestMapping 详解
作用:用于建立请求 URL 和处理请求方法之间的映射关系
位置:
- 类:请求 URL 的第一级访问目录,此处若不写则相当于应用的根目录
/
- 方法:请求 URL 的第二级访问目录,与类上的使用 @RequestMapping 标注的一级目录一起组成访问虚拟路径
属性:
- value:用于指定请求的 URL ,它和 path 属性的作用是一样的
- method:用于指定请求的方式
- RequestMethod.GET:请求方法只能是 GET(URL 地址请求为 GET)
- RequestMethod.POST:请求方法只能是 POST
- ...
- params:用于指定限制请求参数的条件,它支持简单的表达式,要求请求参数的 key 和 value 必须和配置的一模一样
- params = {"accountName"}:表示请求参数必须有 accountName
- params = {"moeny!100"}:表示请求参数中 money 不能是 100
- ...
@Controller("userServlet")
@RequestMapping("/userServlet")
public class UserServlet {
@RequestMapping(value = "/quick", method = RequestMethod.GET, params = {"username"})
public String save() {
System.out.println("SpringMVC...");
return "/pages/success.jsp";
}
}
2.4 视图解析器 InternalResourceViewResolver
SpringMVC 有默认组件配置,默认组件都是 DispatcherServlet.properties 配置文件中配置的,该配置文件地址 org/springframework/web/servlet/DispatcherServlet.properties,该文件中配置了默认的视图解析器,如下:
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
其中便有默认的视图解析器:
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
自定义配置 InternalResourceViewResolver:
<!-- 配置内部资源视图解析器! -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 跳转的页面前缀 -->
<property name="prefix" value="/pages/"/>
<!-- 跳转的页面后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
此时,return success;
等价于 return /pages/success.jsp
:
3. SpringMVC 数据请求与响应
3.1 数据响应
数据响应方式:
- 页面跳转
- 直接返回字符串
- 通过 ModelAndView 对象返回
- 回写数据
- 直接返回字符串
- 返回对象或集合
3.1.1 页面跳转-1:字符串跳转
@RequestMapping("/quick")
public String quickMethod(){
return "/index.jsp";
}
3.1.2 页面跳转-2:ModelAndView 对象
success.jsp:
1)形式一
@RequestMapping("/modelAndView")
public ModelAndView modelAndView() {
ModelAndView modelAndView = new ModelAndView();
/* 数据模型,键值对形式,可在相应页面进行调用 */
modelAndView.addObject("username", "wow");
/* 设置视图 */
modelAndView.setViewName("success");
return modelAndView;
}
2)形式二
@RequestMapping("/modelAndView2")
public ModelAndView modelAndView2(ModelAndView modelAndView) {
modelAndView.addObject("username", "Q");
modelAndView.setViewName("success");
return modelAndView;
}
3)形式三
@RequestMapping("/modelAndView3")
public String modelAndView3(Model model) {
model.addAttribute("username", "K");
return "success";
}
3.1.3 重定向(请求) & 转发(请求)
⭐重定向请求:
注意,重定向的只能是请求而不能是页面!
@RequestMapping("/modelAndView4")
public String modelAndView4() {
...
// 重定向请求路径
return "redirect:anotherRequest";
}
实现效果:URL 由 localhost:8080/modelAndView4
==> localhost:8080/anotherRequest
❗ 然后由处理 \anotherRequest
请求的 Controller 处理(页面跳转了)
⭐转发:
注意,转发的只能是请求而不能是页面!
@RequestMapping("/modelAndView5")
public String modelAndView5() {
...
// 转发
return "forward:anotherRequest";
}
实现效果:URL 仍是 localhost:8080/modelAndView4
❗ 但请求的是 /localhost:8080/anotherRequest
的 Controller 处理(页面没跳转)
3.1.4 回写数据-1:回写字符串
@ResponseBody:将需要回写的字符串直接返回,但此时需要通过 @ResponseBody 注解告知 SpringMVC 框架,方法返回的字符串而不是跳转页面。
1)形式一
@RequestMapping("/data1")
public void dataWrite1(HttpServletResponse httpServletResponse) throws IOException {
httpServletResponse.getWriter().write("Hello SpringMVC!");
}
2)形式二
@RequestMapping("/data2")
@ResponseBody
public String dataWrite2() {
// 直接返回数据, 但是需要注解以标识该字符串为数据, 而非页面:(@ResponseBody)
return "Data...";
}
3.1.5 回写数据-2:对象或集合
3)形式三
pom.xml:
<!-- Gson坐标 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
UserServlet.java:
@RequestMapping("/data3")
@ResponseBody
public String jsonDataWrite3() {
User user = new User();
user.setId(3);
user.setUsername("w");
user.setPassword("123456");
// 使用 JSON 格式返回(导入坐标): https://juejin.cn/post/6967516960451985416#heading-20 (JSON详解)
Gson gson = new Gson();
String json = gson.toJson(user, User.class);
return json;
}
4)形式四
pom.xml:
<!-- Jackson坐标-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.11.0</version>
</dependency>
spring-mvc.xml:
<!-- 配置处理器映射器! -->
<bean id="requestMappingHandlerAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
</list>
</property>
</bean>
UserServlet.java:
@RequestMapping("/data4")
@ResponseBody
public User jsonDataWrite4() {
User user = new User();
user.setId(1);
user.setUsername("w");
user.setPassword("123456");
// 通过配置 RequestMappingHandlerAdapter,即可直接返回对象或集合,底层自动转换为 JSON 格式!
return user;
}
测试结果:
5)形式五(最终形式)
在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。使用 <mvc:annotation-driven>
自动加载 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter,可用在 Spring-mvc.xml 配置文件中使用 <mvc:annotation-driven>
替代注解处理器和适配器的配置。同时使用 <mvc:annotation-driven>
默认底层就会集成 jackson 进行对象或集合的 json 格式字符串的转换。
引入 mvc 命名空间:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 只扫描controller层下的Servlet组件 -->
<context:component-scan base-package="com.one.controller"/>
<!-- MVC の 注解驱动 -->
<mvc:annotation-driven/>
</beans>
UserServlet.java:
@RequestMapping("/data5")
@ResponseBody
public User jsonDataWrite4() {
User user = new User();
user.setId(3);
user.setUsername("w");
user.setPassword("123456");
return user;
}
3.1.6 @ResponseBody
返回数据:String
vs Object
💦最常见的响应数据有两种:一种是 String 格式的数据,一种是 Object 类型的数据。那么若直接在页面上打印这两种数据有什么区别呢?
🔥 String 格式的数据自动转换为 html 格式:
🔥 Object 格式的数据自动转换为 JSON 数据(底层自动使用 Jackson 转换为 JSON 格式):
3.2 数据请求的四大类型
客户端请求参数的格式是:name=value&name=value…
服务器端要获得请求的参数,有时还需要进行数据的封装,SpringMVC 可以接收如下类型的参数:
- 基本类型参数
- POJO 类型参数
- 数组类型参数
- 集合类型参数
3.2.1 基本数据类型
Controller 中的业务方法的参数名称要与请求参数的 name 一致,参数值会自动映射匹配。
URL 请求:
SpringMVC 是该项目模块的名称噢~
http://localhost:8080/SpringMVC/userServlet/params1?username=zhangsan&id=1
UserServlet.java:
@RequestMapping(value = "/params1", params = {"username", "id"})
@ResponseBody
public void requestParam1(String username, int id) {
/* @ResponseBody:仍然需要! */
System.out.println(id + username);
}
3.2.2 POJO 类型参数
Controller 中的业务方法的 POJO 参数的属性名与请求参数的 name 一致,参数值会自动映射匹配。
URL 请求:
http://localhost:8080/SpringMVC/userServlet/params2?username=zhangsan&age=19
Person.java:
public class Person {
private String username;
private int age;
// setter、getter
}
UserServlet.java:
@RequestMapping("/params2")
@ResponseBody
public void requestParam2(Person person) {
// String username, int age
System.out.println(person);
}
3.2.3 数组类型参数
Controller 中的业务方法数组名称与请求参数的 name 一致,参数值会自动映射匹配。
URL 请求:
http://localhost:8080/SpringMVC/userServlet/params3?arr=aaa&arr=bbb&arr=ccc
UserServlet.java:
@RequestMapping("/params3")
@ResponseBody
public void requestParam3(String[] arr) {
System.out.println(Arrays.asList(arr));
}
3.2.4 集合类型参数
当使用 Ajax 提交时,可以指定 contentType 为 json 形式,那么在方法参数位置使用 @RequestBody 可以直接接收集合数据而无需使用 POJO 进行包装。
1. AjaxRequest.jsp:
2. 静态资源访问的开启
SpringMVC 的前端控制器 DispatcherServlet 的 url-pattern 配置的是 /
,代表对所有资源(动态、静态)都进行过滤操作,我们可以通过以下两种方式指定过滤静态资源:
1)方式一:
<mvc:resources mapping="/js/**" location="/js/"/>
mapping="/js/**"
:浏览器的 URI 访问地址
location="/js/"
:静态资源实际的相对路径位置
比如访问 localhost:8080/SpringMVC/js/main.js,这个 URI 对于的 mapping 就是 /js/main.js,它是在设置的 mapping 的范围内的,随后就去拿到对应的实际路径 location 中的静态资源,那么静态资源这样就可以访问到了。
2)方式二:
<mvc:default-servlet-handler/>
3. UserServlet.java:
@RequestMapping("/params4")
@ResponseBody
public void requestParams4(@RequestBody List<Person> personList) {
// 1.Ajax使用需要jQuery导入
// 2.接受集合类型的参数需要注解: @RequestBody
System.out.println(personList);
}
4. URL 请求:
http://localhost:8080/SpringMVC/AjaxRequest.jsp
3.3 访问静态资源
详见 3.2.4 小节第 2 小点
3.3.1 方式一
<mvc:resources mapping="/js/**" location="/js/"/>
3.3.2 方式二
<mvc:default-servlet-handler/>
3.4 配置全局过滤器
POST 请求时,数据会出现乱码,我们可以设置一个过滤器来进行编码过滤
<!-- 配置全局乱码过滤器 -->
<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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.5 参数绑定注解 @RequestParam
注解 @RequestParam 参数:
- value:请求参数的名称
- required:此在指定的请求参数是否必须包括,默认是 true,提交时如果没有此参数则报错
- defaultValue:当没有指定请求参数时,则使用指定的默认值赋值
URL 请求:
UserServlet.java:
@RequestMapping("/param")
@ResponseBody
public void param(@RequestParam(value = "name", required = false, defaultValue = "K") String username) {
// 若请求参数没有name, 则默认打印name=K
System.out.println(username);
}
3.6 获取 Resultful 风格的参数
Restful 是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。
Restful 风格的请求是使用 “url + 请求方式” 表示一次请求目的的,HTTP 协议里面四个表示操作方式的动词如下:
- GET:用于获取资源;/user/1 GET:得到 id = 1 的 user
- POST:用于新建资源;/user/1 DELETE:删除 id = 1 的 user
- PUT:用于更新资源;/user/1 PUT:更新 id = 1 的 user
- DELETE:用于删除资源; /user POST:新增 user
上述 url 地址 /user/1 中的 1 就是要获得的请求参数,在 SpringMVC 中可以使用占位符进行参数绑定。地址 /user/1 可以写成/user/{id},占位符 {id} 对应的就是 1 的值;在业务方法中我们可以使用 @PathVariable 注解进行占位符的匹配获取。
URL 请求:
http://localhost:8080/SpringMVC/userServlet/result_1/zq/19
UserServlet.java:
@RequestMapping("/result_1/{username}/{age}")
@ResponseBody
public void result_1(@PathVariable("username") String name, @PathVariable(value = "age", required = false) int age) {
System.out.println(name + ": " + age);
}
3.7 自定义类型转换器
SpringMVC 默认已经提供了一些常用的类型转换器,例如:客户端提交的字符串转换成 int 类型进行参数设置;但不是所有的数据类型都提供了转换器,没有提供的就需要自定义转换器,例如:日期类型的数据就需要自定义转换器。
URL 请求:
UserServlet.java:
@RequestMapping("/converter")
@ResponseBody
public void typeConverter(Date date) {
System.out.println(date);
}
3.7.1 自定义转换器类实现 Converter 接口
package com.one.converter;
import org.springframework.core.convert.converter.Converter;
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String dateStr) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = sdf.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
3.7.2 在配置文件中声明转换器
spring-mvc.xml:
<bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.one.converter.DateConverter"/>
</list>
</property>
</bean>
3.7.3 在 <annotation-driven>
中引用转换器
spring-mvc.xml:
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>
重新访问:
3.8 获取 Servlet 相关 API
SpringMVC 支持使用原始 Servlet_API 对象作为控制器方法的参数注入...
@RequestMapping("/servlet_api")
@ResponseBody
public void api(HttpServletRequest request, HttpServletResponse response, HttpSession httpSession) {
//TODO
}
3.9 获取请求头
3.9.1 @RequestHeader
@RequestMapping("/requestHead")
@ResponseBody
public void requestheader(@RequestHeader("User-Agent") String userAgent) {
// Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4542.2 Safari/537.36
System.out.println("User-Agent: " + userAgent);
}
3.9.2 @CookieValue
@RequestMapping("/cookie")
@ResponseBody
public void cookie(@CookieValue("JSESSIONID") String jsessionId) {
// BC0B46B49F5C28D97D8CBE7BC144061C
System.out.println(jsessionId);
}
3.10 文件上传
文件上传客户端的三要素:
- 表单项 type=“file”
- 表单的提交方式是 post
- 表单的 enctype 属性是多部分表单形式,及 enctype=“multipart/form-data”
<form action="${pageContext.request.contextPath}/userServlet/file1" method="post" enctype="multipart/form-data">
<input type="text" name="username"/><br>
<input type="file" name="multi"/><br>
<input type="file" name="multi"/><br>
<input type="submit" value="提交">
</form>
文件上传步骤:
1. 导入fileupload & io 相关依赖
pom.xml:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
2. 配置文件上传解析器
spring-mvc.xml:
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上传文件的编码类型 -->
<property name="defaultEncoding" value="UTF-8"/>
<!-- 上传文件总大小 -->
<property name="maxUploadSize" value="1024000"/>
<!-- 单文件大小上限 -->
<property name="maxUploadSizePerFile" value="102400"/>
<!--...-->
</bean>
3. Controller 编写文件处理代码
@RequestMapping("/file1")
@ResponseBody
public void file1(String username, MultipartFile[] multi) throws IOException {
System.out.println(username);
for (MultipartFile file : multi) {
// 获取文件名称
String originalFilename = file.getOriginalFilename();
// 保存文件至磁盘指定位置
file.transferTo(new File("D:\\" + originalFilename));
}
}
name 属性一致:
URL 请求:
4. SpringMVC 拦截器
SpringMVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。、
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(Interceptor Chain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用;拦截器也是 AOP 思想的具体实现。
区别 | 过滤器 | 拦截器 |
---|---|---|
使用范围 | Servlet 规范中的一部分,任何 JavaWeb 工程都可以使用 | SpringMVC 框架的,只有使用了 SpringMVC 框架的工程才能使用拦截器 |
拦截范围 | 在 url-pattern 中配置了 /* 之后,可以对所有要访问的资源拦截 | 只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的 |
4.1 自定义拦截器
4.1.1 创建拦截器类实现 HandlerInterceptor 接口
public class MyInterceptor1 implements HandlerInterceptor {
/**
* 目标方法执行前
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle1..");
if(){
...
// 不拦截
return true;
}else{
...
// 拦截
return false;
}
}
/**
* 目标方法返回前
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 此处可对 ModelAndView 对象进行操作!
System.out.println("postHandle2..");
}
/**
* 目标方法执行后
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion1..");
}
}
4.1.2 配置拦截器
spring-mvc.xml:
<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 拦截器1 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.one.interceptor.MyInterceptor1"/>
</mvc:interceptor>
<!-- 拦截器2 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.one.interceptor.MyInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
演示拦截效果:
4.2 preHandle()
、postHandle()
、afterCompletion()
方法名 | 说明 |
---|---|
preHandle() | 方法将在请求处理之前进行调用,该方法的返回值是布尔值 Boolean 类型的,当它返回为 false 时,表示请求结束,后续的 Interceptor 和 Controller 都不会再执行;当返回值为 true 时就会继续调用下一个 Interceptor 的 preHandle() |
postHandle() | 该方法是在当前请求进行处理之后被调用,前提是 preHandle() 的返回值为 true 时才能被调用,且它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对 Controller 处理之后的ModelAndView 对象进行操作 |
afterCompletion() | 该方法将在整个请求结束之后,也就是在 DispatcherServlet 渲染了对应的视图之后执行,前提是 preHandle() 的返回值为 true 时才能被调用 |
5. SpringMVC 异常处理
系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生。
系统的 Dao、Service、Controller 出现都通过 throws Exception 向上抛出,最后由 SpringMVC 前端控制器 DispatcherServlet 交由异常处理器进行异常处理,如下图:
异常处理的两种方式:
- 使用 SpringMVC 提供的简单异常处理器 SimpleMappingExceptionResolver
- 实现 Spring 的异常处理接口 HandlerExceptionResolver 自定义异常处理器
5.1 SimpleMappingExceptionResolver
UserServiceImpl.java:
@Service("userService")
public class UserServiceImpl implements UserService {
@Override
public void nullPointerException() {
ArrayList arrayList = null;
int length = arrayList.size();
System.out.println(length);
}
@Override
public void divide_0_exception() {
int i = 1 / 0;
}
}
spring-mvc.xml:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 默认错误页面 -->
<property name="defaultErrorView" value="error"/>
<!-- key:异常类型、value:错误页面 -->
<property name="exceptionMappings">
<map>
<entry key="java.lang.NullPointerException" value="error/error1"/>
<entry key="java.lang.ArithmeticException" value="error/error2"/>
<entry key="java.lang.ClassNotFoundException" value="error/error3"/>
</map>
</property>
</bean>
Controll.java:
@Controller()
@RequestMapping("/exception")
public class Controll {
@Autowired
@Qualifier("userService")
private UserService userService;
@RequestMapping("error")
@ResponseBody
public void test() {
userService.nullPointerException();
}
}
5.2 implements
HandlerExceptionResolver
MyExceptionHandler.java:
public class MyExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView modelAndView = new ModelAndView();
if (e instanceof NullPointerException) {
modelAndView.addObject("info", "NullPointer");
} else if (e instanceof ArithmeticException) {
modelAndView.addObject("info", "Arithmetic");
} else {
modelAndView.addObject("info", "others");
}
// 统一返回至error.jsp
modelAndView.setViewName("error/error");
return modelAndView;
}
}
spring-mvc.xml:
<!-- 配置自定义异常处理器 -->
<bean class="com.one.exception.MyExceptionHandler"/>
error.jsp:
<html>
<head>
<title>Error</title>
</head>
<body>
<h2>通用异常页面</h2>
</body>
</html>
原创不易🧠 转载请标明出处🌊
若本文对你有所帮助,点赞支持嗷🔥