美文网首页
springMVC(2) 拦截器的实现原理二

springMVC(2) 拦截器的实现原理二

作者: 谷和阿秋 | 来源:发表于2018-01-12 21:10 被阅读0次

今天阅读springMVC HandlerMapping的源码时发现自己还漏掉了一些拦截器的部分。

这次我们直接从配置文件的解析部分入手。

InterceptorsBeanDefinitionParser类

class InterceptorsBeanDefinitionParser implements BeanDefinitionParser {

   @Override
   @Nullable
   public BeanDefinition parse(Element element, ParserContext context) {
      context.pushContainingComponent(
            new CompositeComponentDefinition(element.getTagName(), context.extractSource(element)));

      RuntimeBeanReference pathMatcherRef = null;
      if (element.hasAttribute("path-matcher")) {
         pathMatcherRef = new RuntimeBeanReference(element.getAttribute("path-matcher"));
      }

      List<Element> interceptors = DomUtils.getChildElementsByTagName(element, "bean", "ref", "interceptor");
      for (Element interceptor : interceptors) {
         RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
         mappedInterceptorDef.setSource(context.extractSource(interceptor));
         mappedInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

         ManagedList<String> includePatterns = null;
         ManagedList<String> excludePatterns = null;
         Object interceptorBean;
         if ("interceptor".equals(interceptor.getLocalName())) {
            includePatterns = getIncludePatterns(interceptor, "mapping");
            excludePatterns = getIncludePatterns(interceptor, "exclude-mapping");
            Element beanElem = DomUtils.getChildElementsByTagName(interceptor, "bean", "ref").get(0);
            interceptorBean = context.getDelegate().parsePropertySubElement(beanElem, null);
         }
         else {
            interceptorBean = context.getDelegate().parsePropertySubElement(interceptor, null);
         }
         mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, includePatterns);
         mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, excludePatterns);
         mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(2, interceptorBean);

         if (pathMatcherRef != null) {
            mappedInterceptorDef.getPropertyValues().add("pathMatcher", pathMatcherRef);
         }

         String beanName = context.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
         context.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, beanName));
      }

      context.popAndRegisterContainingComponent();
      return null;
   }

   private ManagedList<String> getIncludePatterns(Element interceptor, String elementName) {
      List<Element> paths = DomUtils.getChildElementsByTagName(interceptor, elementName);
      ManagedList<String> patterns = new ManagedList<>(paths.size());
      for (Element path : paths) {
         patterns.add(path.getAttribute("path"));
      }
      return patterns;
   }

}

这个类的作用很容易理解,就是将配置转化为对应的拦截器类。但是如果注意一下,我们会发现该解析类是将其转化为MappedInterceptor类。那么接下来我们就去阅读一下MappedInterceptor类部分。

MappedInterceptor类

该类中包含如下几个属性

@Nullable
private final String[] includePatterns;

@Nullable
private final String[] excludePatterns;

private final HandlerInterceptor interceptor;

@Nullable
private PathMatcher pathMatcher;

不难看出其中比接口HandlerInterceptor多了includePattern、excludePattern和pathMatcher。这三个属性的意思我们不难猜出来。其中我们需要关注的是includePattern和excludePattern。接下来看该类中的这样一个方法。

public boolean matches(String lookupPath, PathMatcher pathMatcher) {
   PathMatcher pathMatcherToUse = (this.pathMatcher != null) ? this.pathMatcher : pathMatcher;
   if (this.excludePatterns != null) {
      for (String pattern : this.excludePatterns) {
         if (pathMatcherToUse.match(pattern, lookupPath)) {
            return false;
         }
      }
   }
   if (ObjectUtils.isEmpty(this.includePatterns)) {
      return true;
   }
   else {
      for (String pattern : this.includePatterns) {
         if (pathMatcherToUse.match(pattern, lookupPath)) {
            return true;
         }
      }
      return false;
   }
}

仔细阅读该段代码,我们不难读出MappedInterceptor的匹配规则:(我们不妨就当返回true为拦截,返回false为不拦截)

如果路径在excludePatterns中,则不拦截。如果不在,那么若includePatterns为空,则拦截,否则在includePatterns中才拦截。

比较关键的两个地方是:

  • 优先判excludePatterns
  • 若includePatterns列表为空且请求不在excludePatterns的情况下全部拦截,否则只拦截includePatterns中的内容

相关文章

  • 拦截器

    一 拦截器 定义拦截器,实现HandlerInterceptor接口 二 springMVC 拦截器配置 1 针对...

  • springMVC(2) 拦截器的实现原理二

    今天阅读springMVC HandlerMapping的源码时发现自己还漏掉了一些拦截器的部分。 这次我们直接从...

  • SpringMVC拦截器

    SpringMVC拦截器的应用场景: 1.解决乱码问题 2.解决权限验证问题 拦截器的实现 拦截器的实现主要分为3...

  • springmvc 14 拦截器

    自定义拦截器 1. 自定义的拦截器实现HandlerInterceptor接口 2. 在springmvc中配置拦...

  • SpringMVC拦截器

    SpringMVC拦截器 拦截器的定义 自定义的拦截器需要实现一个接口HandlerInterceptor,并实现...

  • springMVC拦截器

    SpringMVC中使用Interceptor拦截器 有两种常用的方法实现SpringMVC拦截器: 1.一种是实...

  • springboot 配置过滤器和拦截器

    1.配置拦截器 创建拦截器类 实现HandlerInterceptor接口 创建springmvc配置类 实现We...

  • 登录拦截器

    用户在访问页面之前,都会先判断其是否登录,可以通过配置拦截器实现。 1、拦截器代码 2、在springMVC中配置...

  • SpringMvc里面拦截器是怎么写的:

    SpringMvc里面拦截器是怎么写的: SpringMvc里面拦截器是怎么写的: 有两种写法,一种是实现Hand...

  • 2019-03-01 拦截器

    1 什么是拦截器 2 拦截器的基本工作原理 3 拦截器的几个基本方法 3.1 实现HandlerIntercept...

网友评论

      本文标题:springMVC(2) 拦截器的实现原理二

      本文链接:https://www.haomeiwen.com/subject/lfkqoxtx.html