可单例开发、典型的教科书式的mvc构架----springmvc----day02(六)
10.拦截器
10.1定义拦截器,实现HandlerInterceptor接口,接口中提供三个方法。
public class HandlerInterceptor1 implements HandlerInterceptor {
// 执行Handler完成执行此方法
// 应用场景:统一的异常处理,统一日志处理
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception exception) throws Exception {
System.out.println("HandlerInterceptor1.......afterComletion");
}
// 进入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 {
// return false表示拦截,不再向下执行
// return trueb表示方向
System.out.println("HandlerInterceptor1.......preHandle");
return true;
}
}
10.2拦截器配置
10.2.1针对HandlerMapping配置
springmvc拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该HandlerMapping映射成功的handler最终使用该拦截器。
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="handlerInterceptor1"/>
<ref bean="handlerInterceptor2"/>
</list>
</property>
</bean>
<bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>
<bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
一般不推荐使用
10.2.2类似全局的拦截器
springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中。
<!-- 拦截器 -->
<mvc:interceptors>
<!-- 多个拦截器,顺序执行 -->
<!-- 登录认证拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.changemax.ssm.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<!-- /**表示所有url路径包括子路径 -->
<mvc:mapping path="/**" />
<bean class="com.changemax.ssm.interceptor.HandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.changemax.ssm.interceptor.HandlerInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
10.3拦截测试
10.3.1测试需求
测试多个拦截器各个方法执行时机。
10.3.2编写两个拦截
10.3.3两个拦截器都放行
总结:
preHandler方法按顺序执行,
postHandler和afterCompletion按拦截器配置的逆向顺序执行。
10.3.4拦截器1放行,拦截器2不放行
总结:
拦截器1放行,拦截器2preHandler才会执行。
拦截器2preHandler不放行,拦截器2postHandle和afterCompletion不会执行。
只要有一个拦截器不放行,postHandle不会执行
10.3.5小结
根据测试结果,对拦截器应用。
比如:统一日志处理拦截器,需要该 拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置。
比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)
10.4 拦截器应用(实现登陆认证)
10.4.1需求:
1.用户请求url
2.拦截器进行拦截校验
如果请求的url是公开地址(无需登录即可访问的url),让放行
如果用户session不存在跳转的登录页面
如果用户session存在放行,继续操作。
10.4.2登录controller方法
@Controller
public class LoginController{
// 登入
@RequestMapping("/login")
public String login(HttpSession session, 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 {
// 调用service进行用户身份验证
// ..
// 在session中保存用户身份信息
session.invalidate();
return "redirect:/items/queryItems.action";
}
}
10.4.3登陆认证拦截实现
10.4.3.1代码实现
public class LoginInterceptor implements HandlerInterceptor {
// 执行Handler完成执行此方法
// 应用场景:统一的异常处理,统一日志处理
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception exception) throws Exception {
System.out.println("HandlerInterceptor1.......afterComletion");
}
// 进入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().toString();
// 判断url是否为公开地址(实际使用时公开地址配置配置文件中)
if (url.indexOf("login.action") >= 0) {
// 如果进行登入提交,就放行
return true;
}
// 判断session
HttpSession session = request.getSession();
// 从session取出用户的身份信息
String username = (String) session.getAttribute("username");
if (username != null) {
return true;
}
//表示用户身份需要认证
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
// return false表示拦截,不再向下执行
// return trueb表示方向
System.out.println("HandlerInterceptor1.......preHandle");
return false;
}
}
10.4.3.2拦截器配置
<!-- 拦截器 -->
<mvc:interceptors>
<!-- 多个拦截器,顺序执行 -->
<!-- 登录认证拦截器 -->
<mvc:interceptor>
<!-- /**表示所有url路径包括子路径 -->
<mvc:mapping path="/**" />
<bean class="com.changemax.mas.interceptor.AdminInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>