文章目录
- SpringMVC文件上传
- 基本介绍
- 需求分析 / 图解
- 应用实例-代码实现
- 自定义拦截器
- 什么是拦截器
- 自定义拦截器执行流程分析图
- 自定义拦截器应用实例
- 快速入门
- 注意事项和细节
- Debug执行流程
- 多个拦截器
- 多个拦截器执行流程示意图
- 应用实例1
- 代码实现
- 注意事项和细节
- 应用实例2
- 作业布置
上一讲, 我们学习的是 SpringMVC系列十: 中文乱码处理与JSON处理
现在打开springmvc项目
SpringMVC文件上传
基本介绍
1.Spring MVC 为文件上传提供了直接的支持, 这种支持是通过即插即用的 MultipartResolver 实现的. Spring 用 Jakata Commons FileUpload 技术实现了一个 MultipartResolver 实现类: CommonsMultipartResolver
2.SpringMVC 上下文中默认没有装配 Multipartresolver, 因此默认情况下不能处理文件的上传工作, 如果想使用 Spring 的文件上传功能, 需现在上下文中配置 MultipartResolver
需求分析 / 图解
应用实例-代码实现
1.引入springmvc文件上传需要的jar包 spingmvc上传文件需要的jar
2.在web路径
下创建fileUpload.jsp
<body>
<h1>文件上传的演示</h1>
<form action="?" method="post" enctype="multipart/form-data">文件介绍:<input type="text" name="introduce"/><br/>选择文件:<input type="file" name="file"/><br/><input type="submit" value="上传文件"/>
</form>
</body>
3.配置文件过滤器, 在web.xml
中, 使用Spring提供的, 前面已经配置过了 传送
4.配置文件上传解析器, 在springDispatcherServlet-servlet.xml, 简单看一下CommonsMultipartResolver
源码
<!--配置文件上传需要的bean-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
5.在com.zzw.web.fileupload
下新建FileUploadHandler.java
* @author 赵志伟* @version 1.0* 处理文件上传的handler*/
@SuppressWarnings({"all"})
@Controller
public class FileUploadHandler {//编写方法, 处理文件上传的请求@RequestMapping(value = "/fileUpload")public String fileUpload(@RequestParam(value = "file") MultipartFile file,HttpServletRequest request, String introduce) throws IOException {//接收到提交的文件名String originalFilename = file.getOriginalFilename();System.out.println("你上传的文件名=" + originalFilename);System.out.println("文件的介绍=" + introduce);//得到要把上传的文件保存到哪个路径[全路径: 包括文件名]String fileFullPath =request.getServletContext().getRealPath("/img/" + originalFilename);//创建文件File saveToFile = new File(fileFullPath);//将上传的文件, 转存到saveToFilefile.transferTo(saveToFile);return "success";}
}
6.回填``fileUpload.jsp的
action`
<form action="<%=request.getServletContext()%>/fileUpload" method="post" enctype="multipart/form-data">
7.完成测试[页面方式], 看文件是否成功上传 http://localhost:8088/springmvc/fileUpload.jsp
简单地debug一下transferTo()
8.完成测试[postman方式]
自定义拦截器
什么是拦截器
●说明
1.Spring MVC也可以使用拦截器对请求进行拦截处理, 用户可以自定义拦截器来实现特定的功能.
2.自定义的拦截器必须实现HandlerInterceptor接口
●自定义拦截器的三个方法
1.preHandle(): 这个方法在业务处理器处理请求之前被调用, 在该方法中对用户请求 request 进行处理.
2.postHandler(): 这个方法在目标方法处理完请求后执行
3.afterCompletion(): 这个方法在完全处理完请求后被调用, 可以在该方法中进行一些资源清理的操作.
自定义拦截器执行流程分析图
●自定义拦截器执行流程说明
1.如果 preHandle 方法, 返回 false, 则不再执行目标方法, 可以在此指定返回页面
2.postHandle 在目标方法被执行后执行, 可以在方法中访问到目标方法返回的 ModelAndView 对象
3.若 preHandle 返回 true, 则 afterCompletion 方法, 在渲染视图之后被执行
4.若 preHandle 返回 false, 则 afterCompletion 方法不会被调用
5.在配置拦截器时, 可以指定该拦截器对哪些请求生效, 哪些请求不生效
自定义拦截器应用实例
快速入门
●应用实例需求
完成一个自定义拦截器, 学习一下如何配置拦截器和拦截器的运行流程
●应用实例-代码实现
1.com.zzw.web.interceptor包
下新建MyInterceptor01.java
@Component
public class MyInterceptor01 implements HandlerInterceptor {/*** 解读* 1. preHandle() 在目标方法执行前被执行* 2. 如果preHandle() 返回false, 不再执行目标方法* 3. 该方法可以获取到request, response, handler* 4. 这里根据业务, 可以进行拦截, 并指定跳转到哪个页面** @param request current HTTP request* @param response current HTTP response* @param handler chosen handler to execute, for type and/or instance evaluation* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("--MyInterceptor01-- preHandle() 被执行...");return true;}/*** 解读* 1. 在目标方法执行后, 会执行postHandle* 2. 该方法可以获取到 目标方法, 返回的ModelAndView** @param request current HTTP request* @param response current HTTP response* @param handler the handler (or {@link HandlerMethod}) that started asynchronous* execution, for type and/or instance examination* @param modelAndView the {@code ModelAndView} that the handler returned* (can also be {@code null})* @throws Exception*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("--MyInterceptor01-- postHandle()被执行...");}/*** 解读* 1. afterCompletion() 在视图渲染后被执行, 这里可以进行资源清理工作* 2.** @param request current HTTP request* @param response current HTTP response* @param handler the handler (or {@link HandlerMethod}) that started asynchronous* execution, for type and/or instance examination* @param ex any exception thrown on handler execution, if any; this does not* include exceptions that have been handled through an exception resolver* @throws Exception*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("--MyInterceptor01-- afterCompletion()被执行...");}
}
2.在springDispatcherServlet-servlet.xml
配置拦截器
注意: 拦截器是由spring
管理的 ; 过滤器是由web.xml
管理的
<!--配置自定义拦截器-spring配置文件-->
<mvc:interceptors><!--解读1. 第一种配置方式2. 使用ref 引用到对应的拦截器myInterceptor013. 这种方式, 会拦截所有的目标方法--><ref bean="myInterceptor01"/>
</mvc:interceptors><!--加入两个常规配置-->
<!--支持SpringMVC的高级功能, 比如JSR303校验, 映射动态请求-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--将springmvc不能处理的请求, 交给tomcat处理, 比如css, js-->
<mvc:default-servlet-handler/>
3.在com.zzw.ewb.interceptor包
下新建FurnHandler.java
@Controller
public class FurnHandler {@RequestMapping(value = "/hi")public String hi() {System.out.println("--FurnHandler-- hi()...");return "success";}@RequestMapping(value = "/hello")public String hello() {System.out.println("--FurnHandler-- hello()...");return "success";}
}
4.web路径
下创建interceptor.jsp
<head><title>测试自定义拦截器</title>
</head>
<body>
<h1>测试自定义拦截器</h1>
<a href="<%=request.getContextPath()%>/hi">测试自定义拦截器-hi</a><br/><br/>
<a href="<%=request.getContextPath()%>>/hello">测试自定义拦截器-hello</a>
</body>
5.测试
浏览器测试 http://localhost:8088/springmvc/interceptor.jsp
–MyInterceptor01-- preHandle() 被执行…
–FurnHandler-- hi()…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor01-- afterCompletion()被执行…
–MyInterceptor01-- preHandle() 被执行…
–FurnHandler-- hello()…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor01-- afterCompletion()被执行…
postman测试
–MyInterceptor01-- preHandle() 被执行…
–FurnHandler-- hi()…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor01-- afterCompletion()被执行…
–MyInterceptor01-- preHandle() 被执行…
–FurnHandler-- hello()…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor01-- afterCompletion()被执行…
注意事项和细节
1.默认配置是将所有的目标方法都进行拦截, 也可以指定拦截目标方法, 比如只拦截hi
<!--配置自定义拦截器-spring配置文件-->
<mvc:interceptors><!--解读1. 第二种配置方式2. mvc:mapping path="/hi" 指定要拦截的路径3. ref bean="myInterceptor01" 指定对哪个拦截器进行配置--><mvc:interceptor><mvc:mapping path="/hi"/><ref bean="myInterceptor01"/></mvc:interceptor>
</mvc:interceptors>
2.mvc:mapping 支持通配符, 同时指定不对哪些目标方法进行拦截
<!--配置自定义拦截器-spring配置文件-->
<mvc:interceptors><!--解读1. 第三种配置方式2. mvc:mapping path="/h*" 通配符方式 表示拦截 /h 打头的路径3. mvc:exclude-mapping path="/hello" /hello不拦截4. ref bean="myInterceptor01" 指定对哪个拦截器配置--><mvc:interceptor><mvc:mapping path="/h*"/><mvc:exclude-mapping path="/hello"/><ref bean="myInterceptor01"/></mvc:interceptor>
</mvc:interceptors>
FurnHandler
添加方法
@RequestMapping(value = "/ok")
public String ok() {System.out.println("--FurnHandler-- ok()...");return "success";
}
interceptor.jsp
添加标签
<a href="<%=request.getContextPath()%>/ok">测试自定义拦截器-ok</a>
3.拦截器需要配置才生效, 不配置是不生效的.
4.如果preHandler() 方法返回了false, 就不会执行目标方法(前提是你的目标方法被拦截了), 程序员可以在这里根据业务需要指定跳转页面.
Debug执行流程
1.prehandle()
2.目标方法
3.postHandle()
视图解析
一直点下一步
4.render()
5.afterCompletion()
解释一下model数据怎么来的? 用 postman 再走一圈
get请求
post请求
断点打到 preHandle
目标方法
postHandle
render
afterCompletion
多个拦截器
多个拦截器执行流程示意图
应用实例1
代码实现
1.com.zzw.web.interceptor.MyInterceptor02
@Component
public class MyInterceptor02 implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {System.out.println("--MyInterceptor02-- preHandle() 被执行...");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response,Object handler, ModelAndView modelAndView) throws Exception {System.out.println("--MyInterceptor02-- postHandle()被执行...");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response,Object handler, Exception ex) throws Exception {System.out.println("--MyInterceptor02-- afterCompletion()被执行...");}
}
2.配置springDispathcerServlet-servlet.xml
<mvc:interceptors><mvc:interceptor><mvc:mapping path="/h*"/><mvc:exclude-mapping path="/hello"/><ref bean="myInterceptor01"/></mvc:interceptor><!--解读1.配置的第二个拦截器2.多个拦截器在执行时, 是按照顺序执行的--><mvc:interceptor><mvc:mapping path="/h*"/><ref bean="myInterceptor02"/></mvc:interceptor>
</mvc:interceptors>
3.测试
–MyInterceptor01-- preHandle() 被执行…
–MyInterceptor02-- preHandle() 被执行…
–FurnHandler-- hi()…
–MyInterceptor02-- postHandle()被执行…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor02-- afterCompletion()被执行…
–MyInterceptor01-- afterCompletion()被执行…
注意事项和细节
1.如果第1个拦截器的preHandle()返回false, 后面都不执行
2.如果第2个拦截器的preHandle()返回false, 就直接执行第1个拦截器的afterCompletion() 方法, 如果拦截器更多, 规则类似.
3.说明: 前面说的规则, 目标方法被拦截是前提
应用实例2
1.需求: 如果用户提交的数据有禁用词(比如 病毒). 则, 在第1个拦截器就返回, 不执行目标方法, 功能效果如图
2.web路径/WEB-INF/pages/warning.jsp
<head><title>警告</title>
</head>
<body>
<h1>不要乱讲话</h1>
</body>
3.修改MyInterceptor01
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {System.out.println("--MyInterceptor01-- preHandle() 被执行...");//获取到用户提交的关键字String keyword = request.getParameter("keyword");if ("病毒".equals(keyword)) {//请求转发到warning.jsp//这里是原生的请求转发, 不是springmvc里的request.getRequestDispatcher("/WEB-INF/pages/warning.jsp").forward(request, response);return false;}System.out.println("得到keyword=" + keyword);return true;
}
3.postman测试
–MyInterceptor01-- preHandle() 被执行…
得到keyword=赵志伟
–MyInterceptor02-- preHandle() 被执行…
–FurnHandler-- hi()…
–MyInterceptor02-- postHandle()被执行…
–MyInterceptor01-- postHandle()被执行…
–MyInterceptor02-- afterCompletion()被执行…
–MyInterceptor01-- afterCompletion()被执行…
再次测试
–MyInterceptor01-- preHandle() 被执行…
作业布置
1.把前面我们学过的SpringMVC文件上传, 自定义拦截器和相关代码和案例, 自己写一遍. 一定要自己写一遍, 否则没有印象, 理解不会深入
2.简述SpringMVC自定义拦截器工作流程, 并画出示意图
3.debug自定义拦截器源码, 加深理解(不用每一条语句都debug), 重点是梳理流程.
下一讲, 我们学习 SpringMVC系列十一: 文件上传与自定义拦截器