返回空的HTTP响应不起作用

返回空的HTTP响应不起作用

本文介绍了Spring:使用ResponseEntity< Void>返回空的HTTP响应不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We are implementing a REST API with Spring (4.1.1.). For certain HTTP requests, we would like to return a head with no body as a response. However, using ResponseEntity<Void> doesn't seem to work. When called with a MockMvc test, a 406 (Not acceptable) is returned. Using ResponseEntity<String> without a parameter value (new ResponseEntity<String>( HttpStatus.NOT_FOUND )) works fine.

方法:

@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):

Test case (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)


推荐答案

当你返回没有正文的 ResponseEntity 时,Spring使用 ResponseEntity 返回类型声明中提供的type参数来决定身体类型。

When you return a ResponseEntity without a body, Spring uses the type argument provided in the ResponseEntity return type declaration to decide on a body type.

所以

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

该类型将 Void 。 Spring将循环遍历其所有已注册的 HttpMessageConverter 实例,并找到一个可以为 Void 类型编写正文的实例。由于不存在这样的 HttpMessageConverter (对于默认配置),它将决定它不能产生可接受的响应,因此返回406 Not Acceptable HTTP响应。

that type will be Void. Spring will then loop through all its registered HttpMessageConverter instances and find one that can write a body for a Void type. Since no such HttpMessageConverter exists (for a default configuration), it will decide that it cannot produce an acceptable response and therefore return a 406 Not Acceptable HTTP response.

使用 ResponseEntity< String> ,Spring将使用 String 作为响应正文并找到 StringHttpMessageConverter 作为处理程序。由于 StringHttpMessageHandler 可以为任何 Accepted 媒体类型生成内容,因此它将能够处理 application / xml 您的客户请求。

With ResponseEntity<String>, Spring will use String as the response body and find StringHttpMessageConverter as a handler. And since StringHttpMessageHandler can produce content for any Accepted media type, it will be able to handle the application/xml that your client is requesting.

在(目前错误,但似乎建议 ResponseEntity<?> ),正文的类型将被推断为对象。如果类路径中有正确的库,Spring将可以访问XML HttpMessageConverter ,它可用于生成 application / xml 表示类型对象

In iddy85's solution (which is currently wrong, but seems to suggest ResponseEntity<?>), the type for the body will be inferred as Object. If you have the correct libraries in your classpath, Spring will have access to a XML HttpMessageConverter which it can use to produce application/xml for the type Object.

这篇关于Spring:使用ResponseEntity&lt; Void&gt;返回空的HTTP响应不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-26 06:07