Spring boot UriComponentsBuilder 中文亂碼 解決

在SpringBoot使用RestTemplate發送請求,並且使用UriComponentsBuilder來組Params時會出現中文亂碼,一開始誤以為是沒有UTF-8,但其實不是

因為在使用UriComponentsBuilder組參數網址的時候會進行編碼,然後在RestTemplate又會再編碼一次

因為重複編碼然後解碼的時候只解一次,所以中文會變成亂碼

解決方式就是告訴他不要再編碼

不要用:

builder.toUriString()

而是:

builder.build(false).toUriString()


下面有使用範例

能夠不出現中文亂碼的程式碼:

private static final java.util.logging.Logger logger = Logger.getLogger(LockController.class.getName());

@GetMapping("/test")
public int test() {

Member req = new Member();
String url = "http://127.0.0.1:5555/test";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("id", req.id)
.queryParam("name", req.name)
.queryParam("description", req.description);

HttpEntity<?> entity = new HttpEntity<>(headers);
//假設回傳的也是Member
HttpEntity<Member> response = restTemplate.exchange(builder.build(false).toUriString(), HttpMethod.PUT, entity, Member.class);//告訴他不要再編碼
Member res = response.getBody();

return HttpServletResponse.SC_OK;
}

class Member {
String id = "id";
String name = "名稱";
String description = "說明";
}

測試過程:

    private static final java.util.logging.Logger logger = Logger.getLogger(Controller.class.getName());

@GetMapping("/test")
public int test() {

Member req = new Member();
String url = "http://127.0.0.1:5555/test";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("id", req.id)
.queryParam("name", req.name)
.queryParam("description", req.description);

//手動組參數測試
url += "?id=" + req.id +
"&name=" + req.name +
"&description=" + req.description;

logger.info("builder.toString(): " + builder.toString());//回傳"org.springframework.web.util.UriComponentsBuilder@4124a5e7" 用都不能用
logger.info("builder.toUriString(): " + builder.toUriString());//重複編碼
logger.info("builder.build(true).toUriString(): " + builder.build(false).toUriString());//告訴他不要編碼
logger.info("url: " + url);//手動組參數

/**log如下:*/
//builder.toString(): org.springframework.web.util.UriComponentsBuilder@78f2cd36
//builder.toUriString(): http://127.0.0.1:5555/test?id=id&name=%E5%90%8D%E7%A8%B1&description=%E8%AA%AA%E6%98%8E
//builder.build(true).toUriString(): http://127.0.0.1:5555/test?id=id&name=名稱&description=說明
//url: http://127.0.0.1:5555/test?id=id&name=名稱&description=說明

HttpEntity<?> entity = new HttpEntity<>(headers);

//假設回傳的也是Member
HttpEntity<Member> response = restTemplate.exchange(builder.build(false).toUriString(), HttpMethod.PUT, entity, Member.class);//告訴他不要再編碼 成功
// HttpEntity<Member> response = restTemplate.exchange(builder.toUriString(), HttpMethod.PUT, entity, Member.class);//預設會自動編碼
// HttpEntity<Member> response = restTemplate.exchange(builder.toString(), HttpMethod.PUT, entity, Member.class);//回傳"org.springframework.web.util.UriComponentsBuilder@4124a5e7" 用都不能用
// HttpEntity<Member> response = restTemplate.exchange(url, HttpMethod.PUT, entity, Member.class);//手動組參數 成功


Member res = response.getBody();

return HttpServletResponse.SC_OK;
}

class Member {
String id = "id";
String name = "名稱";
String description = "說明";
}


留言