springRestTemplate设计模式

10次阅读

共计 4030 个字符,预计需要花费 11 分钟才能阅读完成。

作用

用于 http 申请,且封装了不同 http 框架,
1.jdk api // 默认
2.httpclient //1. 连接池 2. 超时
3.okhttp // 异步

RestTemplate,自身不实现 http 申请,http 申请的底层实现是其余框架,RestTemplate 的外围有两个
1. 更不便 http 申请
2. 且能够切换不同 http 框架
不同 http 框架,提供的性能不齐全一样

应用层 - 应用

步骤
1. 获取模板
2. 调用模板的办法

List<AuditResult> auditResultList = null; // 响应数据
try {auditResultList = HttpClientUtil.getTemplate().postForObject(url,
         audits // 入参数据的类型个别是 map/list, List.class // 响应数据的数据类型);
} catch (Throwable e) {log.error(msg + "调用风控系统超时!" + e.getMessage());
   return;
}

切换默认 jdk api 为 httpclient

默认是 jdk api,为什么要切换?
因为有更多的配置项,比方
1. 连接池
2. 超时


如何切换?
须要简略封装一下,
1. 用 httpclient 的客户端申请类 CloseableHttpClient 笼罩默认的
2. 配置连接池
3. 配置超时

package xxx.util;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;

public class HttpClientUtil {
// 连接池配置项
   private static int POOLSIZE = 150;// 连接池
   private static PoolingHttpClientConnectionManager connMgr = null;
// 超时配置项
   private final static int SOCKETTIMEOUT = 1000;// 读取响应超时工夫
   private final static int CONNECTIONREQUESTTIMEOUT = 3000; // 从连接池获取连贯超时工夫
   private final static int CONNECTTIMEOUT = 2000;// 连贯超时工夫

   public static RestTemplate getTemplate() {CloseableHttpClient httpClient = getConnection();
      RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient)); // 用 httpclient 的客户端申请类 CloseableHttpClient 笼罩默认的

      List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
      // 采纳 fastjson 进行数据转换
      FastJsonHttpMessageConverter fastjson = new FastJsonHttpMessageConverter();
      fastjson.setFeatures(SerializerFeature.WriteClassName,
            SerializerFeature.BrowserCompatible,
            SerializerFeature.DisableCircularReferenceDetect);
      converters.add(fastjson);
      template.setMessageConverters(converters);
      return template;
   }

   private static CloseableHttpClient getConnection() {if (connMgr == null) {
         // 创立链接池。连接池能够并发申请 100 个连贯
         connMgr = new PoolingHttpClientConnectionManager();
         connMgr.setMaxTotal(POOLSIZE + 1);
         connMgr.setDefaultMaxPerRoute(POOLSIZE);
      }
      RequestConfig requestConfig = RequestConfig.custom()
            .setConnectionRequestTimeout(CONNECTIONREQUESTTIMEOUT)
            .setConnectTimeout(CONNECTTIMEOUT)
            .setSocketTimeout(SOCKETTIMEOUT).build(); // 配置超时
      CloseableHttpClient httpClient = HttpClients.custom()
            .setConnectionManager(connMgr) // 配置连接池
            .setDefaultRequestConfig(requestConfig).build();
      return httpClient;
   }

}

源码

流程是
1. 获取客户端
2. 申请服务器

不论是哪一种 http 框架,流程都是一样。外围步骤就是这两个。

public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor) throws RestClientException {Assert.notNull(url, "'url' must not be null");
    Assert.notNull(method, "'method' must not be null");
    ClientHttpResponse response = null;

    Object var7;
    try {ClientHttpRequest request = this.createRequest(url, method); // 获取 http 申请客户端
        if (requestCallback != null) {requestCallback.doWithRequest(request);
        }

        response = request.execute(); // 申请服务器
        if (!this.getErrorHandler().hasError(response)) {this.logResponseStatus(method, url, response);
        } else {this.handleResponseError(method, url, response);
        }

        if (responseExtractor == null) {
            var7 = null;
            return var7;
        }

        var7 = responseExtractor.extractData(response);
    } catch (IOException var11) {throw new ResourceAccessException("I/O error on" + method.name() + "request for \"" + url + "\":" + var11.getMessage(), var11);
    } finally {if (response != null) {response.close();
        }

    }

    return var7;
}

因为切换了 http 框架,客户端类当初是 CloseableHttpClient(httpclient 框架的客户端类)。其实就是两个步骤,
1. 封装的时候,用 httpclient 的客户端申请类 CloseableHttpClient 笼罩默认的
2. 底层申请服务器的时候,就应用切换之后的客户端

设计模式

看名字是模板模式,spring 里还有其余的相似名字,JdbcTemplate(mybatis/hibernate 等 dao 框架)、RedisTemplate。

RestTemplate 也是不同 http 框架 (jdk api/httpclient/okhttp) 的封装。

slf 也是对不同日志框架 (log4j 等) 的封装,叫门面模式。

不论模式名字叫什么,实质是
1. 本人不实现,只是封装其余框架
底层实现是框架
2. 能够切换不同框架
不同框架,提供的性能不齐全一样

精确的说,模式名字应该叫切换模式,即
1. 封装了不同框架
2. 而后,实现了对不同框架的切换

正文完
 0