Spring thring HttpMediaTypeNotAcceptableException:由于url路径中的点而找不到可接受的表示

最终编辑

因此,在研究了这个之后因为我所看到的答案并没有完全成熟,我发现Spring做了一些奇怪的扩展匹配。 如果我通过byNameOrAtlName/myStringHere.1或者这个byNameOrAtlName/myStringHere.12提交这样的请求,一切都很好,但byNameOrAtlName/myStringHere.123会导致它像byNameOrAtlName/myStringHere.com那样byNameOrAtlName/myStringHere.com ,但是byNameOrAtlName/myStringHere.co ,但byNameOrAtlName/myStringHere.c不是。

总而言之,我不知道逻辑spring用于确定扩展内容,但对于某些扩展, {varName:.+}可以作为一种解决方法,但看起来你需要完全禁用点文件后缀才能真正实现绕过它。


使用Spring 4.1.6

Spring抛出以下exceptionorg.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

我有以下代码,除非字符串(名称)中有句号,否则一切正常。

 @RestController @RequestMapping(value = "/foo/") public class Testing{ @RequestMapping(value = "byNameOrAltName/{name:.+}", method = RequestMethod.GET) @Transactional(readOnly = true) public Collection getByNameOrAltNAme(@PathVariable("name") String name) { return myRepo.getMyDTOsByNameOrAtlName(name); } } 

这样可行。 http://localhost:8080/data/foo/byNameOrAtlName/myStringHere ,但是如果我这样做则会失败http://localhost:8080/data/foo/byNameOrAtlName/myStringHere.fluffy

我阅读了关于这个例外的其他答案,但它们似乎都不适用于我的案例。 起初我认为这是spring不喜欢路径中的时间段的问题,并且我在使用正则表达式之前修复了它.+但我在使用和不使用正则表达式时都尝试了它并且我得到了同样的错误。

关于为什么Spring会抛出这个的任何想法?

编辑

