Spring restTemplate是一个很好的http请求代替方案,当你对HttpClient等其他框架厌倦的时候。
其原本的api已经足够许多场景的http调用,但在实际应用中仍然可能会有一些自定义的场景。
例如这样的情况,出于安全性的考虑,我们对http请求进行了加解密的约定。
但是我们在程序的调用中又期望加解密透明,即封装该层加解密,这时我们需要对restTemplate进行自定义。
翻阅Spring restTemplate的源码,我们发现:
RestTemplate类中有如下方法:
public
通过分析exchange方法的实现,我们可以知道,请求头及请求体是由RequestCallback来处理的,请求结果是由ResponseExtractor来处理,这时就很明朗了,我们只需要调用该execute函数,传入我们的RequestCallback和ResponseExtractor即可。这时候发现这两个接口的实现类都是私有的,因此我们需要实现这两个接口,并且做我们想做的事情。
于是解决思路如下:
1.新建UserCenterRequestCallBack类,实现RequestCallback接口
2.新建UserCenterResponseExec类,实现ResponseExtractor接口
3.新建UCRequestTemplate类,继承RestTemplate,写一个我们最终调用的工具方法
4.测试结果
所有代码如下:
1.UserCenterRequestCallBack类
package com.test.util;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.List;
/**
* @Author: Lxx
* @Description:
* @Date: Created in 11:12 2018/6/10
*/
public class UserCenterRequestCallBack implements RequestCallback {
private RestTemplate restTemplate;
private List> messageConverters;
private HttpEntity requestEntity;
public UserCenterRequestCallBack(RestTemplate restTemplate,HttpEntity requestEntity){
this.restTemplate = restTemplate;
this.messageConverters = restTemplate.getMessageConverters();
this.requestEntity = requestEntity;
}
@Override
public void doWithRequest(ClientHttpRequest clientHttpRequest) throws IOException {
if (!requestEntity.hasBody()) {
HttpHeaders httpHeaders = clientHttpRequest.getHeaders();
HttpHeaders requestHeaders = requestEntity.getHeaders();
if (!requestHeaders.isEmpty()) {
httpHeaders.putAll(requestHeaders);
}
if (httpHeaders.getContentLength() < 0L) {
httpHeaders.setContentLength(0L);
}
}else {
Object requestBody = requestEntity.getBody();
Iterator iterator = messageConverters.iterator();
while (iterator.hasNext()) {
Class> requestBodyClass = requestBody.getClass();
Type requestBodyType = requestEntity instanceof RequestEntity ? ((RequestEntity) requestEntity).getType() : requestBodyClass;
HttpHeaders requestHeadersx = requestEntity.getHeaders();
MediaType requestContentType = requestHeadersx.getContentType();
HttpMessageConverter
2.UserCenterResponseExec类:
package com.test.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.HttpMessageConverterExtractor;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.lang.reflect.Type;
/**
* @Author: Lxx
* @Description:
* @Date: Created in 11:12 2018/6/10
*/
public class UserCenterResponseExec implements ResponseExtractor> {
private HttpMessageConverterExtractor delegate;
private String password;
private Class type;
public UserCenterResponseExec(RestTemplate restTemplate){
Type responseType = String.class;
if (responseType != null && Void.class != responseType) {
this.delegate = new HttpMessageConverterExtractor(responseType, restTemplate.getMessageConverters());
} else {
this.delegate = null;
}
}
public UserCenterResponseExec(RestTemplate restTemplate,String key,Class responseType){
this.password = key;
this.type = responseType;
Type rt = String.class;
if (rt != null && Void.class != rt) {
this.delegate = new HttpMessageConverterExtractor(rt, restTemplate.getMessageConverters());
} else {
this.delegate = null;
}
}
@Override
public ResponseEntity extractData(ClientHttpResponse response) throws IOException {
if (this.delegate != null) {
Object body = this.delegate.extractData(response);
if(StringUtils.isNotEmpty(password)){
body = AESCryptUtil.decryptByPassword(password, (String) body);
}
if(type != null && !type.getName().equalsIgnoreCase("java.lang.String")){
body = new ObjectMapper().readValue((String)body, type);
}
return new ResponseEntity(body, response.getHeaders(), response.getStatusCode());
} else {
return new ResponseEntity(response.getHeaders(), response.getStatusCode());
}
}
}
3.UCRequestTemplate类:
package com.test.util;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: Lxx
* @Description:
* @Date: Created in 11:12 2018/6/10
*/
public class UCRequestTemplate extends RestTemplate {
public ResponseEntity execute(String url, String api,HttpMethod method, Map requestParams, Class responseType) throws RestClientException {
String appVersion = "5.0";
String username = "lixiaoxin";
String password = "asdfasdf+SDFASDF/asdfaDsdfasdf==";
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type","application/json");
headers.set("api",api);
headers.set("username",username);
headers.set("app-version",appVersion);
String xContent = requestParams.toString();
String content = AESCryptUtil.encryptByPassword(password, xContent);
JSONObject obj = new JSONObject();
obj.put("ct", content);
HttpEntity> requestEntity = new HttpEntity(obj.toString(),headers);
RequestCallback requestCallback = new UserCenterRequestCallBack(this,requestEntity);
ResponseExtractor responseExtractor = new UserCenterResponseExec(this,password,responseType);
return (ResponseEntity)this.execute(url, method, requestCallback, responseExtractor);
}
public static void main(String [] args){
String url = "http://192.168.111.233/gtwy.do";
String api = "generatorToken";
UCRequestTemplate restTemplate = new UCRequestTemplate();
Map requestParams = new HashMap<>();
requestParams.put("userId","FasdfasdfasdfYALKSDJFASDF");
try {
ResponseEntity response = restTemplate.execute(url, api,HttpMethod.POST,requestParams,String.class);
System.out.println(response.getBody());
}catch (Exception e){
}
}
}
至此,一个附带加解密的http已经封装好了,下次调用只需要new UCRequestTemplate().execute()调用即可。
代码已经经过测试。