首页 > 其他分享 >[面试]HandlerInterceptors vs. Filters in Spring MVC

[面试]HandlerInterceptors vs. Filters in Spring MVC

时间:2022-09-01 13:34:11浏览次数:61  
标签:请求 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
From: https://www.cnblogs.com/vincy9501/p/16645109.html

相关文章

  • vscode 配置 plantuml
    官网:https://plantuml.com/zh/1.JDK下载安装https://www.oracle.com/java/technologies/javase-downloads.html本次安装PC下载:jdk-18_windows-x64_bin.msi,可以根据自......
  • SpringBoot-Http请求工具类
    一、编写请求配置类importcom.alibaba.fastjson.JSONObject;importorg.springframework.context.annotation.Configuration;importorg.springframework.http.*;imp......
  • springboot整合redis,设置缓存过期时间
    注:redis服务器要先开启!或者连接远程服务器上的Redis,但是依然要开启服务,不然会一直TimeOut!Pom文件添加依赖<dependency><groupId>org.springframework.boot</......
  • SpringBoot项目引入Swagger接口文档
    一、在项目中引入Swagger依赖<!--swagger--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifa......
  • 学习如何将代码从 VSCode 推送到 GitHub
    学习如何将代码从VSCode推送到GitHub您是一名开发人员,大部分时间都在通过在不同窗口之间切换来编辑代码、查看更改以及将代码从VSCode推送到GitHub来消耗大部分时......
  • VSCode创建Vue项目完整教程
    VSCode创建Vue项目完整教程文章目录一、配置环境1.安装VSCode2.安装node.js3.安装配置脚手架vue-cli二、创建vue项目1.命令方式创建2.重新初始化依赖3.启动项目......
  • springboot+Vue项目允许跨域
    packagecom.example.demo.itkb.user.config;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotat......
  • SpringMVC支持ant风格
    SpringMVC中的ant风格?:表示任意单个字符*:任意0个或多个字符**:表示任意的一层或多层目录注:在使用的时候,只能使用//xxx的方式......
  • python + VS code + Docker
    目录1.安装docker2.构建映像3.启动docker4.安装VisualStudioCode并配置5.参考在python项目开发中,经常需要安装依赖包,还要考虑版本兼容问题。尤其是,升级一个python版本,......
  • SpringMVC学习笔记(一)——简介
    1.MVC模式是什么1.1MVC模式简介MVC模式,全称为Model-View-Controller(模型-视图-控制器)模式,它是一种软件架构模式,其目标是将软件的用户界面(即前台页面)和业务逻辑分离,使......