programing

Spring: Response Entity를 사용하여 빈 HTTP 응답을 반환하는 것이 작동하지 않습니다.

javajsp 2023. 10. 6. 20:53

Spring: Response Entity를 사용하여 빈 HTTP 응답을 반환하는 것이 작동하지 않습니다.

우리는 REST API를 Spring(4.1.1.)과 함께 구현하고 있습니다.특정 HTTP 요청의 경우 응답으로 본문이 없는 헤드를 반품하고 싶습니다.하지만 사용하는것은ResponseEntity<Void>효과가 없는 것 같습니다.A와 함께 호출될 때MockMvc테스트하면 406(허용되지 않음)이 반환됩니다.사용.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에 해당합니다.풀어주다.

스프링 MVC 핸들 AResponseEntity수익률을 통한 수익HttpEntityMethodProcessor.

언제.ResponseEntity값에 본문이 설정되어 있지 않습니다. 당신의 토막글의 경우처럼 말이죠.HttpEntityMethodProcessor의 매개 변수화로부터 응답 본문에 대한 내용 유형을 결정하려고 합니다.ResponseEntity의 서명에 있는 반환 형식@RequestMapping핸들러 방식

그래서.

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

그 타입은Void.HttpEntityMethodProcessor그러면 등록된 모든 것을 순환할 것입니다.HttpMessageConverter예를 들어, 하나의 본문을 작성할 수 있는 것을 찾습니다.Voidtype. 구성에 따라 찾을 수도 없고 찾을 수도 없습니다.

발견된 내용이 있으면 해당 본문이 요청 문서에 제공된 유형과 일치하는 내용 유형으로 작성되었는지 확인해야 합니다.Accept머리글,application/xml자네 같은 경우에는

이 모든 점검 후에, 그런 것은 없습니다.HttpMessageConverter존재합니다. Spring MVC는 허용 가능한 응답을 생성할 수 없다고 결정하고 따라서 406 Not Acceptable HTTP 응답을 반환합니다.

와 함께ResponseEntity<String>, 봄은 사용할 것입니다.String대응 기관으로서 그리고 발견으로서.StringHttpMessageConverter조련사로서그 이후로StringHttpMessageHandler모든 미디어 유형에 대한 콘텐츠를 생성할 수 있습니다(에 제공됨).Accept헤더), 그것은 다음을 처리할 수 있을 것입니다.application/xml당신의 고객이 요청하는 것입니다.

스프링 MVC는 그 후 차체가 아래에 있는 경우 406만 리턴하도록 변경되었습니다.ResponseEntity그렇지 않음null. 보다 최신 버전의 Spring MVC를 사용하는 경우에는 원래 질문에서 동작을 볼 수 없습니다.


iddy85의 해결책에서, 제안하는 것처럼 보이는ResponseEntity<?>, 신체에 대한 유형은 다음과 같이 추론될 것입니다.Object. 클래스 경로에 올바른 라이브러리가 있는 경우.Jackson (버전 > 2.5.0)과 그 XML 확장자인 Spring MVC는 다음에 접근할 수 있을 것입니다.MappingJackson2XmlHttpMessageConverter생산에 사용할 수 있는application/xml활자로는Object. 그들의 해결책은 이런 조건에서만 작동합니다.그렇지 않으면 위에서 설명한 것과 같은 이유로 실패합니다.

Spring 4 MVC Response Entity.BodyBuilder 및 Response Entity Enhancements 예는 다음과 같이 쓸 수 있습니다.

....
   return ResponseEntity.ok().build();
....
   return ResponseEntity.noContent().build();

업데이트:

반환된 값이 다음과 같은 경우Optional, 만, 되었습니다 이 있습니다.ok()아니면notFound():

return ResponseEntity.of(optional)

2: 할 수 .OK(200)

public void taxonomyPackageExists(...

에 대한 NO_CONTENT(204)

@ResponseStatus(HttpStatus.NO_CONTENT)
public void taxonomyPackageExists(...

또한 문서를 볼 때 약간 깨끗해 보이는 유형 매개변수와 Spring이 의도한 바를 지정할 수 없습니다.

@RequestMapping(method = RequestMethod.HEAD, value = Constants.KEY )
public ResponseEntity taxonomyPackageExists( @PathVariable final String key ){
    // ...
    return new ResponseEntity(HttpStatus.NO_CONTENT);
}

를 조금 해서 를 . 다음을 시도해보고 코드를 조금 수정해서 사용해보세요.HttpStatus.NO_CONTENT즉 204 대신 HttpStatus.OK

서버가 요청을 이행했지만 개체를 반환할 필요가 없으므로 업데이트된 메타정보를 반환할 수 있습니다.응답에는 개체 헤더의 형태로 새로운 또는 업데이트된 메타 정보가 포함될 수 있으며, 존재하는 경우 요청된 변형과 연관되어야 합니다.

204의 경우 T 값은 무시되지만 404의 경우에는 무시되지 않습니다.

  public ResponseEntity<?> 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<T>(HttpStatus.NO_CONTENT);
            } else {
               LOG.debug( "Taxonomy package with key: {0} does NOT exist.", taxonomyKey ); //$NON-NLS-1$
                return new ResponseEntity<T>( HttpStatus.NOT_FOUND );
            }

    }

Spring 5.2 이상의 경우에는 다음과 같습니다.

@PostMapping("/foo")
ResponseEntity<Void> foo(@PathVariable UUID fooId) {
    return fooService.findExam(fooId)
            .map(uri -> ResponseEntity.noContent().<Void>build())
            .orElse(ResponseEntity.notFound().build());
}

개인적으로 빈 응답을 처리하기 위해 통합 테스트에서 MockMvcResponse 개체를 다음과 같이 사용합니다.

MockMvcResponse response = RestAssuredMockMvc.given()
                .webAppContextSetup(webApplicationContext)
                .when()
                .get("/v1/ticket");

    assertThat(response.mockHttpServletResponse().getStatus()).isEqualTo(HttpStatus.NO_CONTENT.value());

컨트롤러에서 빈 응답을 다음과 같은 특정한 경우에 반환합니다.

return ResponseEntity.noContent().build();

언급URL : https://stackoverflow.com/questions/26550124/spring-returning-empty-http-responses-with-responseentityvoid-doesnt-work