SpringMVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
一.拦截器demo
1.编写拦截器
public class HandlerInterceptor1 implements HandlerInterceptor {
//进入Handler方法之前执行
//场景:身份认证以及身份授权
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("HandlerInterceptor1......preHandle");
return false;
}
//进入Handler方法之后,返回modelAndView之前执行
//场景:将公用的模型数据(菜单导航栏)在这里传到视图
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1......postHandle");
}
//执行完Handler后之后执行
//场景:统一异常处理以及统一日志处理
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("HandlerInterceptor1......afterCompletion");
}
}
2.配置拦截器
<!-- 拦截器 -->
<mvc:interceptors>
<!-- 多个拦截器,顺序执行 -->
<mvc:interceptor>
<!-- 拦截所有url包括子url -->
<mvc:mapping path="/**"/>
<bean class="com.steven.ssm.utils.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.steven.ssm.utils.interceptor.HandlerInterceptor1"></bean>
</mvc:interceptor>
</mvc:interceptors>
3.测试结果总结
拦截器1和拦截器2都放行:
拦截器1preHandle…
拦截器2 preHandle…
拦截器2 postHandle…
拦截器1postHandle…
拦截器2 afterCompletion…
拦截器1 afterCompletion…
先执行拦截器1的preHandle再执行拦截器2的preHandle,后处理是限制性拦截器2再执行拦截器1
拦截器1放行拦截器2不放行:
拦截器1preHandle…
拦截器2 preHandle…
拦截器1 afterCompletion…
分析:拦截器1preHandle执行拦截器2preHandle也执行,被拦截器2中断后,后面的方法都不执行,除了拦截器1的afterCompletion。
拦截器1不放行拦截器2不放行:
拦截器1preHandle…
分析:只执行拦截器1的preHandle方法。
如果要是统一的日志处理需求,需要放到拦截器1的前处理中。
拦截器是按照在springmvc.xml中的配置顺序执行。
二.用户认证
需求:访问网站的任何url(登陆页面除外)先判断是否登陆,如果未登录跳转到登陆页面。
1.编写拦截器
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
//获取请求的url
String requestURI = request.getRequestURI();
if (requestURI.contains("login")) {
return true;
}
//判断用户的登陆状态
String username = (String) request.getSession().getAttribute("username");
//如果session中没有用户信息跳转到登陆页面
if (username != null) {
return true;
}
request.getRequestDispatcher("/WEB-INF/views/items/login.jsp").forward(request,response);
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 {
}
}
2.配置拦截器
<!-- 拦截器 -->
<mvc:interceptors>
<!-- 多个拦截器,顺序执行 -->
<!-- 拦截所有url包括子url -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.steven.ssm.utils.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
3.handler编写
@Controller
public class LoginController {
//登录
@RequestMapping("/login")
public String login( HttpSession session, String username, String password){
//调用service进行用户身份验证
session.setAttribute("username", username);
return "redirect:items/queryItems";
}
//登出
@RequestMapping("/logout")
public String logout( HttpSession session){
//调用service进行用户身份验证
session.invalidate();
return "redirect:items/queryItems";
}
}
4.web层编写
<form action="${pageContext.request.contextPath}/login">
用户名:<input type="text" name="username"><br>
密码:<input type="text" name="password"><br>
<input type="submit" value="登陆">
</form>
当前用户:${username},
<c:if test="${username!=null}">
<a href="${pageContext.request.contextPath}/logout">退出</a>
</c:if>