1 场景

java开发中,使用http连接,访问第三方网络接口,通常使用的连接工具为HttpClientOKHttp

这两种连接工具,使用起来比较复杂,新手容易出问题。如果使用spring框架,可以使用restTemplate来进行http连接请求。

restTemplate默认的连接方式是java中的HttpConnection,可以使用ClientHttpRequestFactory指定不同的HTTP连接方式。

2 依赖

maven依赖如下:

<dependency>     <groupId>org.springframework</groupId>     <artifactId>spring-web</artifactId>     <version>5.2.2.RELEASE</version> </dependency> <dependency>     <groupId>org.apache.httpcomponents</groupId>     <artifactId>httpclient</artifactId>     <version>4.5.7</version> </dependency> 

3 配置

import org.apache.http.client.HttpClient; import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate;  @Configuration public class RestTemplateConfig {          /**      * http连接管理器      * @return      */     @Bean     public HttpClientConnectionManager poolingHttpClientConnectionManager() {         /*// 注册http和https请求         Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()                 .register("http", PlainConnectionSocketFactory.getSocketFactory())                 .register("https", SSLConnectionSocketFactory.getSocketFactory())                 .build();         PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);*/                  PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();         // 最大连接数         poolingHttpClientConnectionManager.setMaxTotal(500);         // 同路由并发数(每个主机的并发)         poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100);         return poolingHttpClientConnectionManager;     }          /**      * HttpClient      * @param poolingHttpClientConnectionManager      * @return      */     @Bean     public HttpClient httpClient(HttpClientConnectionManager poolingHttpClientConnectionManager) {         HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();         // 设置http连接管理器         httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);                  /*// 设置重试次数         httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true));*/                  // 设置默认请求头         /*List<Header> headers = new ArrayList<>();         headers.add(new BasicHeader("Connection", "Keep-Alive"));         httpClientBuilder.setDefaultHeaders(headers);*/                  return httpClientBuilder.build();     }          /**      * 请求连接池配置      * @param httpClient      * @return      */     @Bean     public ClientHttpRequestFactory clientHttpRequestFactory(HttpClient httpClient) {         HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();         // httpClient创建器         clientHttpRequestFactory.setHttpClient(httpClient);         // 连接超时时间/毫秒(连接上服务器(握手成功)的时间,超出抛出connect timeout)         clientHttpRequestFactory.setConnectTimeout(5 * 1000);         // 数据读取超时时间(socketTimeout)/毫秒(务器返回数据(response)的时间,超过抛出read timeout)         clientHttpRequestFactory.setReadTimeout(10 * 1000);         // 连接池获取请求连接的超时时间,不宜过长,必须设置/毫秒(超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool)         clientHttpRequestFactory.setConnectionRequestTimeout(10 * 1000);         return clientHttpRequestFactory;     }          /**      * rest模板      * @return      */     @Bean     public RestTemplate restTemplate(ClientHttpRequestFactory clientHttpRequestFactory) {         // boot中可使用RestTemplateBuilder.build创建         RestTemplate restTemplate = new RestTemplate();         // 配置请求工厂         restTemplate.setRequestFactory(clientHttpRequestFactory);         return restTemplate;     }      } 

4 使用

使用到的实体类如下:

@Data @ToString public class TempUser implements Serializable {     private String userName;        private Integer age; } 

4.1 GET请求

后台接口代码:

@RequestMapping("getUser") public TempUser getUser(TempUser form) {     TempUser tempUser = new TempUser();     tempUser.setUserName(form.getUserName());     tempUser.setAge(form.getAge());     return tempUser; } 
4.1.1 普通访问
TempUser result = restTemplate.getForObject("http://localhost:8080/cs-admin/rest/getUser?userName=张三&age=18", TempUser.class); 
4.1.2 返回HTTP状态
ResponseEntity<TempUser> responseEntity = restTemplate.getForEntity("http://localhost:8080/cs-admin/rest/getUser?userName=张三&age=18", TempUser.class); // 获取状态对象 HttpStatus httpStatus = responseEntity.getStatusCode(); // 获取状态码 int statusCodeValue = responseEntity.getStatusCodeValue(); // 获取headers HttpHeaders httpHeaders = responseEntity.getHeaders(); // 获取body TempUser result = responseEntity.getBody(); 
4.1.3 映射请求参数
Map<String, Object> paramMap = new HashMap<>(); paramMap.put("userName", "张三"); paramMap.put("age", 18); TempUser result = restTemplate.getForObject("http://localhost:8080/cs-admin/rest/getUser?userName={userName}&age={age}", TempUser.class, paramMap); 

4.2 POST请求

4.2.1 普通访问

后台接口代码:

RequestMapping("getPostUser")     public TempUser getPostUser(@RequestBody TempUser form) {     TempUser tempUser = new TempUser();     tempUser.setUserName(form.getUserName());     tempUser.setAge(form.getAge());     return tempUser; } 

(1)普通访问接口

TempUser param = new TempUser(); param.setUserName("张三"); param.setAge(18); TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/getPostUser", param, TempUser.class);  

(2)带HEAD访问接口

// 请求头信息 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.valueOf("application/json;charset=UTF-8")); //headers.add("headParam1", "headParamValue");  // 请求体内容 TempUser param = new TempUser(); param.setUserName("张三"); param.setAge(18);  // 组装请求信息 HttpEntity<TempUser> httpEntity=new HttpEntity<>(param,headers);  TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/getPostUser", httpEntity, TempUser.class);  
4.2.2 无请求体的访问

仅method为post,传参方式仍然为get的param方式

后台接口代码:

@RequestMapping("getPostUserNoBody") public TempUser getPostUserNoBody(TempUser form) {     TempUser tempUser = new TempUser();     tempUser.setUserName(form.getUserName());     tempUser.setAge(form.getAge());     return tempUser; }  

访问方式:

Map<String, Object> paramMap = new HashMap<>(); paramMap.put("userName", "张三"); paramMap.put("age", 18); TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/getPostUserNoBody?userName={userName}&age={age}", null, TempUser.class, paramMap); System.out.println(result);  

4.3 上传文件

后台接口代码:

@RequestMapping("uploadFile") public TempUser uploadFile(HttpServletRequest request, TempUser form) {     MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;     //获取文件信息     MultipartFile multipartFile = multipartHttpServletRequest.getFile("file");     TempUser tempUser = new TempUser();     if (multipartFile != null) {         tempUser.setUserName(form.getUserName()+" "+multipartFile.getOriginalFilename());     }     if(form!=null){         tempUser.setAge(form.getAge());     }     return tempUser; }  

访问方式:

// 文件 FileSystemResource file=new FileSystemResource("D:\\Elasticsearch权威指南(中文版).pdf");  // 设置请求内容 MultiValueMap<String, Object> param=new LinkedMultiValueMap<>(); param.add("file", file); // 其他参数 param.add("userName", "张三"); param.add("age", 18);  // 组装请求信息 HttpEntity<MultiValueMap<String, Object>> httpEntity=new HttpEntity<>(param);  // 发送请求 TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/uploadFile", httpEntity, TempUser.class);