springmvc拦截器的定义和配置

来源:互联网 发布:诺基亚e66软件下载 编辑:程序博客网 时间:2024/06/17 18:11
拦截器
1.拦截定义

定义拦截器,实现HandlerInterceptor接口。接口中提供三个方法。
package cn.edu.hpu.ssm.interceptor;    import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;    import org.springframework.web.servlet.HandlerInterceptor;  import org.springframework.web.servlet.ModelAndView;    //测试拦截器1  public class HandlerInterceptor1 implements HandlerInterceptor{          //执行Handler方法之前执行      //用于身份认证、身份授权      //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行      @Override      public boolean preHandle(HttpServletRequest request, HttpServletResponse response,              Object handler) throws Exception {                              //return false表示拦截,不向下执行          //return true表示放行                  return false;      }            //进入Handler方法之后,返回modelAndView之前执行      //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里      //传到视图,也可以在这里统一指定视图      @Override      public void postHandle(HttpServletRequest request, HttpServletResponse response,              Object handler, ModelAndView modelAndView) throws Exception {                           }            //执行Handler完成执行此方法      //应用场景:统一异常处理,统一日志处理      @Override      public void afterCompletion(HttpServletRequest request, HttpServletResponse response,              Object handler, Exception ex)              throws Exception {                           }  }  
2.拦截器配置
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"/>  
一般不推荐使用。

2.2类似全局的拦截器
springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中。

