RestTemplate和 apache HttpClient 使用方式
高并发请求中需要设置:setMaxConnTotal、setMaxConnPerRoute 两个属性
一、RestTemplate
RestTemplate 是简化了组装请求对象 该类存在于 依赖 spring-boot-starter-web中,RestTemplate 支持get,post 现
1、RestTemplate 不是可直接注入Bean, 需要实例化生成Bean
Spring Boot 的自动配置机制非常强大,但并不是所有的类都被默认自动配置为 bean。对于 RestTemplate 来说,Spring Boot 并没有默认自动配置一个 RestTemplate bean,主要原因有以下几点:
1)、多样化的配置需求
2)、鼓励显式配置
3)、灵活性和扩展性:显式配置使得应用更加灵活,可以根据需要创建和配置多个不同的
1、简单方式生成Bean @Configuration public class AppConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } } 2、自定义参数 生成Bean @Configuration public class RestTemplateAutoConfiguration { private final RestTemplateBuilder builder; public RestTemplateAutoConfiguration(RestTemplateBuilder builder) { this.builder = builder; } @Bean public RestTemplate restTemplate() { return builder .setConnectTimeout(Duration.ofSeconds(3)) .setReadTimeout(Duration.ofMillis(PushTaskConstant.DEFAULT_REQUEST_TIME)) .requestFactory(() -> new HttpComponentsClientHttpRequestFactory( HttpClientBuilder.create() .setMaxConnTotal(200) .setMaxConnPerRoute(40) .disableAutomaticRetries() .useSystemProperties().build()) ).build(); } }
2、在重点介绍post请求试
1)请求 当请求类型contentType是MediaType.APPLICATION_FORM_URLENCODED
1、请求方法 @Resource RestTemplate restTemplate; @Test public void testRequest(){ headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // 当请求类型contentType是MediaType.APPLICATION_FORM_URLENCODED,请求参数实体必须是MultiValueMap MultiValueMap<String,String> requestBody=new LinkedMultiValueMap<>(); requestBody.add("userName","testregisterName"); requestBody.add("loginNo","testReg"); requestBody.add("contactPhone","15210212542"); requestBody.add("smsCode","3820"); // 请求和header组合用entity HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(requestBody, headers); ResponseEntity response= restTemplate.postForEntity("http://testapi-xxxx.com/openApp/user/registerUser", entity, String.class); System.out.println("response.getStatusCode() = " + response.getStatusCode()); System.out.println("response.getBody() = " + response.getBody()); } 2、接收方法 public ResultEntity<String> registerUser(RegisterUserRequest userRequest) { }
2)当请求类型contentType是MediaType.APPLICATION_JSON
@Resource RestTemplate restTemplate; @Test public void testRequest2(){ RestTemplate restTemplate = new RestTemplate(); headers.setContentType(MediaType.APPLICATION_JSON); // 当contentType 是APPLICATION_JSON 请求参数对象用map Map<String,String> requestEntity=new HashMap<>(); requestEntity.put("userName","testregisterName"); requestEntity.put("loginNo","testReg"); requestEntity.put("contactPhone","15210212542"); requestEntity.put("smsCode","3820"); // 请求和header组合用entity HttpEntity<Map<String, String>> entity = new HttpEntity<>(requestEntity, headers); ResponseEntity response= restTemplate.postForEntity("http://testapi-console.dmall.com/openApp/user/registerUser", entity, String.class); System.out.println("response.getStatusCode() = " + response.getStatusCode()); System.out.println("response.getBody() = " + response.getBody()); }
ps:已有Bean的注入
1、第一种在配置类中 可以以参数注入 @Configuration public class AppConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder .setConnectTimeout(Duration.ofMillis(5000)) .setReadTimeout(Duration.ofMillis(5000)) .build(); } -___________________________- 2、也可以正常以属性注入 @Configuration public class AppConfig { @Resource private RestTemplateBuilder builder; @Bean public RestTemplate restTemplate() { return builder .setConnectTimeout(Duration.ofMillis(5000)) .setReadTimeout(Duration.ofMillis(5000)) .build(); } }
二、 java 8 HttpClient
Apache HttpClient 适合需要更多配置和功能的场景
// 需要引入依赖 <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency>
实例调用 ps: 使用 httpClient 需要显示关闭或 try(){} ,try-with-resources 释放
@Test public void testHttp() throws Exception{ try(CloseableHttpClient httpClient= HttpClients.createDefault()){ HttpPost httpPost=new HttpPost("http://testapi-console.dmall.com/openApp/user/registerUser"); // 可以自定义进行设置 // HttpClients.custom().build() // HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() { // @Override // public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { // if (executionCount >= 3) { // return false; // 超过最大重试次数 // } // if (exception instanceof org.apache.http.NoHttpResponseException) { // return true; // 服务器无响应 // } // if (exception instanceof java.net.SocketTimeoutException) { // return true; // 超时 // } // return false; // 不重试其他类型的异常 // } // }; // 可以自定义进行配置信息 RequestConfig requestConfig=RequestConfig.custom() .setConnectTimeout(5000) .setSocketTimeout(5000) .build(); httpPost.setConfig(requestConfig); Map<String,String> parameters=new HashMap<>(); parameters.put("userName","testregisterName"); parameters.put("loginNo","testReg"); parameters.put("contactPhone","15210212542"); parameters.put("smsCode","3820"); StringJoiner stringJoiner=new StringJoiner("&"); for(Map.Entry entry:parameters.entrySet()){ stringJoiner.add(URLEncoder.encode(entry.getKey().toString(),"UTF-8")+"="+URLEncoder.encode(entry.getValue().toString(),"UTF-8")); } // httpPost.setHeader("Content-Type","application/x-www-form-urlencoded"); // httpPost.setEntity(new StringEntity(stringJoiner.toString())); httpPost.setHeader("Content-Type",MediaType.APPLICATION_JSON_VALUE); httpPost.setEntity(new StringEntity(JSON.toJSONString(parameters))); HttpResponse response=httpClient.execute(httpPost); System.out.println("response.getEntity().getContent().toString() = " + response.getEntity().getContent().toString()); String readStr=""; StringBuilder sb=new StringBuilder(); try(BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(response.getEntity().getContent()))){ while ((readStr=bufferedReader.readLine())!=null){ sb.append(readStr); } } System.out.println("stringJoiner = " + sb.toString()); }catch (Exception e){ e.printStackTrace(); throw e; } }