RestTemplate使用实战(二)-复杂多层嵌套对象的处理和封装

在上一节的文章中,我们学习了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

引入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);
    }
}

Jackson

自定义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");
        }});
    }

}

你可能感兴趣的:(resttemplate,fastjson,jackson,复杂对象,多次嵌套)