RestTemplate PATCH 요청
Person D에 대한 정의는 다음과 같습니다.수신처:
public class PersonDTO
{
private String id
private String firstName;
private String lastName;
private String maritalStatus;
}
다음은 샘플 레코드입니다.
{
"id": 1,
"firstName": "John",
"lastName": "Doe",
"maritalStatus": "married"
}
신원미상자는 이혼하고따라서 다음 URL로 패치 요청을 전송해야 합니다.
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) Warendary Status만 설정하기 때문에 다른 필드는 모두 무효가 됩니다.요청을 출력하면 다음과 같이 표시됩니다.
{
"id": null,
"firstName": "null",
"lastName": "null",
"maritalStatus": "married" // I only need to update this field.
}
즉, 패치를 적용하기 전에 GET을 실행해야 합니까?
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's RestTemplate를 사용하여 Restful 웹 서비스를 사용하기 위한 클라이언트 애플리케이션을 작성한 사용자의 조언에 감사드립니다.
완전성을 위해 백엔드의 restful 웹 서비스에 SpringDataRest를 사용하고 있음을 설명하겠습니다.
SGB
이 문제는 restTemplate 인스턴스에 새로운 HttpRequestFactory를 추가하는 것만으로 해결되었습니다.이것처럼.
RestTemplate restTemplate = new RestTemplate();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setConnectTimeout(TIMEOUT);
requestFactory.setReadTimeout(TIMEOUT);
restTemplate.setRequestFactory(requestFactory);
TestRestTemplate의 경우 추가
@Autowired
private TestRestTemplate restTemplate;
@Before
public void setup() {
restTemplate.getRestTemplate().setRequestFactory(new HttpComponentsClientHttpRequestFactory());
}
PS: 프로젝트에 httpClient 컴포넌트를 추가해야 합니다.
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.4.1</version>
</dependency>
다음과 같은 경우RestTemplate
로부터 구축됩니다.RestTemplateBuilder
커스텀 RestClient 컨스트럭터는 다음과 같이 기술할 수 있습니다.
public PersonRestClient(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.requestFactory(new HttpComponentsClientHttpRequestFactory()).build();
}
또,org.apache.httpcomponents.httpclient
POM에 의존성을 추가해야 합니다.
자바 파일에 아래 코드를 추가하였습니다.그것은 나에게 효과가 있었다.
String url="Your API URL";
RestTemplate restTemplate = new RestTemplate();
HttpClient httpClient = HttpClientBuilder.create().build();
restTemplate.setRequestFactory(new
HttpComponentsClientHttpRequestFactory(httpClient));
HttpHeaders reqHeaders = new HttpHeaders();
reqHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<String>(requestJson, reqHeaders);
ResponseEntity<String> responseEntity=restTemplate.exchange(url, HttpMethod.PATCH,
requestEntity, String.class);
또한 pom.xml 파일에 다음과 같은 종속성을 추가해야 합니다.
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
아래 행을 추가하여 해결한 경우:
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
링크된 리소스가 있는 경우 이를 수행하기 위한 일반적인 방법을 만들었습니다.
public void patch(M theEntity, Integer entityId, String linkName, URI linkUri) {
ObjectMapper objectMapper = getObjectMapperWithHalModule();
ObjectNode linkedNode = (ObjectNode) objectMapper.valueToTree(theEntity);
linkedNode.put(linkName, linkUri.getPath());
HttpEntity<ObjectNode> requestEntity = new HttpEntity<>(linkedNode);
restTemplate.exchange(uri + "/" + entityId, HttpMethod.PATCH, requestEntity, Void.class);
}
private ObjectMapper getObjectMapperWithHalModule() {
if(objectMapperHal == null) {
objectMapperHal = new ObjectMapper();
objectMapperHal.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapperHal.registerModule(new Jackson2HalModule());
}
return objectMapperHal;
}
JAL+json의 완전한 구현에서 이 예제의 구현을 자유롭게 살펴보십시오.
3.1.0보다 오래된 스프링버전이 있는 경우 HttpMethods에는 PATCH 메서드가 없습니다.Apache에서 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
}
또한 payload에 변경해야 할 값만 포함되어 있는지 확인하고 올바른 URL로 요청을 전송해야 합니다(경우에 따라서는 /api/guest/{id}와 같이 끝날 수 있습니다).
검증된 답변 선량이 효과가 있는 경우 이 작업이 작동합니다.
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
HttpClient httpClient = HttpClientBuilder.create().build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
restTemplate.setRequestFactory(requestFactory);
return restTemplate;
}
언급URL : https://stackoverflow.com/questions/29447382/resttemplate-patch-request
'programing' 카테고리의 다른 글
reactJs가 event.persist()가 있는 이벤트에서 상태를 설정할 수 없습니다. (0) | 2023.03.28 |
---|---|
Mongoose findByIdAndUpdate가 올바른 모델을 반환하지 않음 (0) | 2023.03.28 |
Wordpress에서 "An active PHP session was detected" 중요 경고를 받는 중 (0) | 2023.03.28 |
AngularJS 인증, 세션 관리 및 REST API WS 보안 문제 (0) | 2023.03.28 |
리액트 라우터와 익스프레스 루트의 차이점은 무엇입니까?js (0) | 2023.03.28 |