拦截器
SpringMVC 中的 Interceptor 拦截器也是相当重要和相当有⽤的,它的主要作⽤是拦截⽤户的请求并进
⾏相应的处理。⽐如通过它来进⾏权限验证,或者是来判断⽤户是否登陆等操作。对于 SpringMVC 拦截
器的定义⽅式有两种:
实现接⼝:org.springframework.web.servlet.HandlerInterceptor
继承适配器:org.springframework.web.servlet.handler.HandlerInterceptorAdapter
拦截器实现
实现 HandlerInterceptor 接⼝
接⼝实现类
/**
- 拦截器实现
- 实现 HandlerInterceptor 接⼝
*/
public class MyInterceptor01 implements HandlerInterceptor {
/**
* 在 ⽬标Handler(⽅法)执⾏前 执⾏
* 返回 true:执⾏handler⽅法
* 返回 false:阻⽌⽬标handler⽅法执⾏
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("⽬标Handler执⾏前执⾏MyInterceptor01 --> preHandle⽅法...");
/**
* 返回 true:执⾏handler⽅法
* 返回 false:阻⽌⽬标handler⽅法执⾏
*/
return true;
}
/**
* 在 ⽬标Handler(⽅法)执⾏后,视图⽣成前 执⾏
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("⽬标Handler执⾏后,视图⽣成前执⾏MyInterceptor01 -->
postHandle⽅法...");
}
/**
* 在 ⽬标Handler(⽅法)执⾏后,视图⽣成后 执⾏
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse
response, Object handler, Exception ex) throws Exception {
System.out.println("⽬标Handler执⾏后,视图⽣成后执⾏MyInterceptor01 -->
afterCompletion⽅法...");
}
}
拦截器xml配置
<!-- 拦截器配置:⽅式⼀ -->
<mvc:interceptors>
<!--
使⽤bean定义⼀个Interceptor
直接定义在mvc:interceptors根下⾯的Interceptor将拦截所有的请求
-->
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor01"/>
</mvc:interceptors>
<!-- 拦截器配置:⽅式⼆ (推荐使⽤) -->
<mvc:interceptors>
<!--
定义在 mvc:interceptor 下⾯,可以⾃定义需要拦截的请求
如果有多个拦截器满⾜拦截处理的要求,则依据配置的先后顺序来执⾏
-->
<mvc:interceptor>
<!-- 通过 mvc:mapping 配置需要拦截的资源。⽀持通配符。可配置多个。 -->
<mvc:mapping path="/**"/> <!-- "/**"表示拦截所有的请求。 -->
<!-- 通过 mvc:mapping 配置不需要被拦截的资源。⽀持通配符。可配置多个。 -->
<mvc:exclude-mapping path="/url/*"/> <!-- "/url/*"表示放⾏url路径下的请求。 -->
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor01"/>
</mvc:interceptor>
</mvc:interceptors>
继承 HandlerInterceptorAdapter
实际上最终还是 HandlerInterceptor 接⼝实现。
⼦类实现类
/**
* 拦截器实现
* 继承 HandlerInterceptorAdapter 适配器
*/
public class MyInterceptor02 extends HandlerInterceptorAdapter {
/**
* 在 ⽬标Handler(⽅法)执⾏前 执⾏
* 返回 true:执⾏handler⽅法
* 返回 false:阻⽌⽬标handler⽅法执⾏
* @param request
* @param response
* @param handler
* @return
* * @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("⽬标Handler执⾏前执⾏MyInterceptor02 --> preHandle⽅法...");
/**
* 返回 true:执⾏handler⽅法
* 返回 false:阻⽌⽬标handler⽅法执⾏
*/
return true;
}
}
拦截器xml配置
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截的资源 -->
<mvc:mapping path="/**"/>
<!-- 放⾏的资源 -->
<mvc:exclude-mapping path="/url/test01"/>
<mvc:exclude-mapping path="/url/test02"/>
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor02"/>
</mvc:interceptor>
</mvc:interceptors>
多个拦截器实现
SpringMVC 框架⽀持多个拦截器配置,从⽽构成拦截器链,对客户端请求进⾏多次拦截操作。
拦截器代码实现
这⾥参考MyInterceptor01、MyInterceptor02代码
拦截器xml配置
<!--
拦截器链(多个拦截器)
如果有多个拦截器满⾜拦截处理的要求,则依据配置的先后顺序来执⾏
先配置的拦截器的 preHandle ⽅法先执⾏
先配置的拦截器的 postHandle、afterCompletion ⽅法后执⾏
-->
<mvc:interceptor>
<!-- 拦截所有请求 -->
<mvc:mapping path="/**" />
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor01" />
</mvc:interceptor>
<mvc:interceptor>
<!-- 拦截所有请求 -->
<mvc:mapping path="/**" />
<bean class="com.xxxx.springmvc.interceptor.MyInterceptor02" />
</mvc:interceptor>
</mvc:interceptors>
拦截器应⽤ - ⾮法请求拦截
使⽤拦截器完成⽤户是否登录请求验证功能
⽤户控制器
UserInfoController 定义
/**
* ⽤户操作模拟实现
* ⽤户登录(⽆需登录)
* ⽤户添加(需要登录)
* ⽤户修改(需要登录)
* ⽤户删除(需要登录)
*/
@Controller
@RequestMapping("/userInfo")
public class UserInfoController {
/**
* ⽤户登录
* @return
*/
@RequestMapping("/login")
public ModelAndView userLogin(HttpSession session){
System.out.println("⽤户登录...");
ModelAndView mv = new ModelAndView();
// 设置视图
mv.setViewName("success");
// ⽤户登录后,设置对应的session域对象
User user = new User();
user.setId(1);
user.setUserName("admin");
user.setUserPwd("123456");
session.setAttribute("user",user);
return mv;
}
/**
* ⽤户添加
* @return
*/
@RequestMapping("/add")
public ModelAndView userAdd(){
System.out.println("⽤户添加...");
ModelAndView mv = new ModelAndView();
// 设置视图
mv.setViewName("success");
return mv;
}
/**
* ⽤户修改
* @return
*/
@RequestMapping("/update")
public ModelAndView userUpdate(){
System.out.println("⽤户更新...");
ModelAndView mv = new ModelAndView();
// 设置视图
mv.setViewName("success");
return mv;
}
/**
* ⽤户删除
* @return
*/
@RequestMapping("/delete")
public ModelAndView userDelete(){
System.out.println("⽤户删除...");
ModelAndView mv = new ModelAndView();
// 设置视图
mv.setViewName("success");
return mv;
}
}
⻚⾯定义
success.jsp 定义
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html> <head>
<title>Title</title>
</head> <body>
<h3>欢迎登录!</h3>
</body>
</html>
⾮法请求拦截器定义
LoginInterceptor 定义
/**
* ⾮法访问拦截
*/
public class LoginInterceptor extends HandlerInterceptorAdapter {
/**
* 在 ⽬标⽅法执⾏前 执⾏
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
// 获取 session 域对象中的user对象
User user= (User) request.getSession().getAttribute("user");
// 判断session域对象中的 user 是否为空
if(null == user){ // 如果为空,表示⽤户未登录
// 拦截⽤户跳转到登录⻚⾯
response.sendRedirect(request.getContextPath() + "/login.jsp");
// 不执⾏⽬标⽅法
return false;
}
// ⽤户已登录,执⾏⽬标⽅法
return true;
}
}
拦截器xml配置
servlet-context.xml 配置
<!-- 拦截所有请求 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截所有请求 -->
<mvc:mapping path="/**" />
<!-- 放⾏⽤户登录请求 -->
<mvc:exclude-mapping path="/userInfo/login"/>
<bean class="com.xxxx.springmvc.interceptor.LoginInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
⽂件上传
环境配置
pom.xml⽂件修改
<!-- 添加 commons-fileupload 依赖 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
servlet-context.xml修改
<!-- ⽂件上传 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 允许⽂件上传的最⼤尺⼨ -->
<property name="maxUploadSize">
<value>104857600</value>
</property>
<!--
设置⽂件放⼊临时⽂件夹的最⼤⼤⼩限制。
此值是阈值,低于此值,则保存在内存中,如⾼于此值,则⽣成硬盘上的临时⽂件。
-->
<property name="maxInMemorySize">
<value>4096</value>
</property>
</bean>
代码实现
单⽂件上传
⻚⾯表单
input 的type设置为file
form 表单的method设为post,
form 表单的enctype设置为multipart/form-data,以⼆进制的形式传输数据
<form action="uploadFile" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<button type="submit"> 提交</button>
</form>
代码实现
/**
* ⽂件上传
*/
@Controller
public class FileController {
/**
* 单⽂件上传
* 使⽤MultipartFile对象作为参数,接收前端发送过来的⽂件
* @param file
* @param request
* @return
*/
@RequestMapping("/uploadFile")
public String uploadFile(@RequestParam("file") MultipartFile file,
HttpServletRequest request){
// 判断⽂件是否为空,如果不为空进⾏对应的⽂件上传操作
if (!file.isEmpty()) {
try {
// 获取项⽬的所在的路径 (绝对路径)
String path = request.getServletContext().getRealPath("/");
// 设置上传的⽂件存放的⽬录
File uploadFile = new File(path + "/upload");
// 判断⽂件⽬录是否存在,不存在则新建⽬录
if (!uploadFile.exists()) {
// 新建⽬录
uploadFile.mkdir();
}
// 获取上传⽂件的原⽂件名
String originalName = file.getOriginalFilename();
// 获取上传的⽂件的后缀
String suffix = originalName.substring(originalName.lastIndexOf("."));
// 通过系统当前时间的毫秒数,⽣成随机⽂件名 (避免上传的⽂件名重复)
String fileName = System.currentTimeMillis() + suffix;
// 上传⽂件 (转存⽂件到指定⽬录)
file.transferTo(new File(uploadFile, fileName));
// 设置成功的域对象
request.setAttribute("msg","⽂件上传成功!");
} catch (IOException e) {
e.printStackTrace();
// 如果报错,设置的域对象
request.setAttribute("msg","⽂件上传失败!");
}
} else {
// 上传⽂件不存在,设置的域对象
request.setAttribute("msg","⽂件不存在,上传失败!");
}
return "result";
}
}
多⽂件上传
⻚⾯表单
<form action="uploadFiles" method="post" enctype="multipart/form-data">
<input type="file" name="files" />
<input type="file" name="files" />
<input type="file" name="files" />
<button type="submit"> 提交</button>
</form>
代码实现
/**
* 上传⽂件
* @param file
* @param request
*/
public void saveFile(MultipartFile file, HttpServletRequest request) {
// 判断⽂件是否为空,如果不为空进⾏对应的⽂件上传操作
if (!file.isEmpty()) {
try {
// 获取项⽬的所在的路径 (绝对路径)
String path = request.getServletContext().getRealPath("/");
// 设置上传的⽂件存放的⽬录
File uploadFile = new File(path + "/upload");
// 判断⽂件⽬录是否存在,不存在则新建⽬录
if (!uploadFile.exists()) {
// 新建⽬录
uploadFile.mkdir();
}
// 获取上传⽂件的原⽂件名
String originalName = file.getOriginalFilename();
// 获取上传的⽂件的后缀
String suffix = originalName.substring(originalName.lastIndexOf("."));
// 通过系统当前时间的毫秒数,⽣成随机⽂件名 (避免上传的⽂件名重复)
String fileName = System.currentTimeMillis() + suffix;
// 上传⽂件 (转存⽂件到指定⽬录)
file.transferTo(new File(uploadFile, fileName));
// 设置成功的域对象
request.setAttribute("msg","⽂件上传成功!");
} catch (IOException e) {
e.printStackTrace();
// 如果报错,设置的域对象
request.setAttribute("msg","⽂件上传失败!");
}
} else {
// 上传⽂件不存在,设置的域对象
request.setAttribute("msg","⽂件不存在,上传失败!");
}
}
/**
* 多⽂件上传
* @param files
* @param request
* @return
*/
@RequestMapping("/uploadFiles")
public String uploadFiles(@RequestParam("files") List<MultipartFile> files,
HttpServletRequest request) {
// 判断⽂件集合是否为空
if (files != null && files.size() > 0) {
// 循环上传
for (MultipartFile file:files) {
// 上传⽂件
saveFile(file, request);
}
}
return "result"; }