Chao's Blog Chao's Blog
首页
  • vue

    • vue路由
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • java
  • spring
  • springboot
  • springcloud
  • git
  • maven
  • nginx
  • tomcat
  • springmvc
  • jvm
  • 图数据库
  • mysql数据库
  • redis数据库
  • windows下docker安装nginx并挂载目录
  • linux命令
  • linux安装软件
  • linux脚本
  • idea
  • vscode
  • 归档
  • 综合项目

    • 若依项目
    • mall项目
  • java
  • mybatis
  • xxl-job
  • mybatis
GitHub (opens new window)

~chao

永远菜鸟,不断努力~
首页
  • vue

    • vue路由
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • java
  • spring
  • springboot
  • springcloud
  • git
  • maven
  • nginx
  • tomcat
  • springmvc
  • jvm
  • 图数据库
  • mysql数据库
  • redis数据库
  • windows下docker安装nginx并挂载目录
  • linux命令
  • linux安装软件
  • linux脚本
  • idea
  • vscode
  • 归档
  • 综合项目

    • 若依项目
    • mall项目
  • java
  • mybatis
  • xxl-job
  • mybatis
GitHub (opens new window)
  • java

    • java深度克隆
    • restemplate

      • resttemplate 设置请求头和请求体
      • Restemplate设置连接池
        • 二、实战代码
          • 2.1 依赖引入
          • 2.2 配置项
          • 2.2.1 配置
          • 2.2.2 读取配置文件
          • 2.3 配置文件
          • 2.4 简单的工具类
        • 三、源码地址
    • hashcode()和equals()的作用、区别、联系
    • java8新特性
    • 接口与抽象类
    • java深度克隆工具类支持对象和list克隆
    • 子线程执行10次后,主线程再运行5次,这样交替执行三遍
    • CountDownLatch的理解和使用
    • CAS详解
    • java中的各种锁详细介绍
    • java线程池
    • Java锁之偏向级锁、轻量级锁、重量级锁
    • Transactional注解与try{}catch(Exception e){}同时使用事务控制无效问题
    • JAVA8 optional用法
    • CyclicBarrier 使用详解
    • Semaphore 使用及原理
    • Java中七大垃圾回收器
  • spring

  • springboot

  • springcloud

  • git

  • maven

  • nginx

  • tomcat

  • springmvc

  • jvm

  • 正则表达式

  • 消息中间件

  • python

  • 后端
  • java
  • restemplate
~chao
2022-11-14
目录

Restemplate设置连接池

resttemplate如果使用默认配置,每次连接都会建立新连接,如果高吞吐量的话会影响性能,因此可以使用连接池。

# 二、实战代码

# 2.1 依赖引入

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- 将tomcat替换为undertow -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

<!-- 自定义的元数据依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

<!-- httpclient,为了使用其连接池 -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.12</version>
</dependency>

<!-- for fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
</dependency>

<!-- lombok,减少代码量,idea需要安装lombok插件 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 2.2 配置项

# 2.2.1 配置

http:
  pool:
    # 连接超时
    connectTimeout: 5000
    connectionRequestTimeout: 5000
    defaultMaxPerRoute: 20
    # 最大连接数
    maxTotal: 100
    # 服务器返回数据(response)的时间
    socketTimeout: 5000
    validateAfterInactivity: 30000
1
2
3
4
5
6
7
8
9
10
11

# 2.2.2 读取配置文件

@Component
@ConfigurationProperties(prefix = "http.pool")
@Data
public class HttpClientProperties {


    /**
     * 最大连接数
     */
    private Integer maxTotal;
    /**
     * 路由是对最大连接数的细分
     * 每个路由基础的连接数
     */
    private Integer defaultMaxPerRoute;
    /**
     * 连接超时时间
     */
    private Integer connectTimeout;
    /**
     * 从连接池中获取连接的超时时间
     */
    private Integer connectionRequestTimeout;
    /**
     * 服务器返回数据(response)的时间
     */
    private Integer socketTimeout;
    /**
     * 可用空闲连接过期时间
     * 重用空闲连接时会先检查是否空闲时间超过这个时间,如果超过,释放socket重新建立
     */
    private Integer validateAfterInactivity;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 2.3 配置文件

@Configuration
public class RestTemplateConfig {