这是我的调试日志:

 21:32:09,118 DEBUG work.orm.jpa.support.OpenEntityManagerInViewFilter: 161 - Opening JPA EntityManager in OpenEntityManagerInViewFilter 21:32:09,118 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/r2d2/**' 21:32:09,118 DEBUG org.springframework.security.web.FilterChainProxy: 324 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 at position 1 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 21:32:09,118 DEBUG y.web.context.HttpSessionSecurityContextRepository: 192 - Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@3eda7134: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@3eda7134: REDACTED 21:32:09,122 DEBUG org.springframework.security.web.FilterChainProxy: 324 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 at position 2 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 21:32:09,122 DEBUG org.springframework.security.web.FilterChainProxy: 324 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter' 21:32:09,122 DEBUG ework.security.web.header.writers.HstsHeaderWriter: 128 - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@518864fd 21:32:09,122 DEBUG org.springframework.security.web.FilterChainProxy: 324 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter' 21:32:09,122 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/logout' 21:32:09,122 DEBUG org.springframework.security.web.FilterChainProxy: 324 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 at position 5 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 21:32:09,122 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 131 - Request 'GET /data/restaurant/supplier/bynameoraltname/quill.com' doesn't match 'POST /login 21:32:09,122 DEBUG org.springframework.security.web.FilterChainProxy: 324 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' 21:32:09,122 DEBUG org.springframework.security.web.FilterChainProxy: 324 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 21:32:09,122 DEBUG org.springframework.security.web.FilterChainProxy: 324 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 21:32:09,122 DEBUG y.web.authentication.AnonymousAuthenticationFilter: 106 - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@3eda7134: REDACTED 21:32:09,123 DEBUG org.springframework.security.web.FilterChainProxy: 324 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter' 21:32:09,123 DEBUG org.springframework.security.web.FilterChainProxy: 324 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 21:32:09,123 DEBUG org.springframework.security.web.FilterChainProxy: 324 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 21:32:09,123 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/login.html' 21:32:09,123 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/index.html' 21:32:09,123 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/*/css/**' 21:32:09,123 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/*/fonts/**' 21:32:09,123 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/*/img/**' 21:32:09,123 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/*/lib/**' 21:32:09,123 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/*/vendor/**' 21:32:09,123 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/sales/**' 21:32:09,123 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/registration/termsofservice.html' 21:32:09,123 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/registration/privacypolicy.html' 21:32:09,123 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/restaurantui/useractivation.html**' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/restaurantui/index.html' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/basicuseractivation/**' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/orderconfirmation/**' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/supplieruseractivation/**' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/restaurantuseractivation/**' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/useractivation/**' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/user/passwordresetrequest' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/user/changepasswordfortoken/**' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/user/checkpasswordtokenvalidity/**' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/signup/**' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/downloads/**' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/unsubscribe.html' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/restaurant/emailsubscriptions/unsubscribe/**' 21:32:09,124 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/adminui/**' 21:32:09,125 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/admin*' 21:32:09,125 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/confirm/**' 21:32:09,125 DEBUG rk.security.web.util.matcher.AntPathRequestMatcher: 151 - Checking match of request : '/data/restaurant/supplier/bynameoraltname/quill.com'; against '/data/**' 21:32:09,125 DEBUG ity.web.access.intercept.FilterSecurityInterceptor: 218 - Secure object: FilterInvocation: URL: /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116; Attributes: [isAuthenticated()] 21:32:09,125 DEBUG ity.web.access.intercept.FilterSecurityInterceptor: 347 - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@3eda7134: REDACTED 21:32:09,126 DEBUG ingframework.security.access.vote.AffirmativeBased: 65 - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@3b97d645, returned: 1 21:32:09,126 DEBUG ity.web.access.intercept.FilterSecurityInterceptor: 242 - Authorization successful 21:32:09,126 DEBUG ity.web.access.intercept.FilterSecurityInterceptor: 255 - RunAsManager did not change Authentication object 21:32:09,126 DEBUG org.springframework.security.web.FilterChainProxy: 309 - /data/restaurant/supplier/byNameOrAltName/quill.com?_=1434072729116 reached end of additional filter chain; proceeding with original chain 21:32:09,126 DEBUG org.springframework.web.servlet.DispatcherServlet: 861 - DispatcherServlet with name 'Spring MVC Servlet' processing GET request for [/data/restaurant/supplier/byNameOrAltName/quill.com] 21:32:09,126 DEBUG mvc.method.annotation.RequestMappingHandlerMapping: 294 - Looking up handler method for path /restaurant/supplier/byNameOrAltName/quill.com 21:32:09,127 DEBUG mvc.method.annotation.RequestMappingHandlerMapping: 299 - Returning handler method [public java.util.Collection com.siftit.webservices.personae.restaurant.RestaurantSupplierWebService.getByNameOrAltNAme(java.lang.String)] 21:32:09,128 DEBUG k.beans.factory.support.DefaultListableBeanFactory: 248 - Returning cached instance of singleton bean 'restaurantSupplierWebService' 21:32:09,128 DEBUG org.springframework.web.servlet.DispatcherServlet: 947 - Last-Modified value for [/data/restaurant/supplier/byNameOrAltName/quill.com] is: -1 21:32:09,128 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 334 - Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1d65b356] for JPA transaction 21:32:09,128 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 367 - Creating new transaction with name [com.siftit.webservices.security.WebServiceInterceptor.preHandle]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; '' 21:32:09,128 DEBUG rg.springframework.jdbc.datasource.DataSourceUtils: 153 - Setting JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@624e4a40] read-only 21:32:09,128 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 403 - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@6d32e04] 21:32:09,128 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 334 - Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1d65b356] for JPA transaction 21:32:09,129 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 472 - Participating in existing transaction 21:32:09,129 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 334 - Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1d65b356] for JPA transaction 21:32:09,129 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 472 - Participating in existing transaction 21:32:09,140 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 755 - Initiating transaction commit 21:32:09,140 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 512 - Committing JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1d65b356] 21:32:09,141 DEBUG rg.springframework.jdbc.datasource.DataSourceUtils: 222 - Resetting read-only flag of JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@624e4a40] 21:32:09,141 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 605 - Not closing pre-bound JPA EntityManager after transaction 21:32:09,142 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 334 - Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1d65b356] for JPA transaction 21:32:09,142 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 367 - Creating new transaction with name [com.siftit.webservices.personae.restaurant.RestaurantSupplierWebService.getByNameOrAltNAme]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; '' 21:32:09,142 DEBUG rg.springframework.jdbc.datasource.DataSourceUtils: 153 - Setting JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@624e4a40] read-only 21:32:09,142 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 403 - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@32689afc] 21:32:09,143 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 334 - Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1d65b356] for JPA transaction 21:32:09,143 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 472 - Participating in existing transaction 21:32:09,143 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 334 - Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1d65b356] for JPA transaction 21:32:09,143 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 472 - Participating in existing transaction 21:32:09,144 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 334 - Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1d65b356] for JPA transaction 21:32:09,144 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 472 - Participating in existing transaction 21:32:09,144 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 334 - Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1d65b356] for JPA transaction 21:32:09,144 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 472 - Participating in existing transaction 21:32:09,146 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 755 - Initiating transaction commit 21:32:09,146 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 512 - Committing JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@1d65b356] 21:32:09,146 DEBUG rg.springframework.jdbc.datasource.DataSourceUtils: 222 - Resetting read-only flag of JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@624e4a40] 21:32:09,147 DEBUG org.springframework.orm.jpa.JpaTransactionManager: 605 - Not closing pre-bound JPA EntityManager after transaction 21:32:09,147 DEBUG ethod.annotation.ExceptionHandlerExceptionResolver: 134 - Resolving exception from handler [public java.util.Collection com.siftit.webservices.personae.restaurant.RestaurantSupplierWebService.getByNameOrAltNAme(java.lang.String)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation 21:32:09,147 DEBUG k.beans.factory.support.DefaultListableBeanFactory: 248 - Returning cached instance of singleton bean 'globalWebServiceExceptionHandler' 21:32:09,147 DEBUG ethod.annotation.ExceptionHandlerExceptionResolver: 360 - Invoking @ExceptionHandler method: public java.lang.Object com.siftit.webservices.GlobalWebServiceExceptionHandler.defaultErrorHandler(javax.servlet.http.HttpServletRequest,java.lang.Exception) throws java.lang.Exception 21:32:09,155 DEBUG thod.annotation.RequestResponseBodyMethodProcessor: 163 - Written [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation] as "application/x-msdownload" using [org.springframework.http.converter.StringHttpMessageConverter@214c8f9d] 21:32:09,155 DEBUG org.springframework.web.servlet.DispatcherServlet:1034 - Null ModelAndView returned to DispatcherServlet with name 'Spring MVC Servlet': assuming HandlerAdapter completed request handling 21:32:09,155 DEBUG org.springframework.web.servlet.DispatcherServlet: 996 - Successfully completed request 21:32:09,155 DEBUG ork.security.web.access.ExceptionTranslationFilter: 116 - Chain processed normally 21:32:09,155 DEBUG urity.web.context.SecurityContextPersistenceFilter: 105 - SecurityContextHolder now cleared, as request processing completed 21:32:09,155 DEBUG work.orm.jpa.support.OpenEntityManagerInViewFilter: 186 - Closing JPA EntityManager in OpenEntityManagerInViewFilter 21:32:09,156 DEBUG .springframework.orm.jpa.EntityManagerFactoryUtils: 432 - Closing JPA EntityManager 

这是我的请求标题:

 Accept:application/json, text/plain, */* Accept-Encoding:gzip, deflate, sdch Accept-Language:en-US,en;q=0.8 Cache-Control:no-cache Connection:keep-alive Cookie:JSESSIONID=BLABLABLABLA; subscriptionType=PREMIUM; userType=ROLE_ADMIN DNT:1 Host:localhost:8080 Pragma:no-cache Referer:http://localhost:8080/restaurantui/ User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36 

