拦截器可以分别通过继承下面的接口实现拦截的功能,下面这两个比MethodInterceptor先执行。实现一个HandlerInterceptor拦截器可以直接实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter类。这两种方法殊途同归,其实HandlerInterceptorAdapter也就是声明了HandlerInterceptor接口中所有方法的默认实现,而我们在继承他之后只需要重写必要的方法:
常用:
public class LoginInterceptor extends HandlerInterceptorAdapter { ... }
public class LoginInterceptor extends HandlerInterceptor { ... }
抽象类:
AbstractInterceptor(status2)的,不提。
常用于AOP的拦截器:
public class RestController implements MethodInterceptor{ ... }
拦截器的三个方法,举例HandlerInterceptor:
public class OtherInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
/*该方法将在请求处理之前进行调用,只有该方法返回true,才会继续执行后续的Interceptor和Controller,当返回值为true 时就会继续调用下一个Interceptor的preHandle 方法,如果已经是最后一个Interceptor的时候就会是调用当前请求的Controller方法;*/
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
/*该方法将在请求处理之后,DispatcherServlet进行视图返回渲染之前进行调用,可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。*/
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
/*该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。用于进行资源清理。*/
}
}
这里使用的HandlerInterceptorAdapter接口,实现的是拦截跳转到职业页面,通过session判断是否有值,没有的话就跳到login登录页面,有session就可以直接访问。
@Controller
public class LoginInterceptor extends HandlerInterceptorAdapter {
private final Logger logger = Logger.getLogger(LoginInterceptor.class);
// preHandle在业务处理器处理请求之前被调用 前置方法
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
String url = request.getRequestURI();
logger.info("\n 拦截url:" + url + "\n");
// 如果url包含 则拦截 或者使用是否处在页面indexOf("profession")
if(url.contains("profession")){
logger.info("拦截了profession");
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
logger.info("\nsession.name:" + username + "\n");
if(username!=null){
return true;
}
request.getRequestDispatcher("/WEB-INF/jsp/body/login.jsp").forward(request,response);
// response.sendRedirect("login");
// request.getRequestDispatcher("login").forward(request,response);
return false;
}
// false拦截 true放行
return true;
}
// postHandle在业务处理请求执行完成之后,视图被调用之前执行,只有pre方法返回true的时候才会被调用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
// afterCompletion在完全处理完请求后(也就是controller执行后)被调用 用来处理清理资源或者后续关闭等行为
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
super.afterCompletion(request, response, handler, ex);
}
}
return true是放行,return false是拦截。
然后在SpringMVC.xml里配置对应的拦截器:
<!--SpringMVC 拦截器 多个拦截器顺序执行-->
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
<mvc:interceptors>
<mvc:interceptor>
<!--匹配url路径-->
<mvc:mapping path="/u/**"/>
<bean "com.tiles.controller.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
这里通过urlpath判断是否拦截,配置的是拦截所有/u/**访问,可以看到所有的/u/都被拦截了:
图
没有session的情况下访问profession页面直接跳转到登录页面
图
登录后访问:
图
访问的时候就是通过session匹配来判断的。登录后储存了session,然后通过匹配到session拦截器就可以放行直接访问页面了。
图