SpringBoot基础教程2-1-11 RestTemplate整合HttpClient
可以在logback里单独配一个debug级别的logger,把org.apache.http下面的日志定向到控制台:
发布日期:2025-05-04 01:55:20
浏览次数:13
分类:精选文章
本文共 10435 字,大约阅读时间需要 34 分钟。
使用RestTemplate进行HTTP请求的服务端开发
概述
Http请求在服务端开发中是必不可少的,本文将使用Spring Boot中的RestTemplate作为门面,HttpClient作为实现,演示基础的Http请求例子。
源码分析
1. 添加pom.xml依赖
RestTemplate在Spring-Web模块中内置,Spring Boot会自动引入。以下是需要添加的依赖:
org.apache.httpcomponents httpclient 4.5.5 io.netty netty-all 4.1.5.Final org.springframework.boot spring-boot-configuration-processor true
2. 配置文件application.yml(可选)
# yml配置的优先级高于java配置;如果yml配置和java配置同时存在,则yml配置会覆盖java配置spring: restTemplate: maxTotalConnect: 1000 #连接池的最大连接数,0代表不限;如果取0,需要考虑连接泄露导致系统崩溃的后果 maxConnectPerRoute: 200 connectTimeout: 3000 readTimeout: 5000 charset: UTF-8
3. 编写RestTemplate配置(必备)
@Configuration@ConfigurationProperties(prefix = "spring.restTemplate")@ConditionalOnClass(value = {RestTemplate.class, CloseableHttpClient.class})public class RestTemplateConfig { // java配置的优先级低于yml配置;如果yml配置不存在,会采用java配置 private int maxTotalConnection = 500; private int maxConnectionPerRoute = 100; private int connectionTimeout = 2000; private int readTimeout = 30000; private String charset = "UTF-8"; public void setMaxTotalConnection(int maxTotalConnection) { this.maxTotalConnection = maxTotalConnection; } public void setMaxConnectionPerRoute(int maxConnectionPerRoute) { this.maxConnectionPerRoute = maxConnectionPerRoute; } public void setConnectionTimeout(int connectionTimeout) { this.connectionTimeout = connectionTimeout; } public void setReadTimeout(int readTimeout) { this.readTimeout = readTimeout; } public void setCharset(String charset) { this.charset = charset; } @Bean(name = "clientHttpRequestFactory") public ClientHttpRequestFactory clientHttpRequestFactory() { return createClientHttpRequestFactory(this.connectionTimeout, this.readTimeout); } @Bean(name = "restTemplate") @ConditionalOnMissingBean(RestTemplate.class) public RestTemplate restTemplate(ClientHttpRequestFactory factory) { return createRestTemplate(factory); } @Bean(name = "asyncRestTemplate") @ConditionalOnMissingBean(AsyncRestTemplate.class) public AsyncRestTemplate asyncRestTemplate(RestTemplate restTemplate) { final Netty4ClientHttpRequestFactory factory = new Netty4ClientHttpRequestFactory(); factory.setConnectTimeout(this.connectionTimeout); factory.setReadTimeout(this.readTimeout); return new AsyncRestTemplate(factory, restTemplate); } private ClientHttpRequestFactory createClientHttpRequestFactory(int connectionTimeout, int readTimeout) { if (this.maxTotalConnection <= 0) { throw new IllegalArgumentException("invalid maxTotalConnection: " + maxTotalConnection); } if (this.maxConnectionPerRoute <= 0) { throw new IllegalArgumentException("invalid maxConnectionPerRoute: " + maxTotalConnection); } List headers = new LinkedList<>(); headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate")); headers.add(new BasicHeader("Accept-Language", "zh-CN,zh;q=0.8,en;q=0.6")); HttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(0, false); CloseableHttpClient httpClient = HttpClients.custom() .setDefaultHeaders(headers) .setRetryHandler(retryHandler) .build(); HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); factory.setConnectTimeout(connectionTimeout); factory.setReadTimeout(readTimeout); return factory; } private RestTemplate createRestTemplate(ClientHttpRequestFactory factory) { RestTemplate restTemplate = new RestTemplate(factory); modifyDefaultCharset(restTemplate); restTemplate.setErrorHandler(new DefaultResponseErrorHandler()); return restTemplate; } private void modifyDefaultCharset(RestTemplate restTemplate) { List converterList = restTemplate.getMessageConverters(); HttpMessageConverter converterTarget = null; for (HttpMessageConverter item : converterList) { if (StringHttpMessageConverter.class == item.getClass()) { converterTarget = item; break; } } if (null != converterTarget) { converterList.remove(converterTarget); } Charset defaultCharset = Charset.forName(charset); converterList.add(1, new StringHttpMessageConverter(defaultCharset)); }} 4. Get请求演示
@RestControllerpublic class GetTestController { @Resource private RestTemplate restTemplate; @GetMapping("/baidu1/{key}") public String get1(@PathVariable String key) throws UnsupportedEncodingException { String encodeKey = URLEncoder.encode(key, "UTF-8"); String url = "http://www.baidu.com/s?bdorz_come=1&ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=" + encodeKey; return restTemplate.getForObject(url, String.class); } @GetMapping("/baidu2/{key}") public String get2(@PathVariable String key) throws UnsupportedEncodingException { HttpHeaders headers = new HttpHeaders(); headers.set("MyHeaderKey", "MyHeaderValue"); HttpEntity entity = new HttpEntity(headers); String encodeKey = URLEncoder.encode(key, "UTF-8"); String url = "http://www.baidu.com/s?bdorz_come=1&ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=" + encodeKey; ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class); return response.getBody(); }} 5. Post请求演示
@RestControllerpublic class PostTestController { @Resource private RestTemplate restTemplate; @GetMapping("/postForm") public String testPostForm() { String url = ""; MultiValueMap form = new LinkedMultiValueMap<>(); form.add("name", "**"); form.add("age", "**"); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); HttpEntity entity = new HttpEntity(form, headers); String json = restTemplate.postForObject(url, entity, String.class); return json; } @RequestMapping("/postBody") public String testPostBody() { String url = ""; String jsonBody = "{\n" + " \"name\": \"XX\",\n" + " \"age\": \"12\",\n" + " \"sex\": \"man\"\n" + "}\n"; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity entity = new HttpEntity(jsonBody, headers); String json = restTemplate.postForObject(url, entity, String.class); return json; // 如果需要将json转换为Java对象,可以使用restTemplate.postForObject(url, entity, ResultVo.class) }} 6. 文件上传与下载请求演示
@RestControllerpublic class FileTestController { @Resource private RestTemplate restTemplate; @RequestMapping("/postFile") public String testPostFileBody() { String filePath = "D:/config.png"; String url = ""; String appId = ""; String secureKey = ""; String time = String.valueOf(System.currentTimeMillis()); String pubStr = "1"; String tempStr = String.format("app_id=%s&is_public=%s&time=%s&vframe=0%s", appId, pubStr, time, secureKey); MultiValueMap form = new LinkedMultiValueMap<>(); form.add("is_public", pubStr); form.add("vframe", "0"); form.add("file", new FileSystemResource(new File(filePath))); form.add("app_id", appId); form.add("time", time); form.add("sign", DigestUtils.md5(tempStr)); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity entity = new HttpEntity(form, headers); String json = restTemplate.postForObject(url, entity, String.class); return json; } @RequestMapping("/downloadFile") public ResponseEntity testDownloadFile() throws Exception { String url = "http://editor.baidu.com/editor/download/BaiduEditor(Online)_5-9-16.exe"; HttpHeaders headers = new HttpHeaders(); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_OCTET_STREAM)); HttpEntity entity = new HttpEntity(headers); ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, byte[].class); byte[] bytes = response.getBody(); long contentLength = bytes != null ? bytes.length : 0; headers.setContentLength((int) contentLength); headers.setContentDispositionFormData("baidu.exe", URLEncoder.encode("百度安装包.exe", "UTF-8")); return new ResponseEntity<>(response.getBody(), headers, HttpStatus.OK); }} 采坑记录
只配@ConfigurationProperties时,不会自动创建bean
正确姿势:
@Configuration@ConfigurationProperties(prefix = "spring.restTemplate")@ConditionalOnClass(value = {RestTemplate.class, CloseableHttpClient.class})public class RestTemplateConfig {} 错误姿势:
@ConfigurationProperties(prefix = "spring.restTemplate")@ConditionalOnClass(value = {RestTemplate.class, CloseableHttpClient.class})public class RestTemplateConfig {} @ConfigurationProperties无法注入没有setter的属性
RestTemplate默认配置会乱码
正确姿势:
private void modifyDefaultCharset(RestTemplate restTemplate) { List converterList = restTemplate.getMessageConverters(); HttpMessageConverter converterTarget = null; for (HttpMessageConverter item : converterList) { if (StringHttpMessageConverter.class == item.getClass()) { converterTarget = item; break; } } if (null != converterTarget) { converterList.remove(converterTarget); } Charset defaultCharset = Charset.forName(charset); converterList.add(1, new StringHttpMessageConverter(defaultCharset));} 错误姿势:
@Beanpublic RestTemplate getRestTemplate() { RestTemplate rest = new RestTemplate(this.createFactory); return rest;} 如何调试RestTemplate
工程目录
[图片描述]
结束语
有任何建议,欢迎留言探讨。
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2026年06月13日 12时44分01秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
PHP学习笔记一:谁动了你的mail(),PHP?
2023-03-01
PHP安全实战
2023-03-01
php安装扩展
2023-03-01
php实战第二十二天
2023-03-01
rabbitmq重启
2023-03-01
php实现上传(多个)文件函数封装
2023-03-01
php实现下载文件方法
2023-03-01
php实现单链表
2023-03-01
php实现图片背景换色功能
2023-03-01
php实现多个一维数组对应合并成二维数组
2023-03-01
php实现多关键字查找方法
2023-03-01
PHP实现微信公众号H5支付
2023-03-01
PHP实现微信公众号网页授权
2023-03-01
PHP实现微信小程序推送消息至公众号
2023-03-01
rabbitmq逻辑与开发
2023-03-01
php实现根据身份证获取年龄
2023-03-01
PHP实现的MongoDB数据增删改查
2023-03-01
PHP实现的SSO单点登录系统,拿走就用吧
2023-03-01
php实现短信验证功能
2023-03-01