SpringMVC源码解读 - RequestMapping注解实现解读 - ConsumesRequestCondition
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的更多相关文章
- SpringMVC源码解读 - RequestMapping注解实现解读 - RequestMappingInfo
使用@RequestMapping注解时,配置的信息最后都设置到了RequestMappingInfo中. RequestMappingInfo封装了PatternsRequestCondition, ...
- SpringMVC源码解读 - RequestMapping注解实现解读 - RequestCondition体系
一般我们开发时,使用最多的还是@RequestMapping注解方式. @RequestMapping(value = "/", param = "role=guest& ...
- SpringMVC源码解读 - RequestMapping注解实现解读
SpringMVC源码解读 - RequestMapping注解实现解读 - RequestCondition体系 https://www.cnblogs.com/leftthen/p/520840 ...
- SpringMVC源码阅读系列汇总
1.前言 1.1 导入 SpringMVC是基于Servlet和Spring框架设计的Web框架,做JavaWeb的同学应该都知道 本文基于Spring4.3.7源码分析,(不要被图片欺骗了,手动滑稽 ...
- SpringMVC源码解读 - HandlerMapping
SpringMVC在请求到handler处理器的分发这步是通过HandlerMapping模块解决的.handlerMapping 还处理拦截器. 先看看HandlerMapping的继承树吧 可以大 ...
- SpringMVC 源码深度解析<context:component-scan>(扫描和注冊的注解Bean)
我们在SpringMVC开发项目中,有的用注解和XML配置Bean,这两种都各有自己的优势,数据源配置比較经经常使用XML配置.控制层依赖的service比較经经常使用注解等(在部署时比較不会改变的) ...
- 7、SpringMVC源码分析(2):分析HandlerAdapter.handle方法,了解handler方法的调用细节以及@ModelAttribute注解
从上一篇 SpringMVC源码分析(1) 中我们了解到在DispatcherServlet.doDispatch方法中会通过 mv = ha.handle(processedRequest, res ...
- SpringMVC源码情操陶冶-AnnotationDrivenBeanDefinitionParser注解解析器
mvc:annotation-driven节点的解析器,是springmvc的核心解析器 官方注释 Open Declaration org.springframework.web.servlet.c ...
- SpringMVC源码剖析5:消息转换器HttpMessageConverter与@ResponseBody注解
转自 SpringMVC关于json.xml自动转换的原理研究[附带源码分析] 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Spring源码 ...
随机推荐
- 第三章 k8s cluster环境创建
1 用如下方法安装指定版本的docker,但是我的环境会报错 # 安装rpm apt install rpm # 下载 RPM 包, docker 版本 wget https://download. ...
- DynamicConverter
folly/DynamicConverter.h When dynamic objects contain data of a known type, it is sometimes useful t ...
- Julia - 函数返回值
return 返回值 要返回函数最后一个表达式的值,可以省略 return julia> function f(x, y) x + y end f (generic function with ...
- 浅析ECMP等价路由
1.ECMP简介 Equal-CostMultipathRouting,等价多路径.即存在多条到达同一个目的地址的相同开销的路径.当设备支持等价路由时,发往该目的 IP 或者目的网段的三层转发流量就可 ...
- 08_java超市管理系统
超市管理系统功能介绍 * A:超市管理系统功能介绍 * a: 显示主菜单 ============欢迎光临ItCast超市============ 1: 货物 清单 2: 添加货物 3: 删除货物 4 ...
- 04_java之基本语法02
01switch语句解构 * A:switch语句解构 a:switch只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码. b:格式如下: swtich(表达式){ case 常量1 : 要 ...
- TCP报文大小
链路层(二层)MTU最大传输单元:1500KByte.每个以太网帧64bytes-1518bytes,减去帧头(DMAC目的MAC地址48bit=6Bytes+SMAC源MAC地址48bit=6Byt ...
- 使用JAVA爬取去哪儿网入住信息
昨天帮一个商科同学爬取去哪儿网站的所有广州如家快捷酒店的所有入住信息. 就是上面的商务出行 xxx年入住这些东西 然而去哪儿的前端很强,在获取所有如家快捷酒店的时候就遇到了问题. 他显示的酒店列表是j ...
- Qt(自适应窗口)
关于窗口布局: 默认控件的大小为最小尺寸: 如果此时右键设置布局时,窗口大小会自动缩放对应大小,不利于调整. 建议窗口控件设置好最小尺寸,便于窗口布局时,控件不会变形,例如: 改变minimumsiz ...
- kaptcha验证码组件使用简介
Kaptcha是一个基于SimpleCaptcha的验证码开源项目. 官网地址:http://code.google.com/p/kaptcha/ kaptcha的使用比较方便,只需添加jar包依赖之 ...