1、 拦截器
1.1拦截器定义
定义拦截器,实现HandlerInterceptor接口,接口中提供三个方法。
public class HandlerInterceptor implements org.springframework.web.servlet.HandlerInterceptor{
//执行Handler完成执行此方法
//应用场景:统一异常、日志处理
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
//进入Handler方法之后,返回modelAndView之前执行
//应用场景从modelAndView出发:将公用的模型数据在这里传到视图(比如菜单导航),也可以在这里统一指定视图
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
}
//进入Handler方法之前执行
//用于身份认证,身份授权,如果认证不通过,表示当前用户没有登录,需要此方法拦截不再向下执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
//return false 拦截,不向下执行
return false;
}
}
2、 拦截器配置
2.1针对HandlerMapping进行拦截设置。
如果在某个HandlerMapping中配置拦截,经过该HandlerMapping映射成功的handler最终才使用该拦截器。
<bean class="org.springframework.web.servlet.handler.BeanNamerUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean = "handlerInterceptor1"/>
<ref bean = "handlerInterceptor2"/>
</list>
</property>
</bean>
<bean id="handlerInterceptor1" class="springmvc.interceptor.HandlerInterceptor1"></bean>
<bean id="handlerInterceptor2" class="springmvc.interceptor.HandlerInterceptor2"></bean>
一般不推荐使用
2.2类似全局的拦截器
springMVC配置类似全局的拦截器,springMVC框架将配置类似全局的拦截器注入到每个HandlerMapping中。
<!-- 拦截器 -->
<mvc:interceptors>
<!-- 多个拦截器,顺序执行 -->
<mvc:interceptor>
<!-- path="/**"表示所有URL包括子URL路径 -->
<mvc:mapping path="/**"/>
<bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.itcast.ssm. interceptor.HandlerInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
3、 拦截器测试
3.1测试需求
测试多个拦截器各个方法执行时机。
3.2编写两个拦截器
HandlerInterceptor1.java
HandlerInterceptor2.java
3.3两个拦截器都放行
控制台输出:
HandlerInterceptor1…preHandler
HandlerInterceptor2…preHandler
HandlerInterceptor2…postHandler
HandlerInterceptor1…postHandler
HandlerInterceptor2…afterCompletion
HandlerInterceptor1…afterCompletion
总结:
preHandler方法按顺序执行
postHandler和afterCompletion按拦截器配置的逆向顺序执行
3.4拦截器1放行,拦截器2不放行
HandlerInterceptor1…preHandler
HandlerInterceptor2…preHandler
HandlerInterceptor1…afterCompletion
总结:
拦截器1放行,拦截器2 preHandler才会执行。
拦截器2 preHandler不放行,拦截器2 的postHandler和afterCompletion方法不会执行。
只要有一个拦截器不放行,postHandler不会执行。
3.5拦截器1不放行,拦截器2不放行
HandlerInterceptor1…preHandler
总结:
拦截器1 preHandler不放行,postHandler和afterCompletion方法不会执行。
拦截器2也不执行。
小结:
根据测试结果,对拦截器进行应用。
比如:统一日志处理拦截器,需要改拦截器preHandler一定要放行,且将它放在拦截器连接中第一个位置。
比如:登录认证拦截器,放在拦截器连接中第一个位置。权限校验拦截器,放在登录认证拦截器之后。(因为登录通过后才校验)
4、 拦截器的应用(实现登录认证)
4.1需求
1.用户请求URL
2.拦截器进行拦截校验
如果请求URL是公开地址,让放行
如果用户session不存在跳转到登录页面
如果用户session存在放行,继续操作。
4.2登录controller方法
//登录
@RequestMapping("/login")
public String login(String username,String password)throws Exception{
//调用service进行用户身份验证
//...
//在session中保存用户信息
session.setAttribute("username",username);
//重定向到商品列表页面
return "redirect:/items/queryItems.action";
}
//退出
@RequestMapping("/logout")
public String logout(HttpSession session)throws Exception{
//清除session
session.invalidate();
//重定向到商品列表页面
return "redirect:/items/queryItems.action";
}
4.3登录认证拦截实现
public class LoginInterceptor implements org.springframework.web.servlet.HandlerInterceptor{
//执行Handler完成执行此方法
//应用场景:统一异常、日志处理
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("HandlerInterceptor1..afterCompletion");
}
//进入Handler方法之后,返回modelAndView之前执行
//应用场景从modelAndView出发:将公用的模型数据在这里传到视图(比如菜单导航),也可以在这里统一指定视图
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1..postHandle");
}
//进入Handler方法之前执行
//用于身份认证,身份授权,如果认证不通过,表示当前用户没有登录,需要此方法拦截不再向下执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
//获得请求的URL
String url = request.getRequestURL();
//判断URL是否是公开地址(实际使用时公开地址配置在配置文件中)
//这里公开地址是登录提交的地址
if(url.indexOf("login.action")>0){
//如果进行登录提交,放行
return true;
}
//判断session
HttpSession session = request.getSession();
String username =(String) session.getAttribute("username");
if(username != null){
return true;
}
//执行这里表示用户身份需要认证,跳转登录页面
request.getRequestDispatcher("WEB-INF/login.jsp").forward(request,response);
//return false 拦截,不向下执行
return true;
}
}
4.3配置拦截器
<!-- 登录 验证拦截器-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.itcast.ssm.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>