将RestTemplate封装为Util工具类
RestTemplate的封装已经很完善了,基本使用是不用处理的,直接用即可。但是实际使用中不仅仅是调用一下接口而已,可能还有其它的操作,比如最常见的记录请求和响应日志或者一些加密处理,这种随处可能存在的调用用AOP实现不是很友好,将其封装为Util是我认为比较合适的方法。
References:
- https://stackoverflow.com/questions/28024942/how-to-autowire-resttemplate-using-annotations
- https://www.mkyong.com/spring/spring-inject-a-value-into-static-variables/
关于RestTemplate的介绍和基本使用这里就不介绍了,相信看到这篇的都知道。
先看下RestTemplate注册为bean:
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
// Do any additional configuration here
return builder.build();
}
}
然后就是将RestTemplate中常用的方法封装一遍,并添加上记录日志等处理操作。代码框架如下:
/**
* Http工具类
*/
public class HttpUtil {
private static final Logger log = LoggerFactory.getLogger(HttpUtil.class);
private RestTemplate restTemplate;
/**
* 发送POST请求
* @param url 请求url
* @param returnType 返回类型,必须重写toString()方法,否则不能正确记录日志信息
* @return 指定的返回类型
*/
public static final <T> T doPostByJson(String url, Class<T> returnType) {
return doPostByJson(url, null, returnType);
}
/**
* 发送POST请求
* @param url 请求url
* @param data 发送的数据,必须重写toString()方法,否则不能正确记录日志信息
* @param returnType 返回类型,必须重写toString()方法,否则不能正确记录日志信息
* @return 指定的返回类型
*/
public static final <T, E> T doPostByJson(String url, E data, Class<T> returnType) {
return doPost(url, data, MediaType.APPLICATION_JSON_UTF8, returnType);
}
/**
* 发送POST请求
* @param url 请求url
* @param data 发送的数据,必须重写toString()方法,否则不能正确记录日志信息
* @param returnType 返回类型,必须重写toString()方法,否则不能正确记录日志信息
* @return 指定的返回类型
*/
public static final <T> T doPostByFormData(String url, MultiValueMap<String, String> data, Class<T> returnType) {
return doPost(url, data, MediaType.APPLICATION_FORM_URLENCODED, returnType);
}
/**
* 发送GET请求
* @param url 请求url
* @param clazz 返回类型,必须重写toString()方法,否则不能正确记录日志信息
* @return 指定的返回类型
*/
public static final <T> T doGet(String url, Class<T> clazz) {
log.info("GET_REQUEST: {}, {}", url, clazz.getName());
// T result = restTemplate.getForObject(url, clazz);
log.info("GET_RESPONSE: {}", result);
return result;
}
/**
* 发送POST请求
* @param url 请求url
* @param data 发送的数据,必须重写toString()方法,否则不能正确记录日志信息
* @param requestType 请求头类型
* @param returnType 返回类型,必须重写toString()方法,否则不能正确记录日志信息
* @return 指定的返回类型
*/
public static final <T, E> T doPost(String url, E data, MediaType requestType, Class<T> returnType) {
log.info("POST_REQUEST: {}, {}, {}, {}", url, data, requestType, returnType.getName());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(requestType);
HttpEntity<E> entity = new HttpEntity<>(data, headers);
// T result = restTemplate.postForObject(url, entity, returnType);
log.info("POST_RESPONSE: {}", result);
return result;
}
}
这里RestTemplate还没有初始化,我们需要注入之前注册的bean。但是问题来了,这个类是工具类,方法也应该都是static的,相应的,RestTemplate也应该是static的。知道我想说什么了吧,Spring不支持给静态变量注入,如果直接使用这个变量就是NullPointerException。这就比较尴尬了,不过难不住伟大的人民群众,参考mkyong
的方法,为RestTemplate生成getter和setter方法,将Util注册为Component,然后在setter方法上注入即可,需要注意的是,用IDE给static变量生成的getter和setter也是static的,需要手动去除。完整代码如下:
/**
* Http工具类
*/
@Component
public class HttpUtil {
private static final Logger log = LoggerFactory.getLogger(HttpUtil.class);
private static RestTemplate restTemplate;
/**
* 发送POST请求
* @param url 请求url
* @param returnType 返回类型,必须重写toString()方法,否则不能正确记录日志信息
* @return 指定的返回类型
*/
public static final <T> T doPostByJson(String url, Class<T> returnType) {
return doPostByJson(url, null, returnType);
}
/**
* 发送POST请求
* @param url 请求url
* @param data 发送的数据,必须重写toString()方法,否则不能正确记录日志信息
* @param returnType 返回类型,必须重写toString()方法,否则不能正确记录日志信息
* @return 指定的返回类型
*/
public static final <T, E> T doPostByJson(String url, E data, Class<T> returnType) {
return doPost(url, data, MediaType.APPLICATION_JSON_UTF8, returnType);
}
/**
* 发送POST请求
* @param url 请求url
* @param data 发送的数据,必须重写toString()方法,否则不能正确记录日志信息
* @param returnType 返回类型,必须重写toString()方法,否则不能正确记录日志信息
* @return 指定的返回类型
*/
public static final <T> T doPostByFormData(String url, MultiValueMap<String, String> data, Class<T> returnType) {
return doPost(url, data, MediaType.APPLICATION_FORM_URLENCODED, returnType);
}
/**
* 发送GET请求
* @param url 请求url
* @param clazz 返回类型,必须重写toString()方法,否则不能正确记录日志信息
* @return 指定的返回类型
*/
public static final <T> T doGet(String url, Class<T> clazz) {
log.info("GET_REQUEST: {}, {}", url, clazz.getName());
T result = restTemplate.getForObject(url, clazz);
log.info("GET_RESPONSE: {}", result);
return result;
}
/**
* 发送POST请求
* @param url 请求url
* @param data 发送的数据,必须重写toString()方法,否则不能正确记录日志信息
* @param requestType 请求头类型
* @param returnType 返回类型,必须重写toString()方法,否则不能正确记录日志信息
* @return 指定的返回类型
*/
public static final <T, E> T doPost(String url, E data, MediaType requestType, Class<T> returnType) {
log.info("POST_REQUEST: {}, {}, {}, {}", url, data, requestType, returnType.getName());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(requestType);
HttpEntity<E> entity = new HttpEntity<>(data, headers);
T result = restTemplate.postForObject(url, entity, returnType);
log.info("POST_RESPONSE: {}", result);
return result;
}
public RestTemplate getRestTemplate() {
return restTemplate;
}
@Autowired
public void setRestTemplate(RestTemplate restTemplate) {
HttpUtil.restTemplate = restTemplate;
}
}
这样就可以通过Util使用RestTemplate了。
我都注册成组件了还能静态调用吗,构造器注入使用不行吗