SpringMVC
Demo代码
1 SpringMVC 简介
MVC是一种软件架构思想, 将软件按照模型、视图、控制器来划分
M: Model
: 模型层, 指工程中的Java Bean, 作用是处理数据
Java Bean分为两类:
- 实体类Bean: 专门存储业务数据的, 比如User, Student
- 业务处理Bean: 指Service或者Dao, 专门用于处理业务逻辑和数据访问
V: View
:视图层, 指工程中html或sp等页面, 作用是与用户进行交互, 展示数据
C: Controller
: 控制层, 指工程中的servlet, 作用是接受请求和响应浏览器
SpringMVC是一个Spring的子项目, SpringMVC有如下特点:
- Spring系列原生产品, 与IOC容器等基础设施无缝对接
- 基于原生的Servlet, 通过功能强大的前端控制器DispatcherServlet, 对请求和响应进行统一处理
- 表述层各细分领域需要解决的问题全方面覆盖, 提供全面解决方案
- 代码清晰简洁、组件化程度高、可插拔式组件即插即用、性能卓越..
2. HelloWorld
2.1准备工作
添加模块
打包方式war
引入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>6.1.13</version> </dependency>
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.4.12</version> </dependency>
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
<dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring6</artifactId> <version>3.1.2.RELEASE</version> </dependency>
|
在main目录下创建webapp
目录
载project structure中的module中添加web.xml(注意路径应该在webapp目录下)
2.2 配置web.xml
注册SpringMVC的前端控制器DispatcherServlet,
- 默认配置方式
此配置作用下, SpringMVC的配置文件默认位于WEB-INF下, 默认名为<servlet-name>-servlet.xml
, 例如, 以下配置对应的SpringMVC的配置文件位于WEB-INF下, 文件名为springMVC-servlet.xml
1 2 3 4 5 6 7 8 9 10 11 12
| <servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet>
<servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
|
- 扩展配置方式(常用)
可通过init-param标签设置SpringMVC配置文件的位置和名称, 通过load-on-startup标签设置SpringMVC前端控制器DispatcherServlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <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> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
|
2.3 创建请求控制器
由于前端控制器对浏览器发出的请求进行了统一的处理, 但是具体的请求有不同的处理过程, 因此需要创建处理具体请求的类, 即请求控制器
请求控制器中每一个处理请求的方法都成为控制器方法.
因为SpringMVC的控制器由一个POJO(普通的java类plain old java object)担任, 因此需要通过@Controller注解将其标识为一个控制层组件, 交给Spring ioc容器进行管理. 此时SpringMVC才能识别出控制器的存在.
1 2 3 4 5 6 7 8 9
| @Controller public void HelloWorld(){ @RequestMapping(value = "/") public String index(){ return "index"; }
}
|
2.4 创建springMVC.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <?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 http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.learning.mvc.controller"/>
<bean id="springResourceTemplateResolver" class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver"> <property name="prefix" value="/WEB-INF/templates/"/> <property name="suffix" value=".html"/> <property name="templateMode" value="HTML"/> <property name="characterEncoding" value="UTF-8"/> </bean>
<bean id="templateEngine" class="org.thymeleaf.spring6.SpringTemplateEngine"> <property name="templateResolver" ref="springResourceTemplateResolver"/> </bean> <bean id="viewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver"> <property name="order" value="1"/> <property name="characterEncoding" value="UTF-8"/> <property name="templateEngine" ref="templateEngine"/> </bean> </beans>
|
2.5 配置tomcat
tomcat10

