Interceptor拦截器
一、概念
拦截器是SpringMVC中的一个强大控件,它可以在进入处理器之前做一些操作,或者在处理器完成后进行操作,甚至是在渲染视图后进行操作。
二、拦截器定义
Spring要求处理器的拦截器都要实现org.springframework.web.servlet.HandlerInterceptor ,这个接口定义了3个方法:
(1)preHandle:在处理器之前执行的前置方法。返回一个boolean值,会影响后面的处理流程。
(2)postHandle:在处理器之后执行的后置方法,处理器的逻辑完成后运行它。
(3)afterCompletion:无论是否产生异常都会在渲染视图后执行的方法。
三、拦截器的执行流程(链路回调思想)
(1)进入前置方法(preHandle)
(2)前置方法的boolean是否为true; 若为false,直接(7);若为true,执行(3);
(3)进入处理器handler
(4)进入后置方法(postHandle)
(5)视图解析和渲染图
(6)进入完成方法(afterCompletion)
(7)结束
四、多个拦截器执行的顺序
正常情况下,Spring会先从第一个拦截器开始进入前置方法,这样前置方法是按配置顺序运行的,然后运行处理器的代码,最后运行后置方法。后置方法和完成方法是按照配置顺序逆序运行的,这和责任链模式的运行顺序是一直的。
五、用户登录的拦截器开发
1、通行拦截器
(1)重写preHandle:从httpServletRequest中监测cookies数据,如果能够获取当前用户的ticket(门票,保存用户登录状态的数据),就将这个数据写入临时的ticket。接着判断这个ticket是否在数据库中,是否已经过期,登录状态是否正常。验证成功后返回true,并将这个用户写入hostHolder,让此时的线程保存这个用户的登录信息,最后返回true进入处理器。
(2)重写postHandle:在处理器执行完后,将hostHolser的用户填充到modelAndView中。
(3)重写afterCompletion:最后将hostHolder清除掉。
@Component
public class PassportInterceptor implements HandlerInterceptor {
@Autowired
private LoginTicketDAO loginTicketDAO;
@Autowired
private UserDAO userDAO;
@Autowired
private HostHolder hostHolder;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
String ticket = null;
if (httpServletRequest.getCookies() != null) {
for (Cookie cookie : httpServletRequest.getCookies()) {
if (cookie.getName().equals("ticket")) {
ticket = cookie.getValue();
break;
}
}
}
if (ticket != null) {
LoginTicket loginTicket = loginTicketDAO.selectByTicket(ticket);
if (loginTicket == null || loginTicket.getExpired().before(new Date()) || loginTicket.getStatus() != 0) {
return true;
}
User user = userDAO.selectById(loginTicket.getUserId());
hostHolder.setUser(user);
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
if (modelAndView != null && hostHolder.getUser() != null) {
modelAndView.addObject("user", hostHolder.getUser());
}
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
hostHolder.clear();
}
}
2、登录拦截器
重写preHandle:如果检测到hostHolder为空,即用户没有登录,就将页面跳转到登录页面,return false,先登录。
@Component
public class LoginRequiredInterceptor implements HandlerInterceptor {
@Autowired
private HostHolder hostHolder;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
if (hostHolder.getUser() == null) {
httpServletResponse.sendRedirect("/?pop=1");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}