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接口

 package org.springframework.web.servlet.mvc.condition;
public interface MediaTypeExpression { MediaType getMediaType(); boolean isNegated(); }

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

// AbstractMediaTypeExpression

     AbstractMediaTypeExpression(String expression) {
if (expression.startsWith("!")) {
isNegated = true;
expression = expression.substring(1);
}
else {
isNegated = false;
}
this.mediaType = MediaType.parseMediaType(expression);
}

看看条件匹配的match

// AbstractMediaTypeExpression

     public final boolean match(HttpServletRequest request) {
try {
boolean match = matchMediaType(request);
return !isNegated ? match : !match;
}
catch (HttpMediaTypeException ex) {
return false;
}
} protected abstract boolean matchMediaType(HttpServletRequest request) throws HttpMediaTypeException;

Consume和Produce的区别终于出来了

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

正文

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

// ConsumesRequestCondition

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

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

// ConsumesRequestCondition

     /**
* Checks if any of the contained media type expressions match the given
* request 'Content-Type' header and returns an instance that is guaranteed
* to contain matching expressions only. The match is performed via
* {@link MediaType#includes(MediaType)}.
*
* @param request the current request
*
* @return the same instance if the condition contains no expressions;
* or a new condition with matching expressions only;
* or {@code null} if no expressions match.
*/
public ConsumesRequestCondition getMatchingCondition(HttpServletRequest request) {
if (isEmpty()) {
return this;
}
Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<ConsumeMediaTypeExpression>(expressions);
for (Iterator<ConsumeMediaTypeExpression> iterator = result.iterator(); iterator.hasNext();) {
ConsumeMediaTypeExpression expression = iterator.next();
if (!expression.match(request)) {
iterator.remove();
}
}
return (result.isEmpty()) ? null : new ConsumesRequestCondition(result);
}

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

// ConsumesRequestCondition

     public int compareTo(ConsumesRequestCondition other, HttpServletRequest request) {
if (this.expressions.isEmpty() && other.expressions.isEmpty()) {
return 0;
}
else if (this.expressions.isEmpty()) {
return 1;
}
else if (other.expressions.isEmpty()) {
return -1;
}
else {
return this.expressions.get(0).compareTo(other.expressions.get(0));
}
}

看看初始化吧

     /**
* Creates a new instance with "consumes" and "header" expressions.
* "Header" expressions where the header name is not 'Content-Type' or have
* no header value defined are ignored. If 0 expressions are provided in
* total, the condition will match to every request
* @param consumes as described in {@link RequestMapping#consumes()}
* @param headers as described in {@link RequestMapping#headers()}
*/
public ConsumesRequestCondition(String[] consumes, String[] headers) {
this(parseExpressions(consumes, headers));
} private static Set<ConsumeMediaTypeExpression> parseExpressions(String[] consumes, String[] headers) {
Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<ConsumeMediaTypeExpression>();
if (headers != null) {
for (String header : headers) {
HeaderExpression expr = new HeaderExpression(header);
if ("Content-Type".equalsIgnoreCase(expr.name)) {
for (MediaType mediaType : MediaType.parseMediaTypes(expr.value)) {
result.add(new ConsumeMediaTypeExpression(mediaType, expr.isNegated));
}
}
}
}
if (consumes != null) {
for (String consume : consumes) {
result.add(new ConsumeMediaTypeExpression(consume));
}
}
return result;
}

