Spring @RequestMapping消耗charset?

时间:2012-10-09 10:46:22

标签: spring character-encoding httprequest

我正在尝试将@RequestMappingconsumes - 元素一起使用。阅读API-document它可以在请求的Content-Type - 标题上工作。但是,使用

@RequestMapping(consumes = "application/x-www-form-urlencoded;charset=UTF-8", value = "/test")
public void test() {
  :
}

@RequestMapping(consumes = "application/x-www-form-urlencoded;charset=ISO-8859-1", value = "/test")
public void test() {
  :
}

没有什么区别。请求中的标头可能看起来像

Content-Type: application/x-www-form-urlencoded;charset=UTF-8

Content-Type: application/x-www-form-urlencoded

test()将在所有四个可能的星座中被调用。

但是,这证明Spring看到并尝试使用charset - 部分,如果我指定

@RequestMapping(consumes = "application/x-www-form-urlencoded;charset=UTF-x8", value = "/test")
public void test() {
  :
}

我在网络应用启动(!)期间遇到异常:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Initialization of bean failed;
    nested exception is java.nio.charset.UnsupportedCharsetException: UTF-x8

请注意,produces - 元素上的文档也未提及charset的使用,但根据Google的说法,有人使用它。

这里发生了什么或者我做错了什么的线索?

BTW,这是Spring 3.1.1.RELEASE。

1 个答案:

答案 0 :(得分:12)

我认为您已经回答了您的问题,因此从代码的角度来看,这更像是一个确认,为什么在解析映射时不会考虑charset

在深入研究Spring代码时,罪魁祸首似乎是MediaType#includes()。方法

更多挖掘揭示了与方法的RequestMappingInfo注释相关联地创建了RequestMapping。此RequestMappingInfo存储了一系列AbstractRequestCondition个对象,其中一个是ConsumesRequestCondition,其中包含在注释的consumes部分中定义的MediaType(即{ {1}})。

稍后当发出请求时,此application/x-www-form-urlencoded;charset=UTF-8有一个inner ConsumeMediaTypeExpression class with a matchMediaType() method,可以提取ConsumesRequestCondition的{​​{1}}并根据它自己的MediaType进行检查看看它是否包括在内。

如果查看HttpServletRequest实现(第426行到第428行),则在MediaType(即MediaType#includes())和type(即application时返回true }}是相等的,完全忽略了subtype映射,在这种情况下 持有残余x-www-form-urlencoded组合。

挖掘parameters曲目似乎显示了类似的结果,但在这种情况下,它涉及的是MediaType#isCompatibleWith()方法,而且只会到达"charset","UTF-8"produces如果他们是平等的。

如果您在Google上发现type正在为charset请求映射工作的证据,我会怀疑它(除非他们更改了Spring的核心内容)

至于为什么它是这样设计的,那么这是另一个问题:)