gpt4 book ai didi

java - Spring:使用 ResponseEntity 返回空的 HTTP 响应不起作用

转载 作者:IT老高 更新时间:2023-10-28 13:49:02 25 4
gpt4 key购买 nike

我们正在使用 Spring (4.1.1.) 实现 REST API。对于某些 HTTP 请求,我们希望返回一个没有正文的头部作为响应。但是,使用 ResponseEntity<Void>似乎不起作用。当使用 MockMvc 调用时测试,返回 406( Not Acceptable )。使用 ResponseEntity<String>没有参数值( new ResponseEntity<String>( HttpStatus.NOT_FOUND ) )工作正常。

方法:

@RequestMapping( method = RequestMethod.HEAD, value = Constants.KEY )
public ResponseEntity<Void> taxonomyPackageExists( @PathVariable final String key ) {

LOG.debug( "taxonomyPackageExists queried with key: {0}", key ); //$NON-NLS-1$

final TaxonomyKey taxonomyKey = TaxonomyKey.fromString( key );

LOG.debug( "Taxonomy key created: {0}", taxonomyKey ); //$NON-NLS-1$

if ( this.xbrlInstanceValidator.taxonomyPackageExists( taxonomyKey ) ) {

LOG.debug( "Taxonomy package with key: {0} exists.", taxonomyKey ); //$NON-NLS-1$

return new ResponseEntity<Void>( HttpStatus.OK );

} else {

LOG.debug( "Taxonomy package with key: {0} does NOT exist.", taxonomyKey ); //$NON-NLS-1$

return new ResponseEntity<Void>( HttpStatus.NOT_FOUND );
}

}

测试用例(TestNG):

public class TaxonomyQueryControllerTest {

private XbrlInstanceValidator xbrlInstanceValidatorMock;
private TaxonomyQueryController underTest;
private MockMvc mockMvc;

@BeforeMethod
public void setUp() {
this.xbrlInstanceValidatorMock = createMock( XbrlInstanceValidator.class );
this.underTest = new TaxonomyQueryController( this.xbrlInstanceValidatorMock );
this.mockMvc = MockMvcBuilders.standaloneSetup( this.underTest ).build();
}

@Test
public void taxonomyPackageDoesNotExist() throws Exception {
// record
expect( this.xbrlInstanceValidatorMock.taxonomyPackageExists( anyObject( TaxonomyKey.class ) ) ).andStubReturn(
false );

// replay
replay( this.xbrlInstanceValidatorMock );

// do the test
final String taxonomyKey = RestDataFixture.taxonomyKeyString;

this.mockMvc.perform( head( "/taxonomypackages/{key}", taxonomyKey ).accept( //$NON-NLS-1$
MediaType.APPLICATION_XML ) ).andExpect( status().isNotFound() );

}

}

此堆栈跟踪失败:

FAILED: taxonomyPackageDoesNotExist
java.lang.AssertionError: Status expected:<404> but was:<406>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89)
at org.springframework.test.web.servlet.result.StatusResultMatchers$10.match(StatusResultMatchers.java:652)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:153)
at de.zeb.control.application.xbrlstandalonevalidator.restservice.TaxonomyQueryControllerTest.taxonomyPackageDoesNotExist(TaxonomyQueryControllerTest.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)

最佳答案

注意:问题中提到的版本 4.1.1.RELEASE 也是如此。

Spring MVC 处理 ResponseEntity通过HttpEntityMethodProcessor返回值.

ResponseEntity value 没有设置正文,就像您的代码段中的情况一样,HttpEntityMethodProcessor尝试从 ResponseEntity 的参数化中确定响应正文的内容类型@RequestMapping 的签名中的返回类型处理方法。

所以

public ResponseEntity<Void> taxonomyPackageExists( @PathVariable final String key ) {

该类型将是 Void . HttpEntityMethodProcessor然后将遍历所有已注册的 HttpMessageConverter实例并找到一个可以为 Void 编写正文的实例类型。根据您的配置,它可能找到也可能找不到。

如果它确实找到了,它仍然需要确保使用与请求的 Accept 中提供的类型匹配的 Content-Type 写入相应的正文。 header ,application/xml在你的情况下。

如果在所有这些检查之后,没有这样的 HttpMessageConverter存在时,Spring MVC 将决定它不能产生可接受的响应,因此返回 406 Not Acceptable HTTP 响应。

ResponseEntity<String> , Spring 将使用 String作为响应体并找到 StringHttpMessageConverter作为处理程序。自从StringHttpMessageHandler可以为任何媒体类型生成内容(在 Accept header 中提供),它将能够处理 application/xml您的客户要求的。

Spring MVC 已更改为仅在 ResponseEntity 中的主体时返回 406不是 null .如果您使用的是更新版本的 Spring MVC,您将看不到原始问题中的行为。


iddy85's solution ,这似乎暗示了ResponseEntity<?> , 正文的类型将被推断为 Object .如果您的类路径中有正确的库,即。 Jackson(版本 > 2.5.0)及其 XML 扩展 Spring MVC 将有权访问 MappingJackson2XmlHttpMessageConverter它可以用来生产application/xml对于类型 Object . 他们的解决方案只在这些条件下有效。否则,它会因为我上面描述的相同原因而失败。

关于java - Spring:使用 ResponseEntity<Void> 返回空的 HTTP 响应不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26550124/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com