3. 核心内容
3.1 @RequestMapping注解
@RequestMapping的作用就是将请求和处理请求的控制器关联起来, 建立映射关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.aot.hint.annotation.Reflective; import org.springframework.core.annotation.AliasFor;
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping @Reflective({ControllerMappingReflectiveProcessor.class}) public @interface RequestMapping { String name() default "";
@AliasFor("path") String[] value() default {};
@AliasFor("value") String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {}; }
|
3.1.1 @RequestMapping注解的位置
- 标识一个类: 设置请求路径的主路径
- 标识一个方法: 设置请求路径的子路径
3.1.2 @RequestMapping注解的value属性
3.1.3 @RequestMapping注解的method属性
@RequestMapping注解的method属性通过请求的请求方式(get、post等)匹配请求路径
@RequestMapping的method属性是一个RequestMethod类型的数组
对于处理指定请求方式的控制器方法, SpringMVC提供了@Request Mapping的派生注解:
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
3.1.4 @RequestMapping的params属性
@RequestMapping的params参数是一个字符串数组, 可以通过四种表达式设置请求和请求映射的匹配关系
param
: 必须携带参数param
!param
: 只要不携带参数param即可
param=value
: 必须要参数param等于value
param!=value
: 只要参数param不等于value即可
1 2 3 4 5 6
| # 例子
params = {username} # 必须携带username params = {!username} # 只要不携带username即可 params = {username=zhangsan} # 必须username = zhangsan params = {username!=zhangsan} # 只要username不等于zhangsan即可
|
3.1.5 SpringMVC支持ant风格的路径
?
: 表示任意的单个字符
*
: 标识任意的0个或多个字符
**
: 表示任意的一层或多层目录
- 注意: 使用
**
时, 只能使用/**/xxx
的方式
3.1.6 SpringMVC支持路径中的占位符(重点)
- 原始方式:
/deleteUser?id=1
(面向操作)
- Restful方式:
/deleteUser/1
(面向资源, 更易理解)
1 2 3 4 5
| @RequestMapping("/test/{id}/{username}") public User getUser(@PathVariable("id") String id, @PathVariable String username){ return new User(id, username); }
|
3.2 SpringMVC获取请求参数
3.2.1 @RequestParam
1 2 3 4 5 6 7
| @RequestMapping("/test") public User getUser(HttpServletRequest request){ String name = request.getParameter("username"); String password = request.getParameter("id"); return new User(name,password); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
@RequestMapping(value = "/testParam") public String testParam(String username, String password){ return "success"; }
@RequestMapping(value = "/testParam") public String testParam(@RequestParam("username") String username, @RequestParam("password") String password){ return "success"; }
|
@RequestHeader是将请求头信息和控制器方法的形参创建映射关系
@RequestHeader注解一共有三个属性: value, required, defaultValue, 用法与@RequestParam一样
3.2.3 @CookieValue
@CookieValue是将cookie数据和控制器方法的形参创建映射关系
三个属性与@RequestParam一样
3.2.4 通过POJO获取请求参数
在控制器方法的形参位置设置一个实体的类型的形参, 浏览器请求的参数与该实体内属性一致, 则参数会自动赋值
3.3 域对象共享数据
域对象 作用范围 生命周期 应用场景
ServletContext
: 全局范围 Web 应用启动到销毁 应用配置、全局统计信息
HttpSession
: 会话范围 用户访问到会话超时或销毁 登录信息、购物车
ServletRequest
: 请求范围 单个 HTTP 请求处理期间 请求数据、转发共享数据
PageContext
: 单个 JSP 页面 从 JSP 页面开始执行到处理完成 当前 JSP 页面内部 存储 JSP 页面的临时变量
3.3.1 使用servletAPI向Request域对象共享数据
1 2 3 4 5 6
| @RequestMapping("/test") public String test(HttpServletRequest request){ request.setAttribute("testScope", "Hello"); return "success"; }
|
3.3.2 使用ModelAndView向request域对象添加数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @RequestMapping("/testModleAndView") public ModelAndView testModelAndView(){
ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("msg111", "testModelAndView + " + modelAndView); modelAndView.setViewName("success"); return modelAndView; }
|
3.3.3 使用Model向request域对象共享数据
1 2 3 4 5
| @RequestMapping("/testModle") public String testModel(Model model){ model.setAttribute("testScope", "hello"); return "success" }
|
3.3.4 使用Map向request域对象共享数据
1 2 3 4 5
| @RequestMapping("/testMap") public String testMap(Map<String, Object> map){ map.put("testScope", "hello"); return "success" }
|
3.3.5 使用ModelMap向request域对象共享数据
1 2 3 4 5
| @RequestMapping("/testModleMap") public String testModelMap(ModelMap model){ model.setAttribute("testScope", "hello"); return "success" }
|
3.3.6 向Session域共享数据
1 2 3 4 5
| @RequestMapping("/testSession") public String testSession(HttpSession session){ session.setAttribute("testSession", "hello, session"); return "success"; }
|
3.3.6 向application域中共享数据
1 2 3 4 5 6 7
| @RequestMapping("/testApp") public String testApp(HttpSession session){ ServletContext application = session.getServletContext(); application.setAttribute("testApp", "hellp application domain"); return "success"; }
|
3.4 SpringMVC的视图
SpringMVC的视图是View接口, 视图的作用是渲染数据, 将模型Model中的数据展示给用户
SpringMVC视图的种类有很多, 默认有转发视图InternalResourceView和重定向视图RedirectView
当工程引入jstl的依赖, 转发视图会自动转化为JstlView
3.4.1 ThymeleafView
若使用的视图为Thymeleaf, 在SpringMVC的配置文件中配置了Thymeleaf的视图解析器, 由此视图解析器解析之后所得到的是ThymeleafView
3.4.2 InternalResourceView
SpringMVC中默认的转发视图是InternalResourceView
当控制器方法中所设置的视图名称以“forward:/“为前缀时, 会创建InternalResourceView视图, 此时视图名称不会被SpringMVC配置文件中的所配置的视图解析器解析. 而是通过转发的方式跳转
3.4.3 RedirectView

3.4.4 视图控制器view-controller
当控制器中的方法, 仅仅用来实现页面跳转, 即只需要设置视图名称时, 可以将处理器方法使用view-controller标签进行表示
1 2 3 4
| <mvc:view-controller path="/" view-name="index"></mvc:view-controller> <mvc:annotation-driven/>
|
4. RESTful
REST: Representational State Transfer 表现层资源状态转移
资源
处于服务器上一切可以访问的数据都可称为资源
资源的表述
资源的表述是一段对于资源在某个特定时刻的状态的描述. 可以理解为数据的格式
状态转移
状态转移是系统从一个状态变化到另一个状态的过程。状态(State)是系统在某一时刻的特定条件或配置,而转移(Transition)是由某种事件或条件触发的状态变化。例如: 用户已登陆, 用户未登录
3.1 RESTful的实现
HTTP协议中, 有四个表示对资源的操作动词:
GET
:获取资源
POST
: 新建资源
PUT
: 更新资源
DELETE
: 删除资源
RESTful风格提倡URL地址使用统一的风格设计, 从前到后各个单词使用斜杠分开, 不使用问号键值对的方式携带请求参数, 而是将要发送给服务器的数据作为url的一部分, 保证风格一致性

3.2 通过过滤器处理delete和put请求
1 2 3 4 5 6 7 8 9 10
| <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>
|
5. SpringMVC执行流程
5.1 SpringMVC常用组件
- DispatcherServlet: 前端控制器, 框架提供,不需要工程师开发. 整个流程控制的中心, 统一处理请求和响应. 由它调用其他组件处理用户的请求
- HandlerMapping: 处理器映射器, 框架提供, 不需要工程师开发. 根据请求的url,method等信息查找Handler, 即控制器方法
- Handler: 处理器,即控制器Controller, 需要工程师开发. 在DispatcherServlet的控制下, Handler对具体的用户请求进行处理
- HandlerAdapter: 处理器适配器, 由框架提供, 不需要工程师开发. 通过HandlerAdapter对控制器方法(处理器)进行执行
- ViewResolver: 视图解析器, 由框架提供, 不需要工程师开发. 进行视图解析, 得到对应的视图
- View: 视图, 不需要工程师开发, 由框架或视图技术提供. 将模型数据通过页面展示给用户
5.2 DispatcherServlet初始化过程
DispatcherServlet本质上是一个Servlet, 所以遵循Servlet的生命周期,
Servlet生命周期
- Servlet 初始化后调用 init () 方法。
- Servlet 调用 service() 方法来处理客户端的请求。
- Servlet 销毁前调用 destroy() 方法。
- 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
1 2 3 4 5 6 7 8 9 10 11
| protected void initStrategies(ApplicationContext context) { this.initMultipartResolver(context); this.initLocaleResolver(context); this.initThemeResolver(context); this.initHandlerMappings(context); this.initHandlerAdapters(context); this.initHandlerExceptionResolvers(context); this.initRequestToViewNameTranslator(context); this.initViewResolvers(context); this.initFlashMapManager(context); }
|
5.3 SpringMVC执行流程
- 用户向服务器发起请求, 请求被SpringMVC前端控制器DispatcherServlet捕获
- DispatcherServlet对URL进行解析, 得到请求资源定位符URI, 判断请求URI对应的映射:
- 不存在URI对应映射
- 再判断是否配置了
mvc:default-servlet-handler
- 如果没配置, 控制台报映射查找不到, 客户端显示404错误
- 有配置, 则访问目标资源(一般是静态资源, html, js, css). 找不到式客户端会显示404
- 存在URI对应映射
- 根据URI, 调用HandlerMapping得到该Handler配置的所有有关对象, 包括控制器和拦截器, 最后以HandlerExecutionChain执行链对象的形式返回
- DispatcherServlet根据的到的Handler, 选择一个合适的HandlerAdapter
- 如果成功或得HandlerAdapter, 开始执行拦截器的preHandler方法
- 提取Request中的模型数据, 填充Handler入参, 开始执行Handler(Controller)方法, 处理请求. 在填充Handler的入参过程中, 根据个人配置, Spring将完成一些额外的工作:
- HttpMessageConvert: 将请求信息(json, xml等)转化为一个对象, 或者将对象转化为对应的响应信息
- 数据转换: 比如String转化为Integer
- 数据格式化: 比如String转化为数字或者日期
- 数据验证: 验证数据有效性(长度, 格式等)
- Handler执行完成后, 向DispatcherServlet返回一个ModleAndView对象
- 此时将开始执行拦截器postHandler()方法
- 根据ModelAndView(如果有异常, 执行Handler ExceptionResolver进行异常处理), 选择一个合适的ViewResovler(普通、forward、redirect)进行视图解析, 根据model和view来渲染视图
- 将渲染结果返回给客户端
6. 注解配置SpringMVC
使用配置类和注解代替web.xml和SpringMVC配置文件功能
6.1 创建初始化类, 代替web.xml
在Servlet3.0中, 容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类, 如果找到的话就用它来配置Servlet容器
Spring提供了这个接口的实现, 名为SpringServletContainerInitializer. 这个类还会查找实现WebApplicationInitializer的类, 并将配置的任务交给他们完成, Spring3.2引入了一个WebApplicationInitializer的实现类, AbstractAnnotationConfigDispatcherServletInitializer.
当我们继承了AbstractAnnotationConfigDispatcherServletInitializer并且将其部署到了Servlet3的容器中时, 容器会自动发现它, 并用它来配置Servlet上下文.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| package com.learning.mvc.anno.config;
import jakarta.servlet.Filter; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.filter.HiddenHttpMethodFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebXML extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; }
@Override protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class}; }
@Override protected String[] getServletMappings() { return new String[]{"/"}; }
@Override protected Filter[] getServletFilters() { CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); characterEncodingFilter.setEncoding("UTF-8"); characterEncodingFilter.setForceEncoding(true); HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter(); return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter}; }
}
|
6.2 创建SpringMVC配置, 代替SpringMVC.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
| package com.learning.mvc.anno.config;
import com.learning.mvc.anno.controller.TestController; import com.learning.mvc.anno.interceptor.TestInterceptor; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.multipart.MultipartResolver; import org.springframework.web.multipart.support.StandardServletMultipartResolver; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.config.annotation.*; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import org.thymeleaf.spring6.SpringTemplateEngine; import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver; import org.thymeleaf.spring6.view.ThymeleafViewResolver;
import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Properties;
@Configuration @ComponentScan("com.learning.mvc.anno") @EnableWebMvc public class WebConfig implements WebMvcConfigurer {
@Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); }
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new TestInterceptor()).addPathPatterns("/**");
WebMvcConfigurer.super.addInterceptors(registry); }
@Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("forward:/index.html"); }
@Bean public MultipartResolver multipartResolver() { return new StandardServletMultipartResolver();
}
@Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver(); Properties properties = new Properties(); properties.setProperty("java.lang.ArithmeticException", "error"); exceptionResolver.setExceptionMappings(properties); exceptionResolver.setExceptionAttribute("exception"); resolvers.add(exceptionResolver);
}
@Bean public ThymeleafViewResolver thymeleafViewResolver(@Qualifier("springTemplateEngine") SpringTemplateEngine templateEngine) { ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setOrder(1); viewResolver.setCharacterEncoding("UTF-8"); viewResolver.setTemplateEngine(templateEngine); return viewResolver; }
@Bean("springTemplateEngine") public SpringTemplateEngine templateEngine(@Qualifier("templateResolver") SpringResourceTemplateResolver templateResolver) { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.addTemplateResolver(templateResolver); return templateEngine; }
@Bean("templateResolver") public SpringResourceTemplateResolver springResourceTemplateResolver() { SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setPrefix("classpath:/WEB-INF/templates/");
templateResolver.setSuffix(".html"); templateResolver.setTemplateMode("HTML5"); templateResolver.setCharacterEncoding("UTF-8"); return templateResolver; }
|
7. 扩展功能
7.1 HttpMessageConverter
HttpMessageConverter, 报文信息转换器, 将请求报文转化为Java对象, 或将java对象转化为响应报文
HttpMessageConverter提供了两个注解和两个类型:
注解:
@RequestBody
: 在控制器中设置一个形参, 并使用此注解标识控制器
@ResponseBody
: 标识控制器方法
, 可以将该控制器的返回值作为响应体返回给浏览器
类型:
RequestEntity
: 放入控制器方法的形参中, 当有请求匹配到此控制器中, 则请求体信息会自动注入该形参中
ResponseEntity
: 用于控制器返回值类型, 就是响应到浏览器的响应报文
@ResponseBody处理json对象需要引入注解才可以让java对象自动转化为json对象
1 2 3 4 5 6
| <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.16.0</version> </dependency>
|
@RestController = @Controller + @ResponseBody
@RestController加载控制器的类上, 相当于为类添加了@Controller, 同时为类中每个控制器添加了@ResponseBody
7.2 文件上传和下载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Controller public class FileController {
@RequestMapping("/testDown") public ResponseEntity<byte[]> testDown(HttpSession session) throws IOException { ServletContext servletContext = session.getServletContext(); String realPath = servletContext.getRealPath("/static/img/a.png"); FileInputStream fileInputStream = new FileInputStream(realPath); byte[] bytes = new byte[fileInputStream.available()]; fileInputStream.read(bytes); MultiValueMap<String, String> httpHeaders = new HttpHeaders(); httpHeaders.add("Content-Disposition", "attachment; filename=a.png"); HttpStatus httpStatus = HttpStatus.OK; ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, httpHeaders, httpStatus); fileInputStream.close(); return responseEntity;
} }
|
文件上传需要先引入相关依赖:
1 2 3 4 5 6
| <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency>
|
配置bean
1 2
| <bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"></bean>
|
配置解析器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <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> </init-param> <load-on-startup>1</load-on-startup>
<multipart-config> <max-file-size>10485760</max-file-size> <max-request-size>10485760</max-request-size> <file-size-threshold>0</file-size-threshold> </multipart-config> </servlet>
|
表单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body>
<form th:action="@{/testUp}" method="post" enctype="multipart/form-data"> 图片上传: <input type="file" name="photo"> <input type="submit" value="上传"> </form>
</body> </html>
|
控制器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @RequestMapping(value = "/testUp", method = RequestMethod.POST) public String testUp(@RequestParam("photo") MultipartFile photo, HttpSession session) throws IOException { System.out.println(photo.getOriginalFilename()); System.out.println(photo.getName()); ServletContext servletContext = session.getServletContext(); String realPath = servletContext.getRealPath("photo"); File file = new File(realPath); if (!file.exists()) { file.mkdirs(); } String finalPath = realPath + File.separator + photo.getOriginalFilename(); photo.transferTo(new File(finalPath)); return "testUP 成功"; }
|
7.3 拦截器