    private final HttpClientProperties httpClientProperties;

    public RestTemplateConfig(HttpClientProperties httpClientProperties) {
        this.httpClientProperties = httpClientProperties;
    }


    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory){
        return new RestTemplate(factory);
    }


    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory(){
        return new HttpComponentsClientHttpRequestFactory(httpClient());
    }


    @Bean
    public HttpClient httpClient() {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        connectionManager.setMaxTotal(httpClientProperties.getMaxTotal());
        connectionManager.setDefaultMaxPerRoute(httpClientProperties.getDefaultMaxPerRoute());
        connectionManager.setValidateAfterInactivity(httpClientProperties.getValidateAfterInactivity());
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(httpClientProperties.getSocketTimeout())
                .setConnectTimeout(httpClientProperties.getConnectTimeout())
                .setConnectionRequestTimeout(httpClientProperties.getConnectionRequestTimeout())
                .build();
        return HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

# 2.4 简单的工具类

@Component
@Slf4j
public class HttpClientUtils {

    private final RestTemplate restTemplate;

    public HttpClientUtils(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * Get
     */
    public String get(String uri, Map<String, String> param, String token) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("token", token);
        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        StringBuilder url = new StringBuilder();
        url.append(uri).append("?");
        param.forEach((k, v) -> url.append(k).append("=").append(v).append("&"));
        String getUrl = url.substring(0, url.length() - 1);
        ResponseEntity<CodeResult> response = restTemplate.exchange(getUrl, HttpMethod.GET, requestEntity, CodeResult.class);
        return parseCodeResult(response);
    }

    /**
     * post方式请求接口
     * - 参数形式:form-data
     */
    public String postFormData(String url, MultiValueMap<String, Object> paramMap, String token) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("token", token);
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        //用HttpEntity封装整个请求报文
        HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(paramMap, headers);
        ResponseEntity<CodeResult> response = restTemplate.postForEntity(url, files, CodeResult.class);
        return parseCodeResult(response);
    }

    /**
     * post方式请求接口
     * - 参数形式:json
     */
    public String postJson(String url, String param, String token) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("token", token);
        HttpEntity<String> entity = new HttpEntity<>(param, headers);
        ResponseEntity<CodeResult> response = restTemplate.postForEntity(url, entity, CodeResult.class);
        return parseCodeResult(response);
    }

    /**
     * 解析云端服务接口返回值
     */
    public String parseCodeResult(ResponseEntity<CodeResult> response) {
        if (response.getStatusCodeValue() != HttpStatus.OK.value()) {
            throw new RuntimeException("网络请求失败,状态码:" + response.getStatusCodeValue());
        }
        CodeResult codeResult = response.getBody();
        assert codeResult != null;
        if (!codeResult.getSuccess()) {
            log.error("调用后台服务接口错误,返回值:{}", JSON.toJSON(codeResult));
            throw new RuntimeException("调用后台服务接口错误, 错误信息:" + codeResult.getMsg());
        }
        return JSON.toJSONString(codeResult.getData());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

# 三、源码地址

https://github.com/lysmile/spring-boot-demo/tree/master/spring-boot-resttemplate-demo (opens new window)

编辑 (opens new window)
上次更新: 2024/01/26, 05:03:22
resttemplate 设置请求头和请求体
hashcode()和equals()的作用、区别、联系

← resttemplate 设置请求头和请求体 hashcode()和equals()的作用、区别、联系→

最近更新
01
python使用生成器读取大文件-500g
09-24
02
Windows环境下 Docker Desktop 安装 Nginx
04-10
03
使用nginx部署多个前端项目(三种方式)
04-10
更多文章>
Theme by Vdoing | Copyright © 2022-2024 chaos | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式