一、Nacos下Http请求设计众多处理模块处理,包括更新、Prometheus监控等众多功能,Nacos对这块做了统一封装,扩展性也很好,有新旧版本和同步和异步版本.
二、具体封装模块.
1、引入依赖如下.
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>0.2.12</version>
</dependency>
2、旧Http模块.
HttpAgent.
package com.alibaba.nacos.client.config.http;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.lifecycle.Closeable;
import java.util.Map;
/**
* HttpAgent.
*
* @author Nacos
*/
public interface HttpAgent extends Closeable {
/**
* start to get nacos ip list.
*
* @throws NacosException on get ip list error.
*/
void start() throws NacosException;
/**
* invoke http get method.
*
* @param path http path
* @param headers http headers
* @param paramValues http paramValues http
* @param encoding http encode
* @param readTimeoutMs http timeout
* @return HttpResult http response
* @throws Exception If an input or output exception occurred
*/
HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
String encoding, long readTimeoutMs) throws Exception;
/**
* invoke http post method.
*
* @param path http path
* @param headers http headers
* @param paramValues http paramValues http
* @param encoding http encode
* @param readTimeoutMs http timeout
* @return HttpResult http response
* @throws Exception If an input or output exception occurred
*/
HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
String encoding, long readTimeoutMs) throws Exception;
ServerHttpAgent.[Server服务内部调用,后续版本要下线,比较重量级,不够灵活]
package com.alibaba.nacos.client.config.http;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.impl.ConfigHttpClientManager;
import com.alibaba.nacos.client.config.impl.ServerListManager;
import com.alibaba.nacos.client.utils.ContextPathUtil;
import com.alibaba.nacos.client.utils.LogUtils;
import com.alibaba.nacos.client.utils.ParamUtil;
import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import org.slf4j.Logger;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.util.Map;
import java.util.Properties;
/**
* Server Agent.
*
* @author water.lyl
*/
public class ServerHttpAgent implements HttpAgent {
private static final Logger LOGGER = LogUtils.logger(ServerHttpAgent.class);
private static final NacosRestTemplate NACOS_RESTTEMPLATE = ConfigHttpClientManager.getInstance()
.getNacosRestTemplate();
private String encode;
private int maxRetry = 3;
final ServerListManager serverListMgr;
@Override
public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
final long endTime = System.currentTimeMillis() + readTimeoutMs;
String currentServerAddr = serverListMgr.getCurrentServerAddr();
int maxRetry = this.maxRetry;
HttpClientConfig httpConfig = HttpClientConfig.builder()
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(100)).build();
do {
try {
Header newHeaders = Header.newInstance();
if (headers != null) {
newHeaders.addAll(headers);
}
Query query = Query.newInstance().initParams(paramValues);
HttpRestResult<String> result = NACOS_RESTTEMPLATE
.get(getUrl(currentServerAddr, path), httpConfig, newHeaders, query, String.class);
if (isFail(result)) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
serverListMgr.getCurrentServerAddr(), result.getCode());
} else {
// Update the currently available server addr
serverListMgr.updateCurrentServerAddr(currentServerAddr);
return result;
}
} catch (ConnectException connectException) {
LOGGER.error("[NACOS ConnectException httpGet] currentServerAddr:{}, err : {}",
serverListMgr.getCurrentServerAddr(), connectException.getMessage());
} catch (SocketTimeoutException socketTimeoutException) {
LOGGER.error("[NACOS SocketTimeoutException httpGet] currentServerAddr:{}, err : {}",
serverListMgr.getCurrentServerAddr(), socketTimeoutException.getMessage());
} catch (Exception ex) {
LOGGER.error("[NACOS Exception httpGet] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
ex);
throw ex;
}
if (serverListMgr.getIterator().hasNext()) {
currentServerAddr = serverListMgr.getIterator().next();
} else {
maxRetry--;
if (maxRetry < 0) {
throw new ConnectException(
"[NACOS HTTP-GET] The maximum number of tolerable server reconnection errors has been reached");
}
serverListMgr.refreshCurrentServerAddr();
}
} while (System.currentTimeMillis() <= endTime);
LOGGER.error("no available server");
throw new ConnectException("no available server");
}
@Override
public HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
final long endTime = System.currentTimeMillis() + readTimeoutMs;
String currentServerAddr = serverListMgr.getCurrentServerAddr();
int maxRetry = this.maxRetry;
HttpClientConfig httpConfig = HttpClientConfig.builder()
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(3000)).build();
do {
try {
Header newHeaders = Header.newInstance();
if (headers != null) {
newHeaders.addAll(headers);
}
HttpRestResult<String> result = NACOS_RESTTEMPLATE
.postForm(getUrl(currentServerAddr, path), httpConfig, newHeaders, paramValues, String.class);
if (isFail(result)) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", currentServerAddr,
result.getCode());
} else {
// Update the currently available server addr
serverListMgr.updateCurrentServerAddr(currentServerAddr);
return result;
}
} catch (ConnectException connectException) {
LOGGER.error("[NACOS ConnectException httpPost] currentServerAddr: {}, err : {}", currentServerAddr,
connectException.getMessage());
} catch (SocketTimeoutException socketTimeoutException) {
LOGGER.error("[NACOS SocketTimeoutException httpPost] currentServerAddr: {}, err : {}",
currentServerAddr, socketTimeoutException.getMessage());
} catch (Exception ex) {
LOGGER.error("[NACOS Exception httpPost] currentServerAddr: " + currentServerAddr, ex);
throw ex;
}
if (serverListMgr.getIterator().hasNext()) {
currentServerAddr = serverListMgr.getIterator().next();
} else {
maxRetry--;
if (maxRetry < 0) {
throw new ConnectException(
"[NACOS HTTP-POST] The maximum number of tolerable server reconnection errors has been reached");
}
serverListMgr.refreshCurrentServerAddr();
}
} while (System.currentTimeMillis() <= endTime);
LOGGER.error("no available server, currentServerAddr : {}", currentServerAddr);
throw new ConnectException("no available server, currentServerAddr : " + currentServerAddr);
}
@Override
public HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,
String encode, long readTimeoutMs) throws Exception {
final long endTime = System.currentTimeMillis() + readTimeoutMs;
String currentServerAddr = serverListMgr.getCurrentServerAddr();
int maxRetry = this.maxRetry;
HttpClientConfig httpConfig = HttpClientConfig.builder()
.setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())
.setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(100)).build();
do {
try {
Header newHeaders = Header.newInstance();
if (headers != null) {
newHeaders.addAll(headers);
}
Query query = Query.newInstance().initParams(paramValues);
HttpRestResult<String> result = NACOS_RESTTEMPLATE
.delete(getUrl(currentServerAddr, path), httpConfig, newHeaders, query, String.class);
if (isFail(result)) {
LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}",
serverListMgr.getCurrentServerAddr(), result.getCode());
} else {
// Update the currently available server addr
serverListMgr.updateCurrentServerAddr(currentServerAddr);
return result;
}
} catch (ConnectException connectException) {
LOGGER.error("[NACOS ConnectException httpDelete] currentServerAddr:{}, err : {}",
serverListMgr.getCurrentServerAddr(), ExceptionUtil.getStackTrace(connectException));
} catch (SocketTimeoutException stoe) {
LOGGER.error("[NACOS SocketTimeoutException httpDelete] currentServerAddr:{}, err : {}",
serverListMgr.getCurrentServerAddr(), ExceptionUtil.getStackTrace(stoe));
} catch (Exception ex) {
LOGGER.error("[NACOS Exception httpDelete] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),
ex);
throw ex;
}
if (serverListMgr.getIterator().hasNext()) {
currentServerAddr = serverListMgr.getIterator().next();
} else {
maxRetry--;
if (maxRetry < 0) {
throw new ConnectException(
"[NACOS HTTP-DELETE] The maximum number of tolerable server reconnection errors has been reached");
}
serverListMgr.refreshCurrentServerAddr();
}
} while (System.currentTimeMillis() <= endTime);
LOGGER.error("no available server");
throw new ConnectException("no available server");
}
private String getUrl(String serverAddr, String relativePath) {
return serverAddr + ContextPathUtil.normalizeContextPath(serverListMgr.getContentPath()) + relativePath;
}
private boolean isFail(HttpRestResult<String> result) {
return result.getCode() == HttpURLConnection.HTTP_INTERNAL_ERROR
|| result.getCode() == HttpURLConnection.HTTP_BAD_GATEWAY
|| result.getCode() == HttpURLConnection.HTTP_UNAVAILABLE;
}
public static String getAppname() {
return ParamUtil.getAppName();
}
public ServerHttpAgent(ServerListManager mgr) {
this.serverListMgr = mgr;
}
public ServerHttpAgent(ServerListManager mgr, Properties properties) {
this.serverListMgr = mgr;
}
public ServerHttpAgent(Properties properties) throws NacosException {
this.serverListMgr = new ServerListManager(properties);
}
@Override
public void start() throws NacosException {
serverListMgr.start();
}
@Override
public String getName() {
return serverListMgr.getName();
}
@Override
public String getNamespace() {
return serverListMgr.getNamespace();
}
@Override
public String getTenant() {
return serverListMgr.getTenant();
}
@Override
public String getEncode() {
return encode;
}
@Override
public void shutdown() throws NacosException {
String className = this.getClass().getName();
LOGGER.info("{} do shutdown begin", className);
ConfigHttpClientManager.getInstance().shutdown();
LOGGER.info("{} do shutdown stop", className);
}
}
RestResult响应.
package com.alibaba.nacos.common.model;
import java.io.Serializable;
/**
* Rest result.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public class RestResult<T> implements Serializable {
private static final long serialVersionUID = 6095433538316185017L;
private int code;
private String message;
private T data;
public RestResult() {
}
public RestResult(int code, String message, T data) {
this.code = code;
this.setMessage(message);
this.data = data;
}
public RestResult(int code, T data) {
this.code = code;
this.data = data;
}
public RestResult(int code, String message) {
this.code = code;
this.setMessage(message);
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public boolean ok() {
return this.code == 0 || this.code == 200;
}
@Override
public String toString() {
return "RestResult{" + "code=" + code + ", message='" + message + '\'' + ", data=" + data + '}';
}
public static <T> ResResultBuilder<T> builder() {
return new ResResultBuilder<T>();
}
public static final class ResResultBuilder<T> {
private int code;
private String errMsg;
private T data;
private ResResultBuilder() {
}
public ResResultBuilder<T> withCode(int code) {
this.code = code;
return this;
}
public ResResultBuilder<T> withMsg(String errMsg) {
this.errMsg = errMsg;
return this;
}
public ResResultBuilder<T> withData(T data) {
this.data = data;
return this;
}
/**
* Build result.
*
* @return result
*/
public RestResult<T> build() {
RestResult<T> restResult = new RestResult<T>();
restResult.setCode(code);
restResult.setMessage(errMsg);
restResult.setData(data);
return restResult;
}
}
}
HttpRestResult.
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.model.RestResult;
/**
* Http RestResult.
*
* @author mai.jh
*/
public class HttpRestResult<T> extends RestResult<T> {
private static final long serialVersionUID = 3766947816720175947L;
private Header header;
public HttpRestResult() {
}
public HttpRestResult(Header header, int code, T data, String message) {
super(code, message, data);
this.header = header;
}
public Header getHeader() {
return header;
}
public void setHeader(Header header) {
this.header = header;
}
}
RestResultUtils
package com.alibaba.nacos.common.model;
import com.alibaba.nacos.common.model.core.IResultCode;
/**
* Rest result utils.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public class RestResultUtils {
public static <T> RestResult<T> success() {
return RestResult.<T>builder().withCode(200).build();
}
public static <T> RestResult<T> success(T data) {
return RestResult.<T>builder().withCode(200).withData(data).build();
}
public static <T> RestResult<T> success(String msg, T data) {
return RestResult.<T>builder().withCode(200).withMsg(msg).withData(data).build();
}
public static <T> RestResult<T> success(int code, T data) {
return RestResult.<T>builder().withCode(code).withData(data).build();
}
public static <T> RestResult<T> failed() {
return RestResult.<T>builder().withCode(500).build();
}
public static <T> RestResult<T> failed(String errMsg) {
return RestResult.<T>builder().withCode(500).withMsg(errMsg).build();
}
public static <T> RestResult<T> failed(int code, T data) {
return RestResult.<T>builder().withCode(code).withData(data).build();
}
public static <T> RestResult<T> failed(int code, T data, String errMsg) {
return RestResult.<T>builder().withCode(code).withData(data).withMsg(errMsg).build();
}
public static <T> RestResult<T> failedWithMsg(int code, String errMsg) {
return RestResult.<T>builder().withCode(code).withMsg(errMsg).build();
}
public static <T> RestResult<T> buildResult(IResultCode resultCode, T data) {
return RestResult.<T>builder().withCode(resultCode.getCode()).withMsg(resultCode.getCodeMsg()).withData(data).build();
}
}
MediaType
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.param;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.common.utils.StringUtils;
/**
* Http Media type.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public final class MediaType {
public static final String APPLICATION_ATOM_XML = "application/atom+xml";
public static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded;charset=UTF-8";
public static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
public static final String APPLICATION_SVG_XML = "application/svg+xml";
public static final String APPLICATION_XHTML_XML = "application/xhtml+xml";
public static final String APPLICATION_XML = "application/xml;charset=UTF-8";
public static final String APPLICATION_JSON = "application/json;charset=UTF-8";
public static final String MULTIPART_FORM_DATA = "multipart/form-data;charset=UTF-8";
public static final String TEXT_HTML = "text/html;charset=UTF-8";
public static final String TEXT_PLAIN = "text/plain;charset=UTF-8";
private MediaType(String type, String charset) {
this.type = type;
this.charset = charset;
}
/**
* content type.
*/
private final String type;
/**
* content type charset.
*/
private final String charset;
/**
* Parse the given String contentType into a {@code MediaType} object.
*
* @param contentType mediaType
* @return MediaType
*/
public static MediaType valueOf(String contentType) {
if (StringUtils.isEmpty(contentType)) {
throw new IllegalArgumentException("MediaType must not be empty");
}
String[] values = contentType.split(";");
String charset = Constants.ENCODE;
for (String value : values) {
if (value.startsWith("charset=")) {
charset = value.substring("charset=".length());
}
}
return new MediaType(values[0], charset);
}
/**
* Use the given contentType and charset to assemble into a {@code MediaType} object.
*
* @param contentType contentType
* @param charset charset
* @return MediaType
*/
public static MediaType valueOf(String contentType, String charset) {
if (StringUtils.isEmpty(contentType)) {
throw new IllegalArgumentException("MediaType must not be empty");
}
String[] values = contentType.split(";");
return new MediaType(values[0], StringUtils.isEmpty(charset) ? Constants.ENCODE : charset);
}
public String getType() {
return type;
}
public String getCharset() {
return charset;
}
@Override
public String toString() {
return type + ";charset=" + charset;
}
}
Header
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.param;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.utils.MapUtil;
import com.alibaba.nacos.common.utils.StringUtils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
* Http header.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public class Header {
public static final Header EMPTY = Header.newInstance();
private final Map<String, String> header;
private final Map<String, List<String>> originalResponseHeader;
private static final String DEFAULT_CHARSET = "UTF-8";
private static final String DEFAULT_ENCODING = "gzip";
private Header() {
header = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
originalResponseHeader = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER);
addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);
addParam(HttpHeaderConsts.ACCEPT_CHARSET, DEFAULT_CHARSET);
//addParam(HttpHeaderConsts.ACCEPT_ENCODING, DEFAULT_ENCODING);
}
public static Header newInstance() {
return new Header();
}
/**
* Add the key and value to the header.
*
* @param key the key
* @param value the value
* @return header
*/
public Header addParam(String key, String value) {
if (StringUtils.isNotEmpty(key)) {
header.put(key, value);
}
return this;
}
public Header setContentType(String contentType) {
if (contentType == null) {
contentType = MediaType.APPLICATION_JSON;
}
return addParam(HttpHeaderConsts.CONTENT_TYPE, contentType);
}
public Header build() {
return this;
}
public String getValue(String key) {
return header.get(key);
}
public Map<String, String> getHeader() {
return header;
}
public Iterator<Map.Entry<String, String>> iterator() {
return header.entrySet().iterator();
}
/**
* Transfer to KV part list. The odd index is key and the even index is value.
*
* @return KV string list
*/
public List<String> toList() {
List<String> list = new ArrayList<String>(header.size() * 2);
Iterator<Map.Entry<String, String>> iterator = iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
list.add(entry.getKey());
list.add(entry.getValue());
}
return list;
}
/**
* Add all KV list to header. The odd index is key and the even index is value.
*
* @param list KV list
* @return header
*/
public Header addAll(List<String> list) {
if ((list.size() & 1) != 0) {
throw new IllegalArgumentException("list size must be a multiple of 2");
}
for (int i = 0; i < list.size(); ) {
String key = list.get(i++);
if (StringUtils.isNotEmpty(key)) {
header.put(key, list.get(i++));
}
}
return this;
}
/**
* Add all parameters to header.
*
* @param params parameters
*/
public void addAll(Map<String, String> params) {
if (MapUtil.isNotEmpty(params)) {
for (Map.Entry<String, String> entry : params.entrySet()) {
addParam(entry.getKey(), entry.getValue());
}
}
}
/**
* set original format response header.
*
* <p>Currently only corresponds to the response header of JDK.
*
* @param key original response header key
* @param values original response header values
*/
public void addOriginalResponseHeader(String key, List<String> values) {
if (StringUtils.isNotEmpty(key)) {
this.originalResponseHeader.put(key, values);
addParam(key, values.get(0));
}
}
/**
* get original format response header.
*
* <p>Currently only corresponds to the response header of JDK.
*
* @return Map original response header
*/
public Map<String, List<String>> getOriginalResponseHeader() {
return this.originalResponseHeader;
}
public String getCharset() {
String acceptCharset = getValue(HttpHeaderConsts.ACCEPT_CHARSET);
if (acceptCharset == null) {
String contentType = getValue(HttpHeaderConsts.CONTENT_TYPE);
acceptCharset = StringUtils.isNotBlank(contentType) ? analysisCharset(contentType) : Constants.ENCODE;
}
return acceptCharset;
}
private String analysisCharset(String contentType) {
String[] values = contentType.split(";");
String charset = Constants.ENCODE;
if (values.length == 0) {
return charset;
}
for (String value : values) {
if (value.startsWith("charset=")) {
charset = value.substring("charset=".length());
}
}
return charset;
}
public void clear() {
header.clear();
originalResponseHeader.clear();
}
@Override
public String toString() {
return "Header{" + "headerToMap=" + header + '}';
}
}
三、新模块,基于多种Http组件分装、可扩展性更好.
具体模块查看
1、NacosRestTemplate[同步RestTemplate]
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.HttpRestResult;
import com.alibaba.nacos.common.http.HttpUtils;
import com.alibaba.nacos.common.http.client.handler.ResponseHandler;
import com.alibaba.nacos.common.http.client.request.DefaultHttpClientRequest;
import com.alibaba.nacos.common.http.client.request.HttpClientRequest;
import com.alibaba.nacos.common.http.client.request.JdkHttpClientRequest;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.HttpMethod;
import org.slf4j.Logger;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Nacos rest template Interface specifying a basic set of RESTful operations.
*
* @author mai.jh
* @see HttpClientRequest
* @see HttpClientResponse
*/
public class NacosRestTemplate extends AbstractNacosRestTemplate {
private final HttpClientRequest requestClient;
private final List<HttpClientRequestInterceptor> interceptors = new ArrayList<HttpClientRequestInterceptor>();
public NacosRestTemplate(Logger logger, HttpClientRequest requestClient) {
super(logger);
this.requestClient = requestClient;
}
/**
* http get URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> get(String url, Header header, Query query, Type responseType) throws Exception {
return execute(url, HttpMethod.GET, new RequestHttpEntity(header, query), responseType);
}
/**
* http get URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
*
* @param url url
* @param config http config
* @param header headers
* @param query http query param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> get(String url, HttpClientConfig config, Header header, Query query, Type responseType)
throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config, header, query);
return execute(url, HttpMethod.GET, requestHttpEntity, responseType);
}
/**
* get request, may be pulling a lot of data URL request params are expanded using the given query {@link Query},
* More request parameters can be set via body.
*
* <p>This method can only be used when HttpClientRequest is implemented by {@link DefaultHttpClientRequest}, note:
* {@link JdkHttpClientRequest} Implementation does not support this method.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body get with body
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> getLarge(String url, Header header, Query query, Object body, Type responseType)
throws Exception {
return execute(url, HttpMethod.GET_LARGE, new RequestHttpEntity(header, query, body), responseType);
}
/**
* http delete URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> delete(String url, Header header, Query query, Type responseType) throws Exception {
return execute(url, HttpMethod.DELETE, new RequestHttpEntity(header, query), responseType);
}
/**
* http delete URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
*
* @param url url
* @param config http config
* @param header http header param
* @param query http query param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> delete(String url, HttpClientConfig config, Header header, Query query,
Type responseType) throws Exception {
return execute(url, HttpMethod.DELETE, new RequestHttpEntity(config, header, query), responseType);
}
/**
* http put Create a new resource by PUTting the given body to http request.
*
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> put(String url, Header header, Query query, Object body, Type responseType)
throws Exception {
return execute(url, HttpMethod.PUT, new RequestHttpEntity(header, query, body), responseType);
}
/**
* http put json Create a new resource by PUTting the given body to http request, http header contentType default
* 'application/json;charset=UTF-8'.
*
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putJson(String url, Header header, Query query, String body, Type responseType)
throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
query, body);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
/**
* http put json Create a new resource by PUTting the given body to http request, http header contentType default
* 'application/json;charset=UTF-8'.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putJson(String url, Header header, String body, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
body);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
/**
* http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given query {@code Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putForm(String url, Header header, Query query, Map<String, String> bodyValues,
Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
/**
* http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putForm(String url, Header header, Map<String, String> bodyValues, Type responseType)
throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
/**
* http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
*
* @param url url
* @param config http config
* @param header http header param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> putForm(String url, HttpClientConfig config, Header header,
Map<String, String> bodyValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config,
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);
return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);
}
/**
* http post Create a new resource by POSTing the given object to the http request.
*
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> post(String url, Header header, Query query, Object body, Type responseType)
throws Exception {
return execute(url, HttpMethod.POST, new RequestHttpEntity(header, query, body), responseType);
}
/**
* http post json Create a new resource by POSTing the given object to the http request, http header contentType
* default 'application/json;charset=UTF-8'.
*
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postJson(String url, Header header, Query query, String body, Type responseType)
throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
query, body);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
/**
* http post json Create a new resource by POSTing the given object to the http request, http header contentType
* default 'application/json;charset=UTF-8'.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param body http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postJson(String url, Header header, String body, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),
body);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
/**
* http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param query http query param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postForm(String url, Header header, Query query, Map<String, String> bodyValues,
Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
/**
* http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* @param url url
* @param header http header param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postForm(String url, Header header, Map<String, String> bodyValues, Type responseType)
throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
/**
* http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header
* contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.
*
* <p>{@code config} Specify the request config via {@link HttpClientConfig}
*
* @param url url
* @param config http config
* @param header http header param
* @param bodyValues http body param
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> postForm(String url, HttpClientConfig config, Header header,
Map<String, String> bodyValues, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config,
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);
return execute(url, HttpMethod.POST, requestHttpEntity, responseType);
}
/**
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns
* the response as {@link HttpRestResult}.
*
* @param url url
* @param header http header param
* @param query http query param
* @param bodyValues http body param
* @param httpMethod http method
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> exchangeForm(String url, Header header, Query query, Map<String, String> bodyValues,
String httpMethod, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues);
return execute(url, httpMethod, requestHttpEntity, responseType);
}
/**
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns
* the response as {@link HttpRestResult}.
*
* @param url url
* @param config HttpClientConfig
* @param header http header param
* @param query http query param
* @param body http body param
* @param httpMethod http method
* @param responseType return type
* @return {@link HttpRestResult}
* @throws Exception ex
*/
public <T> HttpRestResult<T> exchange(String url, HttpClientConfig config, Header header, Query query,
Object body, String httpMethod, Type responseType) throws Exception {
RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config, header, query, body);
return execute(url, httpMethod, requestHttpEntity, responseType);
}
/**
* Set the request interceptors that this accessor should use.
*
* @param interceptors {@link HttpClientRequestInterceptor}
*/
public void setInterceptors(List<HttpClientRequestInterceptor> interceptors) {
if (this.interceptors != interceptors) {
this.interceptors.clear();
this.interceptors.addAll(interceptors);
}
}
/**
* Return the request interceptors that this accessor uses.
*
* <p>The returned {@link List} is active and may get appended to.
*/
public List<HttpClientRequestInterceptor> getInterceptors() {
return interceptors;
}
@SuppressWarnings("unchecked")
private <T> HttpRestResult<T> execute(String url, String httpMethod, RequestHttpEntity requestEntity,
Type responseType) throws Exception {
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
if (logger.isDebugEnabled()) {
logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
}
ResponseHandler<T> responseHandler = super.selectResponseHandler(responseType);
HttpClientResponse response = null;
try {
response = this.requestClient().execute(uri, httpMethod, requestEntity);
return responseHandler.handle(response);
} finally {
if (response != null) {
response.close();
}
}
}
private HttpClientRequest requestClient() {
if (CollectionUtils.isNotEmpty(interceptors)) {
if (logger.isDebugEnabled()) {
logger.debug("Execute via interceptors :{}", interceptors);
}
return new InterceptingHttpClientRequest(requestClient, interceptors.iterator());
}
return requestClient;
}
/**
* close request client.
*/
public void close() throws Exception {
requestClient.close();
}
}
2、NacosAsyncRestTemplate【异步RestTemplate】
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http.client;
import com.alibaba.nacos.common.http.Callback;
import com.alibaba.nacos.common.http.HttpUtils;
import com.alibaba.nacos.common.http.client.handler.ResponseHandler;
import com.alibaba.nacos.common.http.client.request.AsyncHttpClientRequest;
import com.alibaba.nacos.common.http.client.response.HttpClientResponse;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RequestHttpEntity;
import com.alibaba.nacos.common.utils.HttpMethod;
import org.slf4j.Logger;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.Map;
/**
* Nacos async rest template.
*
* @author mai.jh
* @see AsyncHttpClientRequest
* @see HttpClientResponse
*/
public class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {
private final AsyncHttpClientRequest clientRequest;
public NacosAsyncRestTemplate(Logger logger, AsyncHttpClientRequest clientRequest) {
super(logger);
this.clientRequest = clientRequest;
}
/**
* async http get URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param responseType return type
* @param header http header param
* @param query http query param
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void get(String url, Header header, Query query, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.GET, new RequestHttpEntity(header, query), responseType, callback);
}
/**
* async get request, may be pulling a lot of data URL request params are expanded using the given query {@link
* Query}, More request parameters can be set via body.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body get with body
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void getLarge(String url, Header header, Query query, Object body, Type responseType,
Callback<T> callback) {
execute(url, HttpMethod.GET_LARGE, new RequestHttpEntity(header, query, body), responseType, callback);
}
/**
* async http delete URL request params are expanded using the given query {@link Query},
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void delete(String url, Header header, Query query, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.DELETE, new RequestHttpEntity(header, query), responseType, callback);
}
/**
* async http delete large request, when the parameter exceeds the URL limit, you can use this method to put the
* parameter into the body pass.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param body body
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void delete(String url, Header header, String body, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.DELETE_LARGE,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), Query.EMPTY, body),
responseType, callback);
}
/**
* async http put Create a new resource by PUTting the given body to http request.
*
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void put(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.PUT, new RequestHttpEntity(header, query, body), responseType, callback);
}
/**
* async http put Json Create a new resource by PUTting the given body to http request, http header contentType
* default 'application/json;charset=UTF-8'.
*
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void putJson(String url, Header header, Query query, String body, Type responseType,
Callback<T> callback) {
execute(url, HttpMethod.PUT,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), query, body), responseType,
callback);
}
/**
* async http put Json Create a new resource by PUTting the given body to http request, http header contentType
* default 'application/json;charset=UTF-8'.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void putJson(String url, Header header, String body, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.PUT, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), body),
responseType, callback);
}
/**
* async http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http
* header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void putForm(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,
Callback<T> callback) {
execute(url, HttpMethod.PUT,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues),
responseType, callback);
}
/**
* async http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http
* header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void putForm(String url, Header header, Map<String, String> bodyValues, Type responseType,
Callback<T> callback) {
execute(url, HttpMethod.PUT,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues),
responseType, callback);
}
/**
* async http post Create a new resource by POSTing the given object to the http request.
*
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void post(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.POST, new RequestHttpEntity(header, query, body), responseType, callback);
}
/**
* async http post Json Create a new resource by POSTing the given object to the http request, http header
* contentType default 'application/json;charset=UTF-8'.
*
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void postJson(String url, Header header, Query query, String body, Type responseType,
Callback<T> callback) {
execute(url, HttpMethod.POST,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), query, body), responseType,
callback);
}
/**
* async http post Json Create a new resource by POSTing the given object to the http request, http header
* contentType default 'application/json;charset=UTF-8'.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param body http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void postJson(String url, Header header, String body, Type responseType, Callback<T> callback) {
execute(url, HttpMethod.POST, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), body),
responseType, callback);
}
/**
* async http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http
* header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>URL request params are expanded using the given query {@link Query}.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param query http query param
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void postForm(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,
Callback<T> callback) {
execute(url, HttpMethod.POST,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues),
responseType, callback);
}
/**
* async http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http
* header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.
*
* <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.
*
* <p>{@code callback} Result callback execution,
* if you need response headers, you can convert the received RestResult to HttpRestResult.
*
* @param url url
* @param header http header param
* @param bodyValues http body param
* @param responseType return type
* @param callback callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}
*/
public <T> void postForm(String url, Header header, Map<String, String> bodyValues, Type responseType,
Callback<T> callback) {
execute(url, HttpMethod.POST,
new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues),
responseType, callback);
}
@SuppressWarnings("unchecked")
private <T> void execute(String url, String httpMethod, RequestHttpEntity requestEntity, Type type,
Callback<T> callback) {
try {
URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());
if (logger.isDebugEnabled()) {
logger.debug("HTTP method: {}, url: {}, body: {}", httpMethod, uri, requestEntity.getBody());
}
ResponseHandler<T> responseHandler = super.selectResponseHandler(type);
clientRequest.execute(uri, httpMethod, requestEntity, responseHandler, callback);
} catch (Exception e) {
// When an exception occurs, use Callback to pass it instead of throw it directly.
callback.onError(e);
}
}
/**
* close request client.
*/
public void close() throws Exception {
clientRequest.close();
}
}
3、HttpClientFactory
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
/**
* http Client Factory.
*
* @author mai.jh
*/
public interface HttpClientFactory {
/**
* create new nacost rest.
*
* @return NacosRestTemplate
*/
NacosRestTemplate createNacosRestTemplate();
/**
* create new nacos async rest.
*
* @return NacosAsyncRestTemplate
*/
NacosAsyncRestTemplate createNacosAsyncRestTemplate();
}
4、AbstractHttpClientFactory
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http;
import org.slf4j.Logger;
/**
* default http client factory.
*
* @author mai.jh
*/
public class DefaultHttpClientFactory extends AbstractHttpClientFactory {
private static final int TIMEOUT = Integer.getInteger("nacos.http.timeout", 5000);
private final Logger logger;
public DefaultHttpClientFactory(Logger logger) {
this.logger = logger;
}
@Override
protected HttpClientConfig buildHttpClientConfig() {
return HttpClientConfig.builder().setConTimeOutMillis(TIMEOUT).setReadTimeOutMillis(TIMEOUT >> 1).build();
}
@Override
protected Logger assignLogger() {
return logger;
}
}
HttpClientConfig【连接池参数】
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.http;
import com.alibaba.nacos.common.utils.ThreadUtils;
import java.util.concurrent.TimeUnit;
/**
* http client config build.
*
* @author mai.jh
*/
public class HttpClientConfig {
/**
* connect time out.
*/
private final int conTimeOutMillis;
/**
* read time out.
*/
private final int readTimeOutMillis;
/**
* connTimeToLive.
*/
private final long connTimeToLive;
/**
* connTimeToLiveTimeUnit.
*/
private final TimeUnit connTimeToLiveTimeUnit;
/**
* connectionRequestTimeout.
*/
private final int connectionRequestTimeout;
/**
* max redirect.
*/
private final int maxRedirects;
/**
* max connect total.
*/
private final int maxConnTotal;
/**
* Assigns maximum connection per route value.
*/
private final int maxConnPerRoute;
/**
* is HTTP compression enabled.
*/
private final boolean contentCompressionEnabled;
/**
* io thread count.
*/
private final int ioThreadCount;
/**
* user agent.
*/
private final String userAgent;
public HttpClientConfig(int conTimeOutMillis, int readTimeOutMillis, long connTimeToLive, TimeUnit timeUnit,
int connectionRequestTimeout, int maxRedirects, int maxConnTotal, int maxConnPerRoute,
boolean contentCompressionEnabled, int ioThreadCount, String userAgent) {
this.conTimeOutMillis = conTimeOutMillis;
this.readTimeOutMillis = readTimeOutMillis;
this.connTimeToLive = connTimeToLive;
this.connTimeToLiveTimeUnit = timeUnit;
this.connectionRequestTimeout = connectionRequestTimeout;
this.maxRedirects = maxRedirects;
this.maxConnTotal = maxConnTotal;
this.maxConnPerRoute = maxConnPerRoute;
this.contentCompressionEnabled = contentCompressionEnabled;
this.ioThreadCount = ioThreadCount;
this.userAgent = userAgent;
}
public int getConTimeOutMillis() {
return conTimeOutMillis;
}
public int getReadTimeOutMillis() {
return readTimeOutMillis;
}
public long getConnTimeToLive() {
return connTimeToLive;
}
public TimeUnit getConnTimeToLiveTimeUnit() {
return connTimeToLiveTimeUnit;
}
public int getConnectionRequestTimeout() {
return connectionRequestTimeout;
}
public int getMaxRedirects() {
return maxRedirects;
}
public int getMaxConnTotal() {
return maxConnTotal;
}
public int getMaxConnPerRoute() {
return maxConnPerRoute;
}
public boolean getContentCompressionEnabled() {
return contentCompressionEnabled;
}
public int getIoThreadCount() {
return ioThreadCount;
}
public String getUserAgent() {
return userAgent;
}
public static HttpClientConfigBuilder builder() {
return new HttpClientConfigBuilder();
}
public static final class HttpClientConfigBuilder {
private int conTimeOutMillis = -1;
private int readTimeOutMillis = -1;
private long connTimeToLive = -1;
private TimeUnit connTimeToLiveTimeUnit = TimeUnit.MILLISECONDS;
private int connectionRequestTimeout = 5000;
private int maxRedirects = 50;
private int maxConnTotal = 0;
private int maxConnPerRoute = 0;
private boolean contentCompressionEnabled = true;
private int ioThreadCount = ThreadUtils.getSuitableThreadCount(1);
private String userAgent;
public HttpClientConfigBuilder setConTimeOutMillis(int conTimeOutMillis) {
this.conTimeOutMillis = conTimeOutMillis;
return this;
}
public HttpClientConfigBuilder setReadTimeOutMillis(int readTimeOutMillis) {
this.readTimeOutMillis = readTimeOutMillis;
return this;
}
public HttpClientConfigBuilder setConnectionTimeToLive(long connTimeToLive, TimeUnit connTimeToLiveTimeUnit) {
this.connTimeToLive = connTimeToLive;
this.connTimeToLiveTimeUnit = connTimeToLiveTimeUnit;
return this;
}
public HttpClientConfigBuilder setConnectionRequestTimeout(int connectionRequestTimeout) {
this.connectionRequestTimeout = connectionRequestTimeout;
return this;
}
public HttpClientConfigBuilder setMaxRedirects(int maxRedirects) {
this.maxRedirects = maxRedirects;
return this;
}
public HttpClientConfigBuilder setMaxConnTotal(int maxConnTotal) {
this.maxConnTotal = maxConnTotal;
return this;
}
public HttpClientConfigBuilder setMaxConnPerRoute(int maxConnPerRoute) {
this.maxConnPerRoute = maxConnPerRoute;
return this;
}
public HttpClientConfigBuilder setContentCompressionEnabled(boolean contentCompressionEnabled) {
this.contentCompressionEnabled = contentCompressionEnabled;
return this;
}
public HttpClientConfigBuilder setIoThreadCount(int ioThreadCount) {
this.ioThreadCount = ioThreadCount;
return this;
}
public HttpClientConfigBuilder setUserAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}
/**
* build http client config.
*
* @return HttpClientConfig
*/
public HttpClientConfig build() {
return new HttpClientConfig(conTimeOutMillis, readTimeOutMillis, connTimeToLive, connTimeToLiveTimeUnit,
connectionRequestTimeout, maxRedirects, maxConnTotal, maxConnPerRoute, contentCompressionEnabled,
ioThreadCount, userAgent);
}
}
}
开启SSL
HttpClient整体封装比较完善,对项目中使用也比较有参考.