在上一节的文章中,我们学习了restTemplate的基础用法。但是在日常的开发中,我们通常需要更加通用的方式来处理http远程调用。
先来回忆一下,发起一个请求需要哪些步骤:
//1、设置访问url
String url = RemoteUrl + "/id";
//2、设置Http的Header
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
//3、设置访问参数
HashMap<String, Object> params = new HashMap<>();
params.put("name", name);
//4、设置访问的Entity
HttpEntity entity = new HttpEntity<>(params, headers);
ResponseEntity<String> result = null;
try {
//5、发起一个POST请求
result = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
JSONObject data = JSONObject.parseObject(result.getBody()).getJSONObject("data");
return data.getString("id");
可以看到,每次发起http请求调用的时候,我们需要准备一系列的参数。如果在生产中,我们这样处理的话,那将会有很多的重复逻辑。
为了能更好的聚焦业务需求开发,我们需要提炼http远程请求的能力,提供统一的基础调用能力。
今天,就给大家带来restTemplate的使用实战进阶,restTemplate对复杂多层嵌套对象的处理和封装。
将分别通过开发中常用的两种序列化工具 fastjson和jackson来分别给交给大家。
定义统一的返回类Result
public class Result<T> {
private String code;
private T data;
private String message;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
引入fastjson的依赖,建议使用1.2.68以上的版本,避免安全漏洞。
>
>com.alibaba >
>fastjson >
>1.2.73 >
>
自定义restTemplate,以post请求为例,提供统一的封装。
@Component
public class MyRestTemplate {
private Logger logger = LoggerFactory.getLogger(MyRestTemplate.class);
private static final String HTTP_STATUS_SUCCESS = "200";
@Autowired
private RestTemplate restTemplate;
public <T> T postForResult(String url, Class<T> cls, Object body, Object... uriVariables) {
ResponseEntity<String> entity = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, getHeaders()), String.class, uriVariables);
return getResultBody(entity, cls);
}
public <T> List<T> postForResultList(String url, Class<T> cls, Object body, Object... uriVariables) {
ResponseEntity<String> entity = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, getHeaders()), String.class, uriVariables);
return getListResultBody(entity, cls);
}
private <T> T getResultBody(ResponseEntity<String> responseEntity, Class<T> cls) {
Result<T> result = JSON.parseObject(responseEntity.getBody(), new TypeReference<Result<T>>(cls) {
}.getType());
checkResultCode(result);
return result.getData();
}
private <T> List<T> getListResultBody(ResponseEntity<String> responseEntity, Class<T> cls) {
Result<List<T>> result = JSON.parseObject(responseEntity.getBody(), new TypeReference<Result<List<T>>>(cls) {
}.getType());
checkResultCode(result);
return result.getData();
}
private HttpHeaders getHeaders() {
return getHeaders(MediaType.APPLICATION_JSON_UTF8, null);
}
/**
* 调用微服务的默认请求头
*
* @return
*/
private HttpHeaders getHeaders(MediaType mediaType, Map<String, String> extHeaders) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(mediaType);
if (!CollectionUtils.isEmpty(extHeaders)) {
for (Map.Entry<String, String> h : extHeaders.entrySet()) {
headers.add(h.getKey(), h.getValue());
}
}
return headers;
}
private <T> void checkResultCode(Result<T> result) {
if (null == result){
throw new RuntimeException("result body is null");
}
if (!isSuccess(result.getCode())) {
logger.error("error, code===>{},message===>, url===>{}",
result.getCode(),
result.getMessage());
throw new RuntimeException(result.getMessage());
}
}
private boolean isSuccess(String code) {
return code.equals(HTTP_STATUS_SUCCESS);
}
}
自定义restTemplate,以post请求为例,提供统一的封装。
@Component
public class MyRestTemplate {
private Logger logger = LoggerFactory.getLogger(MyRestTemplate.class);
private static final String HTTP_STATUS_SUCCESS = "200";
@Autowired
private RestTemplate restTemplate;
public <T> T postForResult(String url, Class<T> cls, Object body, Object... uriVariables) {
ResponseEntity<String> entity = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, getHeaders()), String.class, uriVariables);
return getResultBody(entity, cls);
}
public <T> List<T> postForResultList(String url, Class<T> cls, Object body, Object... uriVariables) {
ResponseEntity<String> entity = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, getHeaders()), String.class, uriVariables);
return getListResultBody(entity, cls);
}
private <T> T getResultBody(ResponseEntity<String> responseEntity, Class<T> cls) {
Result<T> result = JSON.parseObject(responseEntity.getBody(), Map2ObjectUtils.constructType(cls));
checkResultCode(result);
return result.getData();
}
private <T> List<T> getListResultBody(ResponseEntity<String> responseEntity, Class<T> cls) {
Result<List<T>> result = JSON.parseObject(responseEntity.getBody(), Map2ObjectUtils.constructTypeList(cls));
checkResultCode(result);
return result.getData();
}
private HttpHeaders getHeaders() {
return getHeaders(MediaType.APPLICATION_JSON_UTF8, null);
}
/**
* 调用微服务的默认请求头
*
* @return
*/
private HttpHeaders getHeaders(MediaType mediaType, Map<String, String> extHeaders) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(mediaType);
if (!CollectionUtils.isEmpty(extHeaders)) {
for (Map.Entry<String, String> h : extHeaders.entrySet()) {
headers.add(h.getKey(), h.getValue());
}
}
return headers;
}
private <T> void checkResultCode(Result<T> result) {
if (null == result){
throw new RuntimeException("result body is null");
}
if (!isSuccess(result.getCode())) {
logger.error("error, code===>{},message===>, url===>{}",
result.getCode(),
result.getMessage());
throw new RuntimeException(result.getMessage());
}
}
private boolean isSuccess(String code) {
return code.equals(HTTP_STATUS_SUCCESS);
}
}
定义type类型转换类
public class Map2ObjectUtils {
private static ObjectMapper mapper = new ObjectMapper();
static {
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
}
public static <T> Type constructType(Class<T> cls) {
return mapper.getTypeFactory().constructParametricType(
Result.class, cls);
}
public static <T> Type constructTypeList(Class<T> cls) {
return mapper.getTypeFactory().constructParametricType(
Result.class,
mapper.getTypeFactory().constructCollectionType(List.class, cls));
}
}
定义XiaoAMaController,通过RestTemplate远程调用可以直接获取到需要的泛型类型。
@RestController
public class XiaoAMaController {
private static final String HTTP_GET_URL = "http://127.0.0.1:8077/user";
private static final String HTTP_GET_LIST = "http://127.0.0.1:8077/list";
@Autowired
private MyRestTemplate myRestTemplate;
@GetMapping(value = "/get")
public void get() {
CachaUser cachaUser = myRestTemplate.postForResult(HTTP_GET_URL, CachaUser.class, new BusinessPackage() {{
setId("1");
setName("xiaoama");
}});
}
@GetMapping(value = "/list")
public void list() {
List<CachaUser> cachaUsers = myRestTemplate.postForResultList(HTTP_GET_LIST, CachaUser.class, new BusinessPackage() {{
setId("1");
setName("xiaoama");
}});
}
}