zoukankan      html  css  js  c++  java
  • SpringMVC源码解读

    consumes  指定处理请求的提交内容类型(media-Type),例如application/json, text/html.

    所以这边的ConsumesRequestCondition就是通过content type进行url过滤的.

    具体分析前,我们先准备下基础知识.

      1. MediaType(org.springframework.http包下,封装n多api)

      2. MediaTypeExpression接口,对MediaType和是否匹配关系(=或!=)的封装

      3. AbstractMediaTypeExpression体系,也就是ConsumeMediaTypeExpression和ProduceMediaTypeExpression.

    // MediaTypeExpression接口

    1 package org.springframework.web.servlet.mvc.condition;
    2 public interface MediaTypeExpression {
    3 
    4     MediaType getMediaType();
    5 
    6     boolean isNegated();
    7 
    8 }

    AbstractMediaTypeExpression构造方法处理是否!后,委托MediaType处理

    // AbstractMediaTypeExpression

     1     AbstractMediaTypeExpression(String expression) {
     2         if (expression.startsWith("!")) {
     3             isNegated = true;
     4             expression = expression.substring(1);
     5         }
     6         else {
     7             isNegated = false;
     8         }
     9         this.mediaType = MediaType.parseMediaType(expression);
    10     }

    看看条件匹配的match

    // AbstractMediaTypeExpression

     1     public final boolean match(HttpServletRequest request) {
     2         try {
     3             boolean match = matchMediaType(request);
     4             return !isNegated ? match : !match;
     5         }
     6         catch (HttpMediaTypeException ex) {
     7             return false;
     8         }
     9     }
    10 
    11     protected abstract boolean matchMediaType(HttpServletRequest request) throws HttpMediaTypeException;

    Consume和Produce的区别终于出来了

     1 static class ConsumeMediaTypeExpression extends AbstractMediaTypeExpression {
     2         @Override
     3         protected boolean matchMediaType(HttpServletRequest request) throws HttpMediaTypeNotSupportedException {
     4             try {
     5                 MediaType contentType = StringUtils.hasLength(request.getContentType()) ?
     6                         MediaType.parseMediaType(request.getContentType()) :
     7                         MediaType.APPLICATION_OCTET_STREAM;
     8                         return getMediaType().includes(contentType);
     9             }
    10             catch (IllegalArgumentException ex) {
    11                 throw new HttpMediaTypeNotSupportedException(
    12                         "Can't parse Content-Type [" + request.getContentType() + "]: " + ex.getMessage());
    13             }
    14         }
    15 }
     1     private final List<ProduceMediaTypeExpression> MEDIA_TYPE_ALL_LIST =
     2             Collections.singletonList(new ProduceMediaTypeExpression("*/*"));
     3 
     4 
     5     /**
     6      * Parses and matches a single media type expression to a request's 'Accept' header.
     7      */
     8     class ProduceMediaTypeExpression extends AbstractMediaTypeExpression {
     9 
    10         @Override
    11         protected boolean matchMediaType(HttpServletRequest request) throws HttpMediaTypeNotAcceptableException {
    12             List<MediaType> acceptedMediaTypes = getAcceptedMediaTypes(request);
    13             for (MediaType acceptedMediaType : acceptedMediaTypes) {
    14                 if (getMediaType().isCompatibleWith(acceptedMediaType)) {
    15                     return true;
    16                 }
    17             }
    18             return false;
    19         }
    20     }

    正文

    combine方法,这边不做合并,直接覆盖

    // ConsumesRequestCondition

    1     /**
    2      * Returns the "other" instance if it has any expressions; returns "this"
    3      * instance otherwise. Practically that means a method-level "consumes"
    4      * overrides a type-level "consumes" condition.
    5      */
    6     public ConsumesRequestCondition combine(ConsumesRequestCondition other) {
    7         return !other.expressions.isEmpty() ? other : this;
    8     }

    getMatchingCondition的规则是存在一个即判定匹配

    // ConsumesRequestCondition

     1     /**
     2      * Checks if any of the contained media type expressions match the given
     3      * request 'Content-Type' header and returns an instance that is guaranteed
     4      * to contain matching expressions only. The match is performed via
     5      * {@link MediaType#includes(MediaType)}.
     6      *
     7      * @param request the current request
     8      *
     9      * @return the same instance if the condition contains no expressions;
    10      *         or a new condition with matching expressions only;
    11      *         or {@code null} if no expressions match.
    12      */
    13     public ConsumesRequestCondition getMatchingCondition(HttpServletRequest request) {
    14         if (isEmpty()) {
    15             return this;
    16         }
    17         Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<ConsumeMediaTypeExpression>(expressions);
    18         for (Iterator<ConsumeMediaTypeExpression> iterator = result.iterator(); iterator.hasNext();) {
    19             ConsumeMediaTypeExpression expression = iterator.next();
    20             if (!expression.match(request)) {
    21                 iterator.remove();
    22             }
    23         }
    24         return (result.isEmpty()) ? null : new ConsumesRequestCondition(result);
    25     }

    compareTo谁有匹配规则谁牛逼,都有的话比较第一个expression

    // ConsumesRequestCondition

     1     public int compareTo(ConsumesRequestCondition other, HttpServletRequest request) {
     2         if (this.expressions.isEmpty() && other.expressions.isEmpty()) {
     3             return 0;
     4         }
     5         else if (this.expressions.isEmpty()) {
     6             return 1;
     7         }
     8         else if (other.expressions.isEmpty()) {
     9             return -1;
    10         }
    11         else {
    12             return this.expressions.get(0).compareTo(other.expressions.get(0));
    13         }
    14     }

    看看初始化吧

     1     /**
     2      * Creates a new instance with "consumes" and "header" expressions.
     3      * "Header" expressions where the header name is not 'Content-Type' or have
     4      * no header value defined are ignored. If 0 expressions are provided in
     5      * total, the condition will match to every request
     6      * @param consumes as described in {@link RequestMapping#consumes()}
     7      * @param headers as described in {@link RequestMapping#headers()}
     8      */
     9     public ConsumesRequestCondition(String[] consumes, String[] headers) {
    10         this(parseExpressions(consumes, headers));
    11     }
    12 
    13     private static Set<ConsumeMediaTypeExpression> parseExpressions(String[] consumes, String[] headers) {
    14         Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<ConsumeMediaTypeExpression>();
    15         if (headers != null) {
    16             for (String header : headers) {
    17                 HeaderExpression expr = new HeaderExpression(header);
    18                 if ("Content-Type".equalsIgnoreCase(expr.name)) {
    19                     for (MediaType mediaType : MediaType.parseMediaTypes(expr.value)) {
    20                         result.add(new ConsumeMediaTypeExpression(mediaType, expr.isNegated));
    21                     }
    22                 }
    23             }
    24         }
    25         if (consumes != null) {
    26             for (String consume : consumes) {
    27                 result.add(new ConsumeMediaTypeExpression(consume));
    28             }
    29         }
    30         return result;
    31     }
  • 相关阅读:
    lr 增强窗格中,如何生成调试信息?
    lr 自带的例子,如何进行关联,通过代码的函数进行实现
    lr11 录制脚本时候,无法自动启动ie,查了网上很多方法都未解决?
    loadrunner11 录制脚步不成功,在录制概要出现“No Events were detected”,浮动窗口总是显示“0 Events”,解决办法
    loadrunner11 安装及破解教程来自百度文库
    安装loadrunner11 ,出现如下错误如何解决?
    回收站数据删除了,如何进行恢复?
    网管工作方面——————打印机删除了然后开机重启他依然存在,如何解决
    Windows 不能在 本地计算机 启动 SQL Server 服务 错误代码126
    Sorry, the page you are looking for is currently unavailable. Please try again later. Nginx
  • 原文地址:https://www.cnblogs.com/leftthen/p/5210427.html
Copyright © 2011-2022 走看看