Java interceptor 拦截器

一:拦截器的应用场景

1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page VIEW)等。
2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。
5、OpenSessionInView:如Hibernate,在进入处理器打开SESSION,在完成后关闭SESSION。

二:拦截器与过滤器的区别

 1、拦截器是基于Java的反射机制的,而过滤器是基于函数回调。
 2、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
 3、拦截器只能对ACTION请求起作用,而过滤器则可以对几乎所有的请求起作用。
 4、拦截器可以访问ACTION上下文、值栈里的对象,而过滤器不能访问。
 5、在ACTION的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
 6、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。


三:拦截器的实现

1.过滤器是JavaEE标准,采用函数回调的方式进行。是在请求进入容器之后,还未进入Servlet之前进行预处理,并且在请求结束返回给前端这之间进行后期处理。

点击(此处)折叠或打开

  1. @Override
  2.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  3.         System.out.println("before...");
  4.         chain.doFilter(request, response);
  5.         System.out.println("after...");
  6.     }
chain.doFilter(request, response);这个方法的调用作为分水岭。事实上调用Servlet的doService()方法是在chain.doFilter(request, response);这个方法中进行的。

2.拦截器是被包裹在过滤器之中的。

点击(此处)折叠或打开

  1. @Override
  2.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  3.         System.out.println("preHandle");
  4.         return true;
  5.     }

  6.     @Override
  7.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  8.         System.out.println("postHandle");
  9.     }

  10.     @Override
  11.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  12.         System.out.println("afterCompletion");
  13.     }
a.preHandle()这个方法是在过滤器的chain.doFilter(request, response)方法的前一步执行,也就是在 [System.out.println("before...")][chain.doFilter(request, response)]之间执行。
b.preHandle()方法之后,在RETURN ModelAndView之前进行,可以操控Controller的ModelAndView内容。
c.afterCompletion()方法是在过滤器返回给前端前一步执行,也就是在[chain.doFilter(request, response)][System.out.println("after...")]之间执行。

四:SpringMvc 拦截器和过滤器执行流程




五:实例

点击(此处)折叠或打开

  1. public class SystemAccessInterceper extends HandlerInterceptorAdapter {

  2.     private final String checkpointName = "DO_CHECKPOINT";
  3.     private final String shareType = "enjoylink_share";
  4.     String[] noFilters = ConfigureUtil.getStringArray("nofilter.urls");

  5.     private final Logger logger = Logger.getLogger(getClass());

  6.     @Override
  7.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
  8.             throws Exception {
  9.         String userAgent = request.getHeader("user-agent");
  10.         userAgent = StringUtils.startsWith(userAgent, Constants.USER_AGENT) ? userAgent
  11.                 : request.getHeader("x-user-agent");
  12.         String type = request.getParameter("shareType");
  13.         String requestUri = request.getRequestURI();
  14.         if (isFilter(requestUri)) {
  15.             return true;
  16.         }
  17.         logger.info("User-Agent:" + userAgent);
  18.         if (!StringUtils.equalsIgnoreCase(shareType, type) && (!StringUtils.startsWith(userAgent, Constants.USER_AGENT)
  19.                 || 2 > StringUtils.indexOfAny(userAgent, "|"))) {
  20.             logger.info("非法请求接口!!");
  21.             return false;
  22.         }

  23.         try {
  24.             if (StringUtils.contains(userAgent, "|")) {
  25.                 String[] agts = userAgent.split("\\|");
  26.                 request.setAttribute(Constants.HEAD_SYS, agts[1]);
  27.                 request.setAttribute(Constants.HEAD_VERSION, agts[2]);
  28.             }
  29.             request.setAttribute(Constants.LOG_ACCESS_TIME, System.currentTimeMillis());
  30.             return super.preHandle(request, response, handler);
  31.         }
  32.         catch (Exception e) {
  33.             logger.error("拦截器验证失败!", e);
  34.             return false;
  35.         }
  36.     }

  37.     /**
  38.      * TODO: 检查是否需要过滤
  39.      *
  40.      * @param uri
  41.      * @return
  42.      */
  43.     private boolean isFilter(String uri) {
  44.         if (org.apache.commons.lang3.ArrayUtils.isEmpty(noFilters)) {
  45.             return Boolean.TRUE;
  46.         }

  47.         for (String noFilter : noFilters) {
  48.             if (StringUtils.contains(uri, noFilter)) {
  49.                 return Boolean.TRUE;
  50.             }
  51.         }

  52.         return Boolean.FALSE;
  53.     }

  54.     @Override
  55.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
  56.             throws Exception {
  57.         super.afterCompletion(request, response, handler, ex);
  58.         Object obj = request.getAttribute(Constants.LOG_ACCESS_TIME);
  59.         if (null != obj) {
  60.             Object rb = request.getAttribute(Constants.RETURN_BODY);
  61.             long accessTime = (long) obj;
  62.             if (null == rb || StringUtils.isEmpty(rb.toString())) {
  63.                 logger.info("不进行检查点处理!");
  64.                 logger.info("处理请求" + request.getRequestURI() +"耗时"+ (System.currentTimeMillis() - accessTime) + "毫秒!");
  65.                 return;
  66.             }
  67.             Object userId = request.getAttribute(Constants.REQUEST_USERID);
  68.             String system = request.getAttribute(Constants.HEAD_SYS).toString();
  69.             String version = request.getAttribute(Constants.HEAD_VERSION).toString();

  70.             logger.warn("处理请求|" + ((null == userId || "".equals(userId.toString())) ? "0" : userId.toString()) + "|"
  71.                     + system + "|" + version + "|" + request.getRequestURI() + "|"
  72.                     + GbdDateUtils.format(Calendar.getInstance().getTime(), "yyyy-MM-dd HH:mm:ss") + "|"
  73.                     + (System.currentTimeMillis() - accessTime) + "|毫秒!");
  74.             try {
  75.                 HandlerMethod handlerMethod = (HandlerMethod) handler;
  76.                 BusinessCheckPoint checkPoint = handlerMethod.getMethodAnnotation(BusinessCheckPoint.class);
  77.                 if (null != checkPoint) {
  78.                     String checkpointKey = checkPoint.checkName();

  79.                     // 业务处理结果为正确时。发送积分或者信用累积
  80.                     if (null != rb && null != userId && StringUtils.isNotEmpty(userId.toString())) {
  81.                         ReturnBody returnBody = (ReturnBody) rb;
  82.                         // 检查点检测,如果是检查点则发送消息
  83.                         if (returnBody.getCode() > 0) {
  84.                             // 发送检查点消息
  85.                             CodeDesc codeDesc = new CodeDesc();
  86.                             codeDesc.setJmsType(checkpointName);
  87.                             codeDesc.setName(checkpointKey);
  88.                             codeDesc.setBusinessCode(returnBody.getCheckpointCode());
  89.                             codeDesc.setUserId(Integer.valueOf(userId.toString()));
  90.                             JmsUtil.pushToUserQueue(codeDesc);
  91.                         }
  92.                     }
  93.                 }
  94.             }
  95.             catch (Exception e) {
  96.                 logger.error("发送积分消息失败!", e);
  97.             }
  98.         }
  99.     }

  100. }


点击(此处)折叠或打开

  1. <!-- 拦截器配置 -->
  2.     <mvc:interceptors>
  3.         <bean class="com.gemdale.ghome.business.intercepter.SystemAccessInterceper" />
  4.     </mvc:interceptors>



来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28624388/viewspace-2130071/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/28624388/viewspace-2130071/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值