Spring Boot: HttpMediaTypeNotAcceptableException: Could not find acceptable representation原因及解决方法

来源:互联网 发布:网络电视剧收视率排行 编辑:程序博客网 时间:2024/06/10 04:16

错误场景

使用Spring Boot的Web项目,在其 resources/static/目录下存在login.html静态文件,同时还有一个处理/login请求的控制器方法(该方法会返回JSON格式的数据)。此时如果访问localhost:8080/login.html,用户期望返回login.html页面,但框架却报错:

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation    at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:235) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:382) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:322) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:60) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]    at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:351) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]

错误原因

Spring Boot的MVC默认配置中使用的 ViewResolver 为 ContentNegotiatingViewResolver,该视图解析器的功能是根据要请求的文档类型,来查找不同的视图以返回对应格式的文档。请求的文档类型要可以从请求头中的Accept中获取,也可以通过URI后缀名得到,如/login.html即为请求HTML格式的文档,这两种方式分别对应着两种不同的Strategy(策略),默认为根据URI后缀名。Spring Framework Reference 17.5 节 ContentNegotiatingViewResolver中有说明:

The ContentNegotiatingViewResolver does not resolve views itself but rather delegates to other view resolvers, selecting the view that resembles the representation requested by the client. Two strategies exist for a client to request a representation from the server:
• Use a distinct URI for each resource, typically by using a different file extension in the URI. For example, the URI http://www.example.com/users/fred.pdf requests a PDF representation of the user fred, and http://www.example.com/users/fred.xml requests an XML representation.
• Use the same URI for the client to locate the resource, but set the Accept HTTP request header to list the media types that it understands. For example, an HTTP request for http:// www.example.com/users/fred with an Accept header set to application/pdf requests a PDF representation of the user fred, while http://www.example.com/users/fred with an Accept header set to text/xml requests an XML representation. This strategy is known as content negotiation.

因此,当用户请求 /login.html 时,spring会查找/login对应的控制器,并得到其返回的文档类型为application/json, 然后判断它与后缀名.html文档类型是否匹配,如果不匹配,就报HttpMediaTypeNotAcceptableException了。
其实它的初衷是好的,它是想实现访问/user.json时返回JSON数据,访问/user.html返回HTML, 访问/user.xml则返回XML的功能。但是在这里我们只用Spring Boot提供RESTful接口,因此该功能就无用武之地了。

解决方案

  • 防止静态文件名跟控制器请求路由冲突。如本例中,将login.html更名为signin.html
  • 将静态文件URI与动态请求URI分离。如,把提供REST接口的URI都改成以/api/XXX开头,把静态文件改为以/static/XXX开头。这样当请求/static/login.html时,spring会直接使用内置的处理静态资源的控制器返回静态文件而不再去查找用户定义的控制器、
0 0
原创粉丝点击