getForEntity 나 getForObject 등을 사용하면 특이하고 HttpStatusCodeException
예외로 받았을 때 한글 깨짐현상이 일어났다.
RestTemplate 자체에서 상태 코드 200
을 못 받은 getForXXX
메소드 자체에서 에러가 던져진다. 그리고 이때 어떤 예외를 던지고, 예외 자체에 API 에 호출에서 받은 결과에 대한 responseBody, Header, StatusCode 등의 데이터를 넣어주는 역할을 하는 클래스가 존재한다. 그게 바로 DefaultErrorHandler 클래스이다.
즉 RestTemplate 은 생성시에 setErrorHandler() 메소드로 직접 등록하지 않으면 기본적으로 DefaultErrorHandler
핸들러를 사용하는 것이다.
중요한 것은 HttpStatusCodeException
예외에 넣을 Body 의 내용에 대한 Charset 을 어떤 것을 사용할지를 결정하는 메소드가 있는데, 그게 바로 DefaultErrorHandler 내부있는 getCharset
메소드다.
이 메소드를 Override
하면 되는 것이다.
아래 처럼하면 해결이 된다.
RestTemplate rest = new RestTemplate();
rest.setErrorHandler(new DefaultErrorHandler() {
@Override
protected Charset getCharset(ClientHttpResponse response) {
return StandardCharsets.UTF_8;
}
});
사실 이외에도 조금 어렵게 가는 방법도 있기는 하다.
restTemplate.getForXXX
, restTemplate.postForXXX
메소드가 아니라
restTemplate.exchange
메소드를 사용하면 직접적으로 요청 Header 를 세팅할 수 있다.
이때 이 Header 에 Charset 을 UTF-8
로 지정하면 되는 것이다.
아래처럼 말이다.
// 헤더 생성
HttpHeaders headers = new HttpHeaders();
// application/json;charset=UTF-8 을 위해 특화되어 있다.
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
// **** Accept 헤더 값에서 Charset이 설정되게 한다!!!!!!!
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));
// 요청 URL 생성
UriComponents build = getDefaultComponentBuilder()
.path(requestApiUri)
.queryParams(queryParam)
.build().encode();
HttpEntity requestEntity = new HttpEntity(headers);
try {
RestTemplate rest = new RestTemplate;
ResponseEntity<JsonNode> response
= rest.exchange(build.toUri(),
method,
requestEntity,
JsonNode.class);
catch (HttpStatusCodeException e) {
ResponseEntity.status(e.getRawStatusCode())
.headers(e.getResponseHeaders())
.body(e.getResponseBodyAsString()); // **** 한글이 안깨진다!
}