目前实施了一个REST端点,如下所示:
@RequestMapping(path = "/login/user/{username:.+}", method = POST, produces = "application/json; charset=utf-8")
@ResponseStatus(code = HttpStatus.OK)
public User userLogin(@PathVariable("username") String username, @RequestBody Password password) {
//do stuff
return new User(UUID.randomUUID());
}
我目前使用电子邮件地址作为用户名,当我在.au中使用一个结尾时,端点返回406内容不可接受。
我试过四处游戏并将上面的内容改为
@RequestMapping(path = "/login/user/{username:.+}", method = POST, produces = "application/json; charset=utf-8")
@ResponseStatus(code = HttpStatus.OK)
public String userLogin(@PathVariable("username") String username, @RequestBody Password password) {
//do stuff
return "blah";
}
当我访问它时,它会提示我下载.au文件(由Sun microsystems制作的音频格式......),其中包含“blah”。 如果我在方法中随时检查用户名的值,我会收到正确的电子邮件地址,其中包含.au。
我猜测Spring堆栈中的某些内容正在解析.au并试图强制执行不同的媒体类型,所以它现在忽略了 application / json
答案 0 :(得分:2)
我最近遇到了同样的问题并发现了问题。想在这里分享它会有助于其他人。 @Patrick解释的这种行为似乎是由于Spring MVC中基于 URL(URL后缀)的内容协商而发生的。
什么是内容协商?
在某些情况下,我们必须处理控制器返回的相同数据的多个表示(或视图)。确定要返回的数据格式称为内容协商。
内容协商如何运作?
通过HTTP发出请求时,可以通过设置Accept
标头属性来指定您想要的响应类型。但是,浏览器实际上会发送非常令人困惑的Accept
标头,这使得依赖它们变得不切实际。因此,Spring为内容协商提供了一些替代约定。
Spring内容协商替代方案 - 网址后缀和/或网址参数
这些与
Accept
标题的使用一起使用。结果, 可以通过三种方式中的任何一种来请求内容类型。默认情况下他们 按此顺序检查:
在网址中添加路径扩展名(后缀)。因此,如果传入的URL类似于http://myserver/myapp/accounts/list.html,那么HTML 是必须的。对于电子表格,URL应该是 http://myserver/myapp/accounts/list.xls。媒体类型的后缀 映射是通过JavaBeans Activation自动定义的 框架或JAF(所以
activation.jar
必须在类路径上)。这样的网址参数:http://myserver/myapp/accounts/list?format=xls。的名字 参数是默认格式,但可以更改。用一个 默认情况下禁用参数,但启用后,将检查该参数 第二
- 最后检查
Accept
HTTP标头属性。这就是HTTP实际定义的工作方式,但是,如前所述,它可以 使用会有问题。
在问题中解释的上述情况中,您看到的是基于路径扩展的内容协商。 (的 .AU 强>)
来自ContentNegotiationConfigurer的hava文件,
favorPathExtension
public ContentNegotiationConfigurer favorPathExtension(boolean favorPathExtension)
是否应使用URL路径中的路径扩展来确定 请求的媒体类型。
默认情况下,此设置为true,在这种情况下请求/hotels.pdf 将被解释为" application / pdf"不管 接受'报头中。
解决方案 - 将favorPathExtension设置为false
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false).
favorParameter(true).
parameterName("mediaType").
ignoreAcceptHeader(true).
useJaf(false).
defaultContentType(MediaType.APPLICATION_JSON).
mediaType("xml", MediaType.APPLICATION_XML).
mediaType("json", MediaType.APPLICATION_JSON);
}
}
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="true" />
<property name="parameterName" value="mediaType" />
<property name="ignoreAcceptHeader" value="true"/>
<property name="useJaf" value="false"/>
<property name="defaultContentType" value="application/json" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
</bean>
请注意,除了将favorPathExtension设置为false之外,上述配置还有一些其他更改。
有关详细信息,请访问here。
为了完成,我们对此问题的回应如下:
{
"timestamp": 1518691842254,
"status": 406,
"error": "Not Acceptable",
"exception": "org.springframework.web.HttpMediaTypeNotAcceptableException",
"message": "Not Acceptable",
"path": "/rest/token/something.au"
}
答案 1 :(得分:0)
我认为它是由串行器和解串器时的A数据传输对象(DTO)引起的。所以用户应该实现Serializable接口。
答案 2 :(得分:0)
我遇到了类似的问题。我的资源已映射到/ upload / (需要文件路径)。因此资源URI类似于/upload/a/b/c/test1.jpg、upload/xy/test2.xml等,
就像@Rajind提到的那样,它正在考虑将媒体类型作为URL中扩展名(在dot(。)之后)。
HTTP状态406 –不可接受
{
"timestamp": 1538992653298,
"status": 406,
"error": "Not Acceptable",
"message": "Could not find acceptable representation",
"path": "/file-manager-services/api-6.0/234833/upload/Mohan/tst.jpg"
}
我通过添加以下配置来解决它。
@Configuration
@EnableWebMvc
public class **** implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
....
....
}