<!-- 拦截器 -->  <mvc:interceptors>      <!-- 多个拦截器,顺序执行 -->      <mvc:interceptor>          <!-- /**表示所有url包括子url路径 -->          <mvc:mapping path="/**"/>          <bean class="cn.edu.hpu.ssm.interceptor.HandlerInterceptor1"/>      </mvc:interceptor>      <mvc:interceptor>          <mvc:mapping path="/**"/>          <bean class="cn.edu.hpu.ssm.interceptor.HandlerInterceptor2"/>      </mvc:interceptor>  </mvc:interceptors>  

3.拦截测试
3.1测试需求
测试多个拦截器各各方法执行时机。

3.2编写两个拦截
HandlerInterceptor1.java:
package cn.edu.hpu.ssm.interceptor;    import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;    import org.springframework.web.servlet.HandlerInterceptor;  import org.springframework.web.servlet.ModelAndView;    //测试拦截器1  public class HandlerInterceptor1 implements HandlerInterceptor{          //执行Handler方法之前执行      //用于身份认证、身份授权      //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行      @Override      public boolean preHandle(HttpServletRequest request, HttpServletResponse response,              Object handler) throws Exception {                    System.out.println("HandlerInterceptor1......preHandle");                    //return false表示拦截,不向下执行          //return true表示放行                  return false;      }            //进入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 void afterCompletion(HttpServletRequest request, HttpServletResponse response,              Object handler, Exception ex)              throws Exception {                    System.out.println("HandlerInterceptor1......afterHandle");                }  }  
HandlerInterceptor2.java:
package cn.edu.hpu.ssm.interceptor;      import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;      import org.springframework.web.servlet.HandlerInterceptor;  import org.springframework.web.servlet.ModelAndView;      //测试拦截器2  public class HandlerInterceptor2 implements HandlerInterceptor{          //执行Handler方法之前执行      //用于身份认证、身份授权      //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行      @Override      public boolean preHandle(HttpServletRequest request, HttpServletResponse response,              Object handler) throws Exception {                    System.out.println("HandlerInterceptor2......preHandle");                    //return false表示拦截,不向下执行          //return true表示放行                  return false;      }            //进入Handler方法之后,返回modelAndView之前执行      //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里      //传到视图,也可以在这里统一指定视图      @Override      public void postHandle(HttpServletRequest request, HttpServletResponse response,              Object handler, ModelAndView modelAndView) throws Exception {                    System.out.println("HandlerInterceptor2......postHandle");                }            //执行Handler完成执行此方法      //应用场景:统一异常处理,统一日志处理      @Override      public void afterCompletion(HttpServletRequest request, HttpServletResponse response,              Object handler, Exception ex)              throws Exception {                    System.out.println("HandlerInterceptor2......afterHandle");                }  }  

3.3两个拦截器都放行
将preHandle方法的返回值设为true,然后随便访问一个controller,控制台打印一下结果:

HandlerInterceptor1...preHandle  HandlerInterceptor2...preHandle    HandlerInterceptor2...postHandle  HandlerInterceptor1...postHandle    HandlerInterceptor2...afterCompletion  HandlerInterceptor1...afterCompletion  
总结:
preHandle方法按顺序执行,
postHandle和afterCompletion按拦截器配置的逆向顺序执行。

3.4拦截器1放行,拦截器2不放行

HandlerInterceptor1...preHandle  HandlerInterceptor2...preHandle  HandlerInterceptor1...afterCompletion 

总结:
拦截器1放行,拦截器2 preHandle才会执行。
拦截器2 preHandle不放行,拦截器2 postHandle和afterCompletion不会执行。
只要有一个拦截器不放行,postHandle不会执行。
3.5拦截器1不放行,拦截器2不放行

HandlerInterceptor1...preHandle  
拦截器1 preHandle不放行,postHandle和afterCompletion不会执行。
拦截器1 preHandle不放行,拦截器2不执行。

4.根据测试结果,对拦截器应用。

比如:统一日志处理拦截器,需要该拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置。

比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)

5拦截器应用(实现登陆认证)

5.1需求

(1)用户请求url
(2)拦截器进行拦截校验
如果请求的url是公开地址(无需登陆即可访问的url),让放行
如果用户session 不存在跳转到登陆页面
如果用户session存在放行,继续操作。

5.2登陆controller方法
package cn.edu.hpu.ssm.controller;    import javax.servlet.http.HttpSession;    import org.springframework.stereotype.Controller;  import org.springframework.web.bind.annotation.RequestMapping;    @Controller  public class LoginController {            //登录      @RequestMapping("/login")      public String login(HttpSession session,String username,String password)throws Exception{          //调用serivce进行用户身份验证          //...                    //在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";      }  }  
登录页面:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  <%  String path = request.getContextPath();  String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  %>      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  <html>    <head>      <base href="<%=basePath%>">            <title>系统登录</title>        </head>        <body>     <form action="${pageContext.request.contextPath }/login.action" method="post">      用户账号:<input type="text" name="username"/><br/>      用户密码:<input type="password" name="password"/><br/>      <input type="submit" value="登录"/>     </form>    </body>  </html>  
在商品列表那里加入:
当前用户:${username }|  <c:if test="${username!=null }">  <a href="${pageContext.request.contextPath }/logout.action">退出</a>  </c:if>  

5.3登陆认证拦截实现

5.3.1代码实现

package cn.edu.hpu.ssm.interceptor;    import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import javax.servlet.http.HttpSession;    import org.springframework.web.servlet.HandlerInterceptor;  import org.springframework.web.servlet.ModelAndView;    //登录认证的拦截器  public class LoginInterceptor implements HandlerInterceptor{        //执行Handler方法之前执行      //用于身份认证、身份授权      //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行      @Override      public boolean preHandle(HttpServletRequest request, HttpServletResponse response,              Object handler) throws Exception {                    //获取请求的url          String url=request.getRequestURI();          //判断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 true表示放行                  return false;      }            //进入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 void afterCompletion(HttpServletRequest request, HttpServletResponse response,              Object handler, Exception ex)              throws Exception {                    System.out.println("HandlerInterceptor1......afterHandle");                }  }  
5.3.2拦截器配置
springmvc.xml中配置:

<!-- 拦截器 -->  <mvc:interceptors>      <!-- 多个拦截器,顺序执行 -->      <!-- 登录认证拦截器 -->      <mvc:interceptor>          <mvc:mapping path="/**"/>          <bean class="cn.edu.hpu.ssm.interceptor.LoginInterceptor"/>      </mvc:interceptor>  </mvc:interceptors>  

测试:
输入商品列表的网址,结果发现被拦截在登录界面(原因:拦截器没有检测到登录用户的session,所以判定用户没有登录,没有权限查看商品列表)


原创粉丝点击