目录
1、Springmvc拦截器
1、自定义拦截器
2、定义多个拦截器
2、拦截器跟过滤器的区别
3、使用拦截器实现登录权限拦截
拦截器采用AOP的设计思想, 它跟过滤器类似, 用来拦截处理方法在之前和之后执行一些跟主业务没有关系的一些公共功能:
比如:可以实现:权限控制、日志、异常记录、记录方法执行时间.....
SpringMVC提供了拦截器机制,允许运行目标方法之前进行一些拦截工作或者目标方法运行之后进行一下其他相关的处理。自定义的拦截器必须实现HandlerInterceptor接口。
拦截器一个有3个回调方法,而一般的过滤器Filter才两个:
preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器才会执行
MyInterceptor.java
public class MyInterceptor implements HandlerInterceptor {
/**
* 在处理方法之前执 日志、权限、 记录调用时间
* @param request 可以在方法请求进来之前更改request中的属性值
* @param response
* @param handler 封装了当前处理方法的信息
* @return true 后续调用链是否执行/ false 则中断后续执行
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 在请求映射到对应的处理方法映射,实现类才是HandlerMethod。
// 如果是视图控制器,实现类ParameterizableViewController
if(handler instanceof HandlerMethod ) {
HandlerMethod handMethod = (HandlerMethod) handler;
}
/*System.out.println("-------类["+handMethod.getBean().getClass().getName()+"]" +
"方法名["+handMethod.getMethod().getName()+"]" +
"参数["+ Arrays.toString(handMethod.getMethod().getParameters()) +"]前执行--------preHandle");*/
System.out.println("---------方法后执行,在渲染之前--------------preHandle");
return true;
}
/**
* 如果preHandle返回false则会不会允许该方法
* 在请求执行后执行, 在视图渲染之前执行
* 当处理方法出现了异常则不会执行方法
* @param request
* @param response 可以在方法执行后去更改response中的信息
* @param handler 封装了当前处理方法的信息
* @param modelAndView 封装了model和view.所以当请求结束后可以修改model中的数据或者新增model数据, 也可以修改view的跳转
* @throws Exception
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("---------方法后执行,在渲染之前--------------postHandle");
}
/**
* 如果preHandle返回false则会不会允许该方法
* 在视图渲染之后执行,相当于try catch finally 中finally,出现异常也一定会执行该方法
* @param request
* @param response
* @param handler
* @param ex Exception对象,在该方法中去做一些:记录异常日志的功能,或者清除资源
* @throws Exception
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("---------在视图渲染之后--------------afterCompletion");
}
InterceptorController.java
/***
*
* 拦截器演示
* 1.定义拦截器,必须要实现HandlerInterceptor
* 2. 在springmvc配置文件中去配置拦截器
*
*
*
*/
@Controller
public class InterceptorController {
@RequestMapping("/test01")
public String test01(){
System.out.println("请求方法执行中...");
return "admin";
}
}
springmvc.xml
通过运行结果能够发现拦截器的执行顺序如下:
可以看到先执行拦截器的preHandle方法----》执行目标方法----》执行拦截器的postHandle方法----》执行页面跳转----》执行拦截器的afterCompletion方法
在配置拦截器的时候有两个需要注意的点:
1、如果prehandle方法返回值 为false,那么意味着不放行,那么就会造成后续的所有操作都中断
2、如果执行到方法中出现异常,那么后续流程不会处理但是afterCompletion方法会执行
再添加另外一个拦截器
MySecondInterceptor.java
public class MySecondInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(this.getClass().getName()+"------->preHandle");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println(this.getClass().getName()+"------->postHandle");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println(this.getClass().getName()+"------->afterCompletion");
}
}
看到如下执行顺序:
调整两个拦截器的配置顺序:
大家可以看到对应的效果,谁先执行取决于配置的顺序。
拦截器的preHandle是按照顺序执行的
拦截器的postHandle是按照逆序执行的
拦截器的afterCompletion是按照逆序执行的
如果执行的时候核心的业务代码出问题了,那么已经通过的拦截器的afterCompletion会接着执行。
1、过滤器是基于函数回调的,而拦截器是基于java反射的
2、过滤器依赖于servlet容器,而拦截器不依赖与Servlet容器,拦截器依赖SpringMVC
3、过滤器几乎对所有的请求都可以起作用,而拦截器只能对SpringMVC请求起作用
4、拦截器可以访问处理方法的上下文,而过滤器不可以
UserController.java
@Controller
public class UserController {
@PostMapping("/login")
public String login(HttpSession session){
//登录成功
session.setAttribute("username","fztx");
return "admin";
}
@GetMapping("/login")
public String login(){
return "login";
}
}
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
admin.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
管理员后台页面 ,您好:${sessionScope.username}
CheckLoginInterceptor.java
/***
*
* 验证用户是否登录拦截器
*/
public class CheckLoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
// 如果没有登录
if(StringUtils.isEmpty(session.getAttribute("username"))){
response.sendRedirect(request.getContextPath()+"/login");
return false;
}
else
{
return true;
}
}
}
拦截映射和排除映射