[SPRING] RestTemplate PATCH 요청
SPRINGRestTemplate PATCH 요청
PersonDTO에 대한 다음 정의가 있습니다.
public class PersonDTO
{
private String id
private String firstName;
private String lastName;
private String maritalStatus;
}
다음은 샘플 레코드입니다.
{
"id": 1,
"firstName": "John",
"lastName": "Doe",
"maritalStatus": "married"
}
이제, Doe는 이혼합니다. 따라서 다음 URL로 PATCH 요청을 보내야합니다.
http://localhost:8080/people/1
다음 요청 본문 :
{
"maritalStatus": "divorced"
}
나는 그것을하는 방법을 이해할 수 없다. 여기 내가 지금까지 시도한 것이있다.
// Create Person
PersonDTO person = new PersonDTO();
person.setMaritalStatus("Divorced");
// Create HttpEntity
final HttpEntity<ObjectNode> requestEntity = new HttpEntity<>(person);
// Create URL (for eg: localhost:8080/people/1)
final URI url = buildUri(id);
ResponseEntity<Void> responseEntity = restTemplate.exchange(url, HttpMethod.PATCH, requestEntity, Void.class);
위의 문제점은 다음과 같습니다.
1) MaritalStatus 만 설정하면 다른 필드는 모두 null입니다. 따라서 요청을 인쇄하면 다음과 같이 보입니다.
{
"id": null,
"firstName": "null",
"lastName": "null",
"maritalStatus": "married" // I only need to update this field.
}
그게 패치를하기 전에 내가 얻은 것을 의미합니까?
2) 다음과 같은 스택 추적을 얻고 있습니다 :
08:48:52.717 ERROR c.n.d.t.s.PersonServiceImpl - Unexpected Exception :
org.springframework.web.client.ResourceAccessException: I/O error on PATCH request for "http://localhost:8080/people/1":Invalid HTTP method: PATCH; nested exception is java.net.ProtocolException: Invalid HTTP method: PATCH
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:580) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:545) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:466) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at com.sp.restclientexample..service.PersonServiceImpl.doPatch(PersonServiceImpl.java:75) ~[classes/:na]
at com.sp.restclientexample..service.PatchTitle.itDoPatch(PatchTitle.java:53) [test-classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_20]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_20]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_20]
at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_20]
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) [junit-4.12.jar:4.12]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) [junit-4.12.jar:4.12]
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) [.cp/:na]
Caused by: java.net.ProtocolException: Invalid HTTP method: PATCH
at java.net.HttpURLConnection.setRequestMethod(HttpURLConnection.java:440) ~[na:1.8.0_20]
at sun.net.www.protocol.http.HttpURLConnection.setRequestMethod(HttpURLConnection.java:517) ~[na:1.8.0_20]
at org.springframework.http.client.SimpleClientHttpRequestFactory.prepareConnection(SimpleClientHttpRequestFactory.java:209) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:138) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.java:76) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:565) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
... 33 common frames omitted
Spring의 RestTemplate을 사용하여 안정적인 웹 서비스를 사용하기 위해 클라이언트 애플리케이션을 작성한 사람들의 포인터를 감사하십시오.
완성을 위해 SpringDataRest를 우리의 백엔드 편안한 웹 서비스에 사용한다고 명시하겠습니다.
SGB
해결법
-
==============================
1.restTemplate 인스턴스에 새로운 HttpRequestFactory를 추가하는 것만으로이 문제를 해결했습니다. 이처럼
restTemplate 인스턴스에 새로운 HttpRequestFactory를 추가하는 것만으로이 문제를 해결했습니다. 이처럼
RestTemplate restTemplate = new RestTemplate(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setConnectTimeout(TIMEOUT); requestFactory.setReadTimeout(TIMEOUT); restTemplate.setRequestFactory(requestFactory);
추신 : 프로젝트에 httpClient 구성 요소를 추가해야합니다.
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.4.1</version> </dependency>
-
==============================
2.RestTemplate이 RestTemplateBuilder에서 빌드 된 경우 사용자 정의 RestClient의 생성자는 다음과 같이 작성할 수 있습니다.
RestTemplate이 RestTemplateBuilder에서 빌드 된 경우 사용자 정의 RestClient의 생성자는 다음과 같이 작성할 수 있습니다.
public PersonRestClient(RestTemplateBuilder restTemplateBuilder) { this.restTemplate = restTemplateBuilder.requestFactory(new HttpComponentsClientHttpRequestFactory()).build(); }
또한 org.apache.httpcomponents.httpclient 종속성을 pom에 추가해야합니다.
-
==============================
3.3.1.0 이전의 스프링 버전을 사용하고 있다면 HttpMethods에 PATCH 메소드가 없습니다. 여전히 아파치에서 HttpClient를 사용할 수 있습니다. 여기 내가 어떻게했는지에 대한 짧은 예가있다.
3.1.0 이전의 스프링 버전을 사용하고 있다면 HttpMethods에 PATCH 메소드가 없습니다. 여전히 아파치에서 HttpClient를 사용할 수 있습니다. 여기 내가 어떻게했는지에 대한 짧은 예가있다.
try { //This is just to avoid ssl hostname verification and to trust all, you can use simple Http client also CloseableHttpClient httpClient = HttpClientBuilder.create().setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build()) .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build(); HttpPatch request = new HttpPatch(REST_SERVICE_URL); StringEntity params = new StringEntity(JSON.toJSONString(payload), ContentType.APPLICATION_JSON); request.setEntity(params); request.addHeader(org.apache.http.HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); request.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE); //You can use other authorization method, like user credentials request.addHeader(HttpHeaders.AUTHORIZATION, OAuth2AccessToken.BEARER_TYPE + " " + accessToken); HttpResponse response = httpClient.execute(request); String statusCode = response.getStatusLine().getStatusCode(); } catch (Exception ex) { // handle exception here }
이것에 해당하는 RestTemplate은 다음과 같습니다.
HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.add("Authorization", OAuth2AccessToken.BEARER_TYPE + " " + accessToken); final HttpEntity<String> entity = new HttpEntity<String>(JSON.toJSONString(payload), headers); RestTemplate restTemplate = new RestTemplate(); try { ResponseEntity<String> response = restTemplate.exchange(REST_SERVICE_URL, HttpMethod.PATCH, entity, String.class); String statusCode = response.getStatusCode(); } catch (HttpClientErrorException e) { // handle exception here }
또한 페이로드에 변경해야하는 값만 포함되어 있는지 확인하고 올바른 URL로 요청을 보내고 있는지 확인하십시오. (어떤 경우에는 / api / guest / {id}와 같이 끝나는 경우도 있습니다).
from https://stackoverflow.com/questions/29447382/resttemplate-patch-request by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 프레임 워크가 XML 기반 구성으로 어노테이션 기반 구성을 재정의 할 수 있습니까? (0) | 2019.02.06 |
---|---|
[SPRING] HTTP 상태 405 - 요청 메소드 'POST'가 지원되지 않음 (스프링 MVC) (0) | 2019.02.06 |
[SPRING] @Autowire (required = false)와 같이 @Inject를 JSR 330에서 선택적으로 사용할 수 있습니까? (0) | 2019.02.06 |
[SPRING] Spring Data JPA 저장소 : 조건 적으로 자식 엔티티를 가져 오는 방법 (0) | 2019.02.06 |
[SPRING] Spring JDBC에서 현재 Connection 객체를 얻는 방법 (0) | 2019.02.06 |