一个Http客户端
2020-07-09 本文已影响0人
茶还是咖啡
最近间HttpTemplate进行了一些封装,分享给大家
通过建造者模式,一句话完成各种http请求。
不多说,直接上代码
- 这里需要添加gson依赖,用于json处理,
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
- 代码
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.*;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;
import java.time.Duration;
import java.util.*;
@Slf4j
public class RestBuilder {
private static final RestTemplate REST_TEMPLATE;
private HttpHeaders httpHeaders;
private String postBodyStr;
private Map<String, String> restfulPathParamMap;
private Map<String, String> getParamMap;
private Map<String, Object> bodyParam;
private MultiValueMap<String, Object> postParam;
private HttpEntity<?> httpEntity;
private String requestPath;
private static final Gson GSON;
private Duration readTimeOut;
private Duration connectTimeOut;
private Boolean setTimeout = false;
static {
REST_TEMPLATE = new RestTemplate();
GSON = new Gson();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
REST_TEMPLATE.getMessageConverters().add(converter);
}
private RestBuilder() {
}
public static RestBuilder builder() {
return new RestBuilder();
}
/**
* 添加header
*
* @param headerKey key
* @param value value
* @return {@link RestBuilder}
*/
public RestBuilder header(String headerKey, String value) {
Assert.hasText(headerKey, "headerKey must not be null");
if (Objects.isNull(httpHeaders)) {
httpHeaders = new HttpHeaders();
}
httpHeaders.add(headerKey, value);
return this;
}
/**
* 添加多个header
*
* @param headerMap map
* @return {@link RestBuilder}
*/
public RestBuilder headers(MultiValueMap<String, String> headerMap) {
Assert.notEmpty(headerMap, "headerMap must not be null");
if (Objects.isNull(headerMap)) {
headerMap = new HttpHeaders();
}
this.httpHeaders.addAll(headerMap);
return this;
}
/**
* 设置Http ContentType
*
* @param mediaType {@link MediaType}
* @return {@link RestBuilder}
*/
public RestBuilder contentType(MediaType mediaType) {
if (Objects.isNull(httpHeaders)) {
httpHeaders = new HttpHeaders();
}
httpHeaders.setContentType(mediaType);
return this;
}
/**
* 设置GET请求参数,URL拼接形式
*
* @param getParam key
* @param value value
* @return {@link RestBuilder}
*/
public RestBuilder getParam(String getParam, String value) {
Assert.hasText(getParam, "getParam must not be null");
if (Objects.isNull(getParamMap)) {
getParamMap = new HashMap<>();
}
if (Objects.nonNull(value)) {
getParamMap.put(getParam, value);
}
return this;
}
/**
* 批量设置GET请求参数,URL拼接形式
*
* @param getParamMap paramMap
* @return {@link RestBuilder}
*/
public RestBuilder getParams(Map<String, String> getParamMap) {
Assert.notEmpty(getParamMap, "getParamMap must not be null");
if (Objects.isNull(this.getParamMap)) {
this.getParamMap = new HashMap<>();
}
this.getParamMap.putAll(getParamMap);
return this;
}
/**
* 设置post表单
*
* @param param key
* @param value value
* @return {@link RestBuilder}
*/
public RestBuilder formData(String param, Object value) {
Assert.hasText(param, "param must not be null");
if (Objects.isNull(this.postParam)) {
postParam = new LinkedMultiValueMap<>();
}
this.postParam.add(param, value);
return this;
}
/**
* 批量设置表单
*
* @param postParams postParam
* @return {@link RestBuilder}
*/
public RestBuilder formDatas(MultiValueMap<String, Object> postParams) {
Assert.notEmpty(postParams, "PostParams must not be null");
if (Objects.isNull(this.postParam)) {
postParam = new LinkedMultiValueMap<>();
}
postParam = postParams;
return this;
}
/**
* 设置body,传输的字符串,可以是json,xml
*
* @param postBody postBody
* @return {@link RestBuilder}
*/
public RestBuilder postBodyStr(String postBody) {
Assert.notNull(postBody, "postBody must not be null");
this.postBodyStr = postBody;
return this;
}
/**
* 设置body参数,最终会被转换成json
*
* @param key key
* @param value value
* @return {@link RestBuilder}
*/
public RestBuilder postBodyParam(String key, Object value) {
Assert.hasText(key, "post body param must not be null");
if (Objects.isNull(bodyParam)) {
this.bodyParam = new HashMap<>();
}
bodyParam.put(key, value);
return this;
}
/**
* 设置post body最终会被转换成json
*
* @param bodyMap bodyMap
* @return {@link RestBuilder}
*/
public RestBuilder postBodyParams(Map<String, Object> bodyMap) {
Assert.notEmpty(bodyMap, "bodyMap must not be null");
if (Objects.isNull(bodyParam)) {
this.bodyParam = bodyMap;
} else {
this.bodyParam.putAll(bodyMap);
}
return this;
}
/**
* 设置请求body,最终会转换成json
*
* @param postBodyObj {@link Object}
* @return {@link RestBuilder}
*/
public RestBuilder postBodyObj(Object postBodyObj) {
Assert.notNull(postBodyObj, "postBodyObj must not be null");
this.postBodyStr = GSON.toJson(postBodyObj);
return this;
}
/**
* 设置路径参数
*
* @param key key
* @param value value
* @return {@link RestBuilder}
*/
public RestBuilder restFulPathParam(String key, String value) {
Assert.hasText(key, "key must not be null");
if (Objects.isNull(restfulPathParamMap)) {
this.restfulPathParamMap = new HashMap<>();
}
restfulPathParamMap.put(key, value);
return this;
}
/**
* 批量设置路径参数
*
* @param restfulPathParamMap paramMap
* @return {@link RestBuilder}
*/
public RestBuilder restFulPathParams(Map<String, String> restfulPathParamMap) {
Assert.notEmpty(restfulPathParamMap, "restfulPathParamMap must not be null");
if (Objects.isNull(restfulPathParamMap)) {
this.restfulPathParamMap = new HashMap<>();
}
this.restfulPathParamMap.putAll(restfulPathParamMap);
return this;
}
/**
* 发送POST请求,并返回响应信息
*
* @param requestPath 请求路径/url
* @param responseType 响应类型
* @param <R> ResponseType
* @return response
*/
public <R> R postForObj(String requestPath, Class<R> responseType) {
build(requestPath, HttpMethod.POST);
return getRestTemplate().postForObject(this.requestPath, this.httpEntity, responseType);
}
/**
* 发送POST请求并返回{@link ResponseEntity}
*
* @param requestPath 请求路径/url
* @param responseType 响应类型
* @param <R> ResponseType
* @return response
*/
public <R> ResponseEntity<R> postForEntity(String requestPath, Class<R> responseType) {
build(requestPath, HttpMethod.POST);
return getRestTemplate().postForEntity(this.requestPath, this.httpEntity, responseType);
}
/**
* 发送GET请求并返回响应信息
*
* @param requestPath 请求路径/URL
* @param responseType 响应类型
* @param <R> R
* @return R
*/
public <R> R getForObj(String requestPath, Class<R> responseType) {
ResponseEntity<R> responseEntity = getForEntity(requestPath, responseType);
return responseEntity.getBody();
}
/**
* 发送GET请求并反返回{@link ResponseEntity}
*
* @param requestPath 请求路径/URL
* @param responseType 响应类型
* @param <R> R
* @return R
*/
public <R> ResponseEntity<R> getForEntity(String requestPath, Class<R> responseType) {
build(requestPath, HttpMethod.GET);
// 构造execute()执行所需要的参数。
RequestCallback requestCallback = REST_TEMPLATE.httpEntityCallback(this.httpEntity, responseType);
ResponseExtractor<ResponseEntity<R>> entityResponseExtractor = REST_TEMPLATE.responseEntityExtractor(responseType);
// 执行execute(),发送请求
return getRestTemplate().execute(this.requestPath, HttpMethod.GET, requestCallback, entityResponseExtractor);
}
/**
* 获取restTemplate
*
* @return RestTemplate
*/
private RestTemplate getRestTemplate() {
if (!setTimeout) {
return RestBuilder.REST_TEMPLATE;
}
RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();
if (Objects.nonNull(this.readTimeOut)) {
restTemplateBuilder.setReadTimeout(readTimeOut);
}
if (Objects.nonNull(this.connectTimeOut)) {
restTemplateBuilder.setConnectTimeout(connectTimeOut);
}
return restTemplateBuilder.build();
}
/**
* 设置readTimeOut
* [注意]如果设置超时时间会导致每次请求的时候都会创建{@link RestTemplate}
*
* @param readTimeOut readTimeOut
* @return {@link RestBuilder}
*/
public RestBuilder readTimeOut(Duration readTimeOut) {
this.setTimeout = true;
this.readTimeOut = readTimeOut;
return this;
}
/**
* 设置ConnectTimeOut
* [注意]如果设置超时时间会导致每次请求的时候都会创建{@link RestTemplate}
*
* @param connectTimeOut connectTimeOut
* @return {@link RestBuilder}
*/
public RestBuilder connectTimeOut(Duration connectTimeOut) {
this.setTimeout = true;
this.connectTimeOut = connectTimeOut;
return this;
}
/**
* 构造restful路径
*
* @param path path
* @return restful path
*/
private String generatePath(String path) {
if (Objects.nonNull(restfulPathParamMap) && !restfulPathParamMap.isEmpty()) {
// 替换restful值
Set<Map.Entry<String, String>> entrySet = restfulPathParamMap.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
path = path.replace(String.format("${%s}", entry.getKey()), entry.getValue());
}
}
if (Objects.nonNull(getParamMap) && !getParamMap.isEmpty()) {
StringBuilder pathBuilder = new StringBuilder(path).append("?");
// 拼接请求值
getParamMap.forEach((k, v) -> pathBuilder.append(k).append("=").append(v).append("&"));
// 最后一个&
int length = pathBuilder.length();
pathBuilder.delete(length - 1, length);
path = pathBuilder.toString();
}
if (log.isDebugEnabled()) {
log.debug("PATH [ {} ]", path);
}
return path;
}
/**
* 构造http的URL和body
*
* @param path 请求路径
* @param httpMethod 请求方法
*/
private void build(String path, HttpMethod httpMethod) {
// 构造请求路径
this.requestPath = generatePath(path);
Object body = null;
if (httpMethod.matches(HttpMethod.POST.name())) {
MediaType contentType = httpHeaders.getContentType();
if (Objects.isNull(contentType)) {
// 不设置content-type默认为ALL,并只从postBodyStr中获取body
httpHeaders.setContentType(MediaType.ALL);
body = postBodyStr;
} else if (MediaType.APPLICATION_JSON.equals(contentType)) {
// 请求方式为json
if (Objects.nonNull(bodyParam) && !bodyParam.isEmpty()) {
// 如果设置map,map为准
body = GSON.toJson(bodyParam);
} else {
body = postBodyStr;
}
} else if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) {
// 请求方式为form-data
body = postParam;
}
}
this.httpEntity = new HttpEntity<>(body, httpHeaders);
if (log.isDebugEnabled()) {
log.debug("requestEntity [ {} ]", httpEntity.toString());
}
}
}