编写拦截器方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Component public class FirstInterceptor implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("FirstInterceptor preHandle"); return false ; }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("FirstInterceptor postHandle"); HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("FirstInterceptor afterCompletion"); HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } }
|
编写控制器
1 2 3 4 5 6 7 8 9 10
| @Controller public class HandlerController {
@RequestMapping("/testInterceptor") public String testInterceptor() {
return "interceptor"; }
}
|
配置SpringMVC
1 2 3 4 5 6 7 8 9
|
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/testInterceptor"/> <ref bean="firstInterceptor"/> </mvc:interceptor> </mvc:interceptors>
|
有多个拦截器时

7.4 异常处理器
SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口: HandlerExceptionResolver
HandlerExceptionResolver的实现类有:
- DefaultHandlerExceptionResolver SpringMVC默认使用的异常处理器
- SimpleHandlerExceptionResolver: 留给开发人员自定义处理异常
基于配置的异常处理
1 2 3 4 5 6 7 8 9
| <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props > <prop key="java.lang.ArithmeticException">error</prop> </props> </property> </bean>
|
基于注解的异常处理
1 2 3 4 5 6 7 8 9 10
| @ControllerAdvice public class ExceptionCatchController2 { @ExceptionHandler(value = {ArithmeticException.class, NullPointerException.class}) public String testExceptionHandler(Exception e) { return "error"; }
}
|