我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Spring中拦截器的原理与使用方法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Spring中拦截器的原理与使用方法

这篇文章主要讲解了“Spring中拦截器的原理与使用方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring中拦截器的原理与使用方法”吧!

    1.Spring中的拦截器

    在web开发中,拦截器是经常用到的功能。它可以帮我们预先设置数据以及统计方法的执行效率等等。

    spring中拦截器主要分两种,一个是HandlerInterceptor,一个是MethodInterceptor。

    1.1HandlerInterceptor拦截器

    HandlerInterceptor是springMVC项目中的拦截器,它拦截的目标是请求的地址,比MethodInterceptor先执行。其工作原理是当请求来时先进性预处理,如下。

    Spring中拦截器的原理与使用方法

    这里我们可以实现一个通过HandlerInterceptor实现打印请求开始和结束的日志,如下。

    1.依赖引入

            <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>

    2.实现类

    拦截器类

    @Componentpublic class EasyLogControllerInterceptor implements HandlerInterceptor {         public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)            throws Exception {        System.out.println(request.getRequestURI()+"开始执行");        return true;    }         public void postHandle(            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)            throws Exception {    }         public void afterCompletion(            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)            throws Exception {        System.out.println(request.getRequestURI()+"执行结束");    } }

    controller类

    @RestControllerpublic class TestController {     @GetMapping("/hello")    public Map<String,String> hello(){        Map<String,String> response=new HashMap<>();        response.put("msg","hello");        return response;    } }

    配置类

    @Configurationpublic class IntercepterConfig implements WebMvcConfigurer {     @Autowired    private EasyLogControllerInterceptor easyLogControllerInterceptor;     @Override    public void addInterceptors(InterceptorRegistry registry) {        //addPathPatterns用于添加拦截路径        //excludePathPatterns用于添加不拦截的路径        registry.addInterceptor(easyLogControllerInterceptor).addPathPatterns("/hello");     }      //此方法用于配置静态资源路径    @Override    public void addResourceHandlers(ResourceHandlerRegistry registry) {        registry.addResourceHandler("/**").addResourceLocations("classpath:/my/");    }}

    3.运行效果

    Spring中拦截器的原理与使用方法

    Spring中拦截器的原理与使用方法

    1.1.1HandlerInterceptor讲解

    实现一个HandlerInterceptor拦截器可以直接实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter类。这两种方法殊途同归,其实HandlerInterceptorAdapter也就是声明了HandlerInterceptor接口中所有方法的默认实现,而我们在继承他之后只需要重写必要的方法。

    下面就是HandlerInterceptorAdapter的代码,可以看到一个方法只是默认返回true,另外两个是空方法:

    public abstract class HandlerInterceptorAdapter implements HandlerInterceptor {         public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)          throws Exception {          return true;      }       public void postHandle(              HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)              throws Exception {      }         public void afterCompletion(              HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)              throws Exception {      }    }

    这三个方法都是干什么的,有什么作用,什么时候调用,不同的拦截器之间是怎样的调用顺序呢?

    先补一张图:

    Spring中拦截器的原理与使用方法

    这还得参考一下DispatcherServlet的doDispatch方法: 

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {          HttpServletRequest processedRequest = request;          HandlerExecutionChain mappedHandler = null;          int interceptorIndex = -1;            try {              ModelAndView mv;              boolean errorView = false;                try {                  processedRequest = checkMultipart(request);                    // Determine handler for the current request.                  mappedHandler = getHandler(processedRequest, false);                  if (mappedHandler == null || mappedHandler.getHandler() == null) {                      noHandlerFound(processedRequest, response);                      return;                  }                    // Determine handler adapter for the current request.                  HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());                    // Process last-modified header, if supported by the handler.                  String method = request.getMethod();                  boolean isGet = "GET".equals(method);                  if (isGet || "HEAD".equals(method)) {                      long lastModified = ha.getLastModified(request, mappedHandler.getHandler());                      if (logger.isDebugEnabled()) {                          String requestUri = urlPathHelper.getRequestUri(request);                          logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);                      }                      if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {                          return;                      }                  }                    // Apply preHandle methods of registered interceptors.                  HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();                  if (interceptors != null) {                      for (int i = 0; i < interceptors.length; i++) {                          HandlerInterceptor interceptor = interceptors[i];                          if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {                              triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);                              return;                          }                          interceptorIndex = i;                      }                  }                    // Actually invoke the handler.                  mv = ha.handle(processedRequest, response, mappedHandler.getHandler());                    // Do we need view name translation?                  if (mv != null && !mv.hasView()) {                      mv.setViewName(getDefaultViewName(request));                  }                    // Apply postHandle methods of registered interceptors.                  if (interceptors != null) {                      for (int i = interceptors.length - 1; i >= 0; i--) {                          HandlerInterceptor interceptor = interceptors[i];                          interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);                      }                  }              }              catch (ModelAndViewDefiningException ex) {                  logger.debug("ModelAndViewDefiningException encountered", ex);                  mv = ex.getModelAndView();              }              catch (Exception ex) {                  Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);                  mv = processHandlerException(processedRequest, response, handler, ex);                  errorView = (mv != null);              }                // Did the handler return a view to render?              if (mv != null && !mv.wasCleared()) {                  render(mv, processedRequest, response);                  if (errorView) {                      WebUtils.clearErrorRequestAttributes(request);                  }              }              else {                  if (logger.isDebugEnabled()) {                      logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +                              "': assuming HandlerAdapter completed request handling");                  }              }                // Trigger after-completion for successful outcome.              triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);          }            catch (Exception ex) {              // Trigger after-completion for thrown exception.              triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);              throw ex;          }          catch (Error err) {              ServletException ex = new NestedServletException("Handler processing failed", err);              // Trigger after-completion for thrown exception.              triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);              throw ex;          }            finally {              // Clean up any resources used by a multipart request.              if (processedRequest != request) {                  cleanupMultipart(processedRequest);              }          }      }

    代码有点长,但是它封装了springMVC处理请求的整个过程。首先根据请求找到对应的HandlerExecutionChain,它包含了处理请求的handler和所有的HandlerInterceptor拦截器;然后在调用hander之前分别调用每个HandlerInterceptor拦截器的preHandle方法,若有一个拦截器返回false,则会调用triggerAfterCompletion方法,并且立即返回不再往下执行;若所有的拦截器全部返回true并且没有出现异常,则调用handler返回ModelAndView对象;再然后分别调用每个拦截器的postHandle方法;最后,即使是之前的步骤抛出了异常,也会执行triggerAfterCompletion方法。

    1.2 MethodInterceptor拦截器

    MethodInterceptor是AOP项目中的拦截器,它拦截的目标是方法,即使不是controller中的方法。具体使用方式可以参考SpringBoot中利用AOP和拦截器实现自定义注解

    2.二者的区别

    上面的两种拦截器都能起到拦截的效果,但是他们拦截的目标不一样,实现的机制不同,所以有的时候适用不同的场景。

    HandlerInterceptoer拦截的是请求地址,所以针对请求地址做一些验证、预处理等操作比较合适。当你需要统计请求的响应时间时MethodInterceptor将不太容易做到,因为它可能跨越很多方法或者只涉及到已经定义好的方法中一部分代码。MethodInterceptor利用的是AOP的实现机制,在本文中只说明了使用方式,关于原理和机制方面介绍的比较少,因为要说清楚这些需要讲出AOP的相当一部分内容。在对一些普通的方法上的拦截HandlerInterceptoer就无能为力了,这时候只能利用AOP的MethodInterceptor。

     另外,还有一个跟拦截器类似的东西----Filter。Filter是Servlet规范规定的,不属于spring框架,也是用于请求的拦截。但是它适合更粗粒度的拦截,在请求前后做一些编解码处理、日志记录等。而拦截器则可以提供更细粒度的,更加灵活的,针对某些请求、某些方法的组合的解决方案。

    另外的另外,用过人人网的ROSE框架的人都会非常喜欢它的拦截器功能。因为它实现了全注解的方式,只要在类的名字上加上拦截器的注解即表示这是一个拦截器。而使用这个拦截器的方法或者controller也只需在方法或controller的上面加上这个拦截器的注解。其实这是一个关注点的转变,spring的切面控制在配置文件中,配置文件关注哪些地方需要拦截。而在ROSE中,则是在需要拦截的地方关注我要被谁拦截。

    感谢各位的阅读,以上就是“Spring中拦截器的原理与使用方法”的内容了,经过本文的学习后,相信大家对Spring中拦截器的原理与使用方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    Spring中拦截器的原理与使用方法

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    Spring中拦截器的原理与使用方法

    这篇文章主要讲解了“Spring中拦截器的原理与使用方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring中拦截器的原理与使用方法”吧!1.Spring中的拦截器在web开发中,拦截
    2023-07-02

    使用Spring MVC拦截器实现日志记录的方法

    最近在研究Spring MVC拦截器,那么今天也算个学习笔记吧!有需要了解使用Spring MVC拦截器实现日志记录的朋友可参考。希望此文章对各位有所帮助。1. 定义一个类实现HandlerInterceptor,比如: public
    2023-05-31

    详解struts2拦截器的使用方法

    这篇文章给大家介绍详解struts2拦截器的使用方法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。如何使用struts2拦截器,或者自定义拦截器。特别注意,在使用拦截器的时候,在Action里面必须最后一定要引用str
    2023-05-31

    axios拦截器、ElementUI组件的使用方法

    大家都知道ElementUI是"饿了么"公司推出的基于Vue2.0的组件库,这篇文章主要介绍了axios拦截器、ElementUI组件的使用方法,需要的朋友可以参考下
    2023-01-11

    如何正确的使用spring boot拦截器

    如何正确的使用spring boot拦截器?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1.spring boot拦截器默认有:HandlerIntercept
    2023-05-31

    SpringBoot过滤器与拦截器使用方法深入分析

    大家应该都晓得实现过滤器需要实现javax.servlet.Filter接口,而拦截器会在处理指定请求之前和之后进行相关操作,配置拦截器需要两步,本文通过实例代码给大家介绍SpringBoot过滤器和拦截器的相关知识,感兴趣的朋友一起看看吧
    2022-12-27

    Struts2拦截器Interceptor原理与配置的示例分析

    这篇文章将为大家详细讲解有关Struts2拦截器Interceptor原理与配置的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、Struts2拦截器原理:Struts2拦截器的实现原理相对简单
    2023-05-30

    Spring MVC的拦截器与异常处理机制是什么

    这篇文章主要介绍了Spring MVC的拦截器与异常处理机制是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring MVC的拦截器与异常处理机制是什么文章都会有所收获,下面我们一起来看看吧。1. Sp
    2023-06-29

    gRPC中拦截器的使用详解

    gRPC拦截器使用详解gRPC拦截器允许开发者在不修改服务代码的情况下增强gRPC请求和响应处理。它分为客户端和服务端类型,用于执行自定义代码,如日志记录、身份验证或错误处理。通过注册拦截器到gRPC通道,可以插入拦截器来拦截请求和响应,实现高级功能和最佳实践,从而提高应用程序性能和可观测性。
    gRPC中拦截器的使用详解
    2024-04-23

    详解SpringMVC拦截器配置及使用方法

    本文介绍了SpringMVC拦截器配置及使用方法,分享给大家,具体如下:常见应用场景1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。 2、权限检查:如登录检测,进入处理器检测检测是否登录,如果
    2023-05-31

    spring中的拦截器怎么利用注解实现

    本篇文章给大家分享的是有关spring中的拦截器怎么利用注解实现,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。类似用户权限的需求,有些操作需要登录,有些操作不需要,可以使用过滤
    2023-05-31

    Spring的@Configuration使用与原理

    这篇文章主要介绍了Spring的@Configuration使用与原理,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,需要的朋友可以参考下
    2023-05-20

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录