ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[面试]HandlerInterceptors vs. Filters in Spring MVC

2022-09-01 13:31:27  阅读:208  来源: 互联网

标签:请求 HandlerInterceptors Spring void request throws vs Override public


一. Filters

过滤器是web服务器的一部分,而不是Spring框架的一部分。对于传入的请求,我们可以使用过滤器来操作甚至阻止请求到达任何的servlet。反之亦然,我们也可以阻止响应到达客户端。

创建filter

我们需要新建一个类,实现javax.servlet.Filter interface

@Component
public class LogFilter implements Filter {

    private Logger logger = LoggerFactory.getLogger(LogFilter.class);

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws IOException, ServletException {
        logger.info("Hello from: " + request.getLocalAddr());
        chain.doFilter(request, response);
    }

}

接下来,我们重写doFilter方法,在这里我们可以访问或操作ServletRequest、ServletResponse或FilterChain对象。我们可以使用FilterChain对象允许或阻止请求。
最后,我们通过@Component注释将Filter添加到Spring中。

二.HandlerInterceptors

HandlerInterceptors是Spring MVC框架的一部分,位于DispatcherServlet和我们的控制器之间。我们可以在请求到达控制器之前以及视图呈现之前和之后拦截请求。

创建HandlerInterceptors

要创建HandlerInterceptor,我们需要创建一个实现org.springframework.web.servlet.HandlerInterceptor接口的类。

  • preHandle() -在目标处理程序被调用之前执行
  • postHandle() -在目标处理程序之后但在DispatcherServlet呈现视图之前执行
  • afterCompletion() -在完成请求处理和视图呈现后回调
public class LogInterceptor implements HandlerInterceptor {

    private Logger logger = LoggerFactory.getLogger(LogInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
      throws Exception {
        logger.info("preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 
      throws Exception {
        logger.info("postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 
      throws Exception {
        logger.info("afterCompletion");
    }

}

三.关键区别和使用范例


过滤器在请求到达DispatcherServlet之前拦截请求,这使得它们非常适合执行粗粒度的任务,例如:

  • 身份验证
  • 日志记录和审计
  • 图像和数据压缩
  • 任何我们想从SpringMVC中解耦的功能
    HandlerIntercepors拦截DispatcherServlet和控制器之间的请求。这是在Spring MVC框架内完成的,提供了对处理程序和ModelAndView对象的访问

四.总结

区别 拦截器 过滤器
实现原理 基于Java的反射机制(动态代理) 基于函数回调
使用范围 是一个Spring组件,并由Spring容器管理,可以单独使用 实现 javax.servlet.Filter 接口,该接口在Servlet规范中定义,因此只能在web程序中使用
触发时机 请求进入servlet中,进入Controlloer之前预处理,Controlloer渲染了对应的视图之后请求结束 请求进入容器但进去servlet之前预处理,servlet处理完之后结束
拦截的请求范围 只对controller中请求或访问static目录下的资源请求起作用 对所有请求起作用

补充:

  1. 过滤器Filter基于函数回调?
    函数回调:A类拥有B类引用,通过A类完成业务时,对B进行实现,由调用方控制B的实现。相当于A调用了B,B中又调用了A的业务逻辑

举例:你去图书馆借两本书,但是只有一本有,另外一本被别人借走了,于是你就先借了一本,跟管理员说,等第二本到了,跟你打电话,你来拿。
上面的过程就相当于一个回调函数,你是回调对象,管理员是控制器对象,打电话是回调的方法。

引自https://blog.csdn.net/weixin_44036154/article/details/108220620

@WebFilter("/*")  //对所有的请求都执行该过滤器
public class EncodingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    //执行过滤处理
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {

        req.setCharacterEncoding("UTF-8");

        //放行
        filterChain.doFilter(req,resp);
    }

    @Override
    public void destroy() {
    }
}

在调用 doFilter 方法时,会传递一个 filterChain 对象进来,如果调用该方法,则 web 服务器就会调用 web 资源的 service 方法,即 web 资源就会被访问。

  1. 拦截器?
    我们创建一个计算方法执行时间的拦截器
@Slf4j
public class MyHandlerInterceptor implements HandlerInterceptor {

    // 进入我们的 Controller方法之前执行,如果返回结果为false,那么的处理器就不执行了。如果为true,放行。
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("==================preHandle====================");
//        String path = request.getServletPath();
//        System.out.println(handler);
//        System.out.println(path);
        Long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        log.info(handler + "被调用了");
        return true;
    }

    // 我们的处理器执行完毕,在返回 modelAndView 给前端控制器之前执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//        System.out.println("==================postHandle====================");
        Long startTime = (Long)request.getAttribute("startTime");
        Long endTime = System.currentTimeMillis();
        log.info("执行时间为:" + (endTime-startTime)/1000 + "秒");
    }

    // 把 modelAndView 返回给前端控制器之后执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//        System.out.println("==================afterCompletion====================");
    }
}

流程如下:

我们从流程图可以看到,拦截器的执行是在穿插在SpringMvc的工作流程中的,并没有用到动态代理机制,直接调用的拦截器方法。
拦截器在实现层面,并没有用到aop,并没有切面,通知这一类的代码,所以它的实现并不是基于aop的。但是拦截器从思想层面上,是面向切面编程的,是在controller这个层面上进行的代码织入。

引自https://blog.csdn.net/oracle1158/article/details/123307319

标签:请求,HandlerInterceptors,Spring,void,request,throws,vs,Override,public
来源: https://www.cnblogs.com/vincy9501/p/16645109.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有