Spring MVC拦截器开发实例讲解
文学百科 时间:
推荐访问:
springmvc登录拦截器
一、什么是拦截器
Java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登陆,统一处理系统日志等。
二、拦截器的开发
1、创建一个测试拦截器类,并实现HandlerInterceptor接口的几个方法
在idea中,快速实现接口方法的快捷键是 Ctrl+I
接口实现3个方法说明:
1)、public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
执行时机:在进入handler方法之前执行
应用场景:一般用于进行身份认证和身份授权
如果身份认证不通过,要拦截,不向下执行,
return false表示拦截,return true表示放行
2)、public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
执行时机:进入handler方法之后,返回ModelAndView之前
应用场景:一般用于将共用的模型数据在这里传入视图(比如菜单导航),也可以在这里统一指定视图。
3)、public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
执行时机:执行handler完成后
应用场景:统一异常处理、统一日志处理
2、在springmvc中配置拦截器
方法一:
springmvc的拦截器不是全局的,针对HandlerMapping进行拦截器的设置,如果在某个HandlerMapping中配置了拦截器,经过该HandlerMapping映射成功的handler最终才使用该拦截器。
这个一般不常用,太麻烦
方法二:
spingmvc配置类似全局拦截器,springmvc框架将配置的拦截器注入到每个HandlerMapping中。
在spingmvc.xml中添加拦截器的配置信息,Springmvc支持多拦截器,要注意连接器链的顺序,/**表示支持子目录
<!--拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="fred.ssm.interceptor.HandlerInterceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="fred.ssm.interceptor.HandlerInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
这个实例我们测试2个拦截器,验证拦截器的运行时机
3、拦截器的测试
编写两个简单的拦截器,输出当前执行的方法名称,并且全部方向,测试执行结果。
当拦截器1和拦截器2都放行时: 查看日志输出 HandlerInterceptor1.preHandle HandlerInterceptor2.preHandle HandlerInterceptor2.postHandle HandlerInterceptor1.postHandle HandlerInterceptor2.afterCompletion HandlerInterceptor1.afterCompletion 当拦截器1放行和拦截器2不放行: HandlerInterceptor1.preHandle HandlerInterceptor2.preHandle HandlerInterceptor1.afterCompletion 当拦截器1不放行和拦截器2放行: HandlerInterceptor1.preHandle HandlerInterceptor1.preHandle 当拦截器1不放行和拦截器2不放行: HandlerInterceptor1.preHandle 4、总结: 1)、拦截器中只要有一个不放行,其后面的代码均不执行 2)、一个拦截器的执行顺序是:preHandle、postHandle、afterCompletion 3)、多个拦截器的执行顺序类似堆栈的概念,preHandle可以看成是堆(先进先出),postHandle、afterCompletion可以看成是栈(先进后出) 不管多少个拦截器,所有preHandle都是最先执行,而且按拦截器链顺序执行 所有拦截器的preHandle执行完成后,执行postHandle,且是先进后出,先执行最后面拦截器的postHandle 直到第一个拦截器的postHandle执行完成后,开始执行afterCompletion,也是先进后出的顺序,最后执行第一个拦截器的afterCompletion。 三、拦截器应用,用户登录 1、设计思想: 获取用户请求的url 如果url为公开地址,不需要认证,直接放行, 如果用户session不存在,跳转到登录页面 如果用户session存在,放行 2、controller开发 @Controller public class LoginController { @RequestMapping("/login") public String login(HttpSession session,String username,String password) throws Exception{ //创建session保存用户登录信息 session.setAttribute("username",username); return "redirect:/user/queryUserlist.action"; } @RequestMapping("/logout") public String logout(HttpSession session) throws Exception{ //清楚session session.invalidate(); return "redirect:/"; } } 3、拦截器开发 4、login视图开发 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>用户登录</title> </head> <body> <form action="${pageContext.request.contextPath}/login.action"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <input type="submit" value="登录"> </form> </body> </html> 5、springmvc拦截器配置 <!--拦截器--> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="fred.ssm.interceptor.HandlerInterceptor1"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="fred.ssm.interceptor.HandlerInterceptor2"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="fred.ssm.interceptor.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors> 添加拦截器LoginInterceptor 6、运行测试 访问静态页面 点击列表,拦截器生效,并跳转到login视图,点击登录调用@RequestMapping("/login") 进入列表页面 调用logout和logout.action都可以访问到@RequestMapping("/logout"),完成注销,因为系统使用了两个前端控制器,详情可以参考关于RESTfull的开发实例
当拦截器1和拦截器2都放行时: 查看日志输出 HandlerInterceptor1.preHandle HandlerInterceptor2.preHandle HandlerInterceptor2.postHandle HandlerInterceptor1.postHandle HandlerInterceptor2.afterCompletion HandlerInterceptor1.afterCompletion 当拦截器1放行和拦截器2不放行: HandlerInterceptor1.preHandle HandlerInterceptor2.preHandle HandlerInterceptor1.afterCompletion 当拦截器1不放行和拦截器2放行: HandlerInterceptor1.preHandle HandlerInterceptor1.preHandle 当拦截器1不放行和拦截器2不放行: HandlerInterceptor1.preHandle 4、总结: 1)、拦截器中只要有一个不放行,其后面的代码均不执行 2)、一个拦截器的执行顺序是:preHandle、postHandle、afterCompletion 3)、多个拦截器的执行顺序类似堆栈的概念,preHandle可以看成是堆(先进先出),postHandle、afterCompletion可以看成是栈(先进后出) 不管多少个拦截器,所有preHandle都是最先执行,而且按拦截器链顺序执行 所有拦截器的preHandle执行完成后,执行postHandle,且是先进后出,先执行最后面拦截器的postHandle 直到第一个拦截器的postHandle执行完成后,开始执行afterCompletion,也是先进后出的顺序,最后执行第一个拦截器的afterCompletion。 三、拦截器应用,用户登录 1、设计思想: 获取用户请求的url 如果url为公开地址,不需要认证,直接放行, 如果用户session不存在,跳转到登录页面 如果用户session存在,放行 2、controller开发 @Controller public class LoginController { @RequestMapping("/login") public String login(HttpSession session,String username,String password) throws Exception{ //创建session保存用户登录信息 session.setAttribute("username",username); return "redirect:/user/queryUserlist.action"; } @RequestMapping("/logout") public String logout(HttpSession session) throws Exception{ //清楚session session.invalidate(); return "redirect:/"; } } 3、拦截器开发 4、login视图开发 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>用户登录</title> </head> <body> <form action="${pageContext.request.contextPath}/login.action"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <input type="submit" value="登录"> </form> </body> </html> 5、springmvc拦截器配置 <!--拦截器--> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="fred.ssm.interceptor.HandlerInterceptor1"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="fred.ssm.interceptor.HandlerInterceptor2"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="fred.ssm.interceptor.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors> 添加拦截器LoginInterceptor 6、运行测试 访问静态页面 点击列表,拦截器生效,并跳转到login视图,点击登录调用@RequestMapping("/login") 进入列表页面 调用logout和logout.action都可以访问到@RequestMapping("/logout"),完成注销,因为系统使用了两个前端控制器,详情可以参考关于RESTfull的开发实例