SpringMVC源码解读 - RequestMapping注解实现解读 - ConsumesRequestCondition的更多相关文章

  1. SpringMVC源码解读 - RequestMapping注解实现解读 - RequestMappingInfo

    使用@RequestMapping注解时,配置的信息最后都设置到了RequestMappingInfo中. RequestMappingInfo封装了PatternsRequestCondition, ...

  2. SpringMVC源码解读 - RequestMapping注解实现解读 - RequestCondition体系

    一般我们开发时,使用最多的还是@RequestMapping注解方式. @RequestMapping(value = "/", param = "role=guest& ...

  3. SpringMVC源码解读 - RequestMapping注解实现解读

    SpringMVC源码解读 - RequestMapping注解实现解读 - RequestCondition体系  https://www.cnblogs.com/leftthen/p/520840 ...

  4. SpringMVC源码阅读系列汇总

    1.前言 1.1 导入 SpringMVC是基于Servlet和Spring框架设计的Web框架,做JavaWeb的同学应该都知道 本文基于Spring4.3.7源码分析,(不要被图片欺骗了,手动滑稽 ...

  5. SpringMVC源码解读 - HandlerMapping

    SpringMVC在请求到handler处理器的分发这步是通过HandlerMapping模块解决的.handlerMapping 还处理拦截器. 先看看HandlerMapping的继承树吧 可以大 ...

  6. SpringMVC 源码深度解析&lt;context:component-scan&gt;(扫描和注冊的注解Bean)

    我们在SpringMVC开发项目中,有的用注解和XML配置Bean,这两种都各有自己的优势,数据源配置比較经经常使用XML配置.控制层依赖的service比較经经常使用注解等(在部署时比較不会改变的) ...

  7. 7、SpringMVC源码分析(2):分析HandlerAdapter.handle方法,了解handler方法的调用细节以及@ModelAttribute注解

    从上一篇 SpringMVC源码分析(1) 中我们了解到在DispatcherServlet.doDispatch方法中会通过 mv = ha.handle(processedRequest, res ...

  8. SpringMVC源码情操陶冶-AnnotationDrivenBeanDefinitionParser注解解析器

    mvc:annotation-driven节点的解析器,是springmvc的核心解析器 官方注释 Open Declaration org.springframework.web.servlet.c ...

  9. SpringMVC源码剖析5:消息转换器HttpMessageConverter与@ResponseBody注解

    转自 SpringMVC关于json.xml自动转换的原理研究[附带源码分析] 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Spring源码 ...

随机推荐

  1. 十五.jQuery源码解析之Sizzle总体结构.htm

    Sizzle是一款纯javascript实现的css选择器引擎,它具有完全独立,无库依赖;小;易于扩展和兼容性好等特点. W3C Selectors API规范定义了方法querySelector() ...

  2. 【UVALive】3695 Distant Galaxy(......)

    题目 传送门:QWQ 分析 好喵啊~~~~ 不会做 正解看蓝书P53吧 代码 #include <cstdio> #include <algorithm> using name ...

  3. 3d标签云(JS版)

    http://www.miaov.com/miaov_demo/3dLable/miaov_demo.html http://www.lijian.net/p/windstagball/index.h ...

  4. ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(转)

    开发工具:VS2015(2012以上)+SQL2008R2以上数据库 您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB 升级后界面效果如下: 日程管理   http://ww ...

  5. Integer-->String String-->Integer

    参考:http://blog.csdn.net/wangjolly/article/details/18354457 crane: String str="123";int a=0 ...

  6. zabbix agent主动模式与proxy模式,实现公网zabbix监控私网客户机

    zabbix agent主动模式,实现公网zabbix监控私网客户机 zabbix_server端当主机数量过多的时候,由Server端去收集数据,Zabbix会出现严重的性能问题,主要表现如下:  ...

  7. 对Node的优点和缺点提出了自己的看法?

    (优点)因为Node是基于事件驱动和无阻塞的,所以非常适合处理并发请求, 因此构建在Node上的代理服务器相比其他技术实现(如Ruby)的服务器表现要好得多. 此外,与Node代理服务器交互的客户端代 ...

  8. 【转】C#父类与子类的静态成员变量、实例成员变量、构造函数的执行顺序

    原文地址:http://www.xuebuyuan.com/1092603.html Win7+VS2010测试的结果如下: ①子类静态成员变量②子类静态构造函数③子类实例成员变量④父类静态成员变量⑤ ...

  9. Novell云计算

    老牌操作系统NetWare,淡出人们的视野,已记不清是哪一年的事了.不过,它的拥有者-NOVELL公司,却没有像自己曾经红极一时的OS那样被人遗忘.相反,在今天云计算的大潮中,Novell华丽转身,摇 ...

  10. 更改AD域安全策略-密码必须符合复杂性要求

    在域环境中,修改域用户密码时,会提示不符合密码策略, 更改"本地安全策略"是不会对域产生任何的作用的. 上图中可以看,这里按钮都是灰色的! 下面这个步骤教你如何找到"域安 ...