Spring将点后面的部分视为文件后缀,以尝试确定您实际需要的响应类型。 这是关于Spring中内容协商的一个体面的写作。

所以会发生什么是Spring试图将结果呈现在一个无法找到转换器的内容类型中。

要解决这个问题,您需要告诉spring关闭基于后缀的内容协商:

 @Configuration public class ContentNegotiationConfig extends WebMvcConfigurerAdapter { @Override void configureContentNegotiation(final ContentNegotiationConfigurer configurer) { // Turn off suffix-based content negotiation configurer.favorPathExtension(false); } } 

更新:

我挖得更深了,我想我可以解释发生了什么。

默认配置会忽略未知的路径后缀,因此为了解释这一点,我们需要知道Spring如何确定路径后缀未知,并归结为PathExtensionContentNegotiationStrategy这段代码:

 @Override protected MediaType handleNoMatch(NativeWebRequest webRequest, String extension) throws HttpMediaTypeNotAcceptableException { if (this.useJaf) { MediaType jafMediaType = JafMediaTypeFactory.getMediaType("file." + extension); if (jafMediaType != null && !MediaType.APPLICATION_OCTET_STREAM.equals(jafMediaType)) { return jafMediaType; } } if (!this.ignoreUnknownExtensions) { throw new HttpMediaTypeNotAcceptableException(getAllMediaTypes()); } return null; } 

所以正在发生的事情可能是Java Activation Framework正在识别你的一些后缀并为它们返回一个媒体类型 – .c扩展可能会返回text / xc,因为它会导致exception。