Http请求-RestTemplate
创始人
2025-05-30 04:55:24
0

文章目录

  • 0. 概述
  • 1. RestTemplate配置
  • 2. GET请求
    • 2.1. getForObject
      • 2.1.1. 带参的get请求(restful风格):
      • 2.1.2. 带参的get请求(使用占位符号传参):
    • 2.2. getForEntity
  • 3. POST请求
    • 3.1. postForObject
      • 3.1.1. 表单请求:
      • 3.1.2. 表单请求(传递对象):
    • 3.2. postForEntity
    • 3.3 postForLocation
  • 4. PUT
  • 5. DELETE
  • 6. EXCHANGE
  • 7. 文件上传
  • 一些其他设置

在这里插入图片描述

0. 概述

RestTemplate是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。

  • getForObject:Retrieves a representation via GET.
  • getForEntity:Retrieves a ResponseEntity (that is, status, headers, and body) by using GET.
  • headForHeaders:Retrieves all headers for a resource by using HEAD.
  • postForLocation:Creates a new resource by using POST and returns the Location header from the response.
  • postForObject:Creates a new resource by using POST and returns the representation from the response.
  • postForEntity:Creates a new resource by using POST and returns the representation from the response.
  • put:Creates or updates a resource by using PUT.
  • delete:Deletes the resources at the specified URI by using DELETE.
  • exchange:More generalized (and less opinionated) version of the preceding methods that provides extra flexibility when needed. It accepts a RequestEntity (including HTTP method, URL, headers, and body as input) and returns a ResponseEntity.
  • execute:The most generalized way to perform a request, with full control over request preparation and response extraction through callback interfaces.

getForObject - delete:提供常规的 Rest API(GET、POST、DELETE 等)方法调用;

exchange:接收一个 RequestEntity 参数,可以自己设置 HTTP method,URL,headers 和 body,返回 ResponseEntity;

execute:通过 callback 接口,可以对请求和返回做更加全面的自定义控制。

一般情况下,我们使用第一组和第二组方法就够了。


1. RestTemplate配置

依赖:

org.springframework.bootspring-boot-starter-web

RestTemplate配置初始化为一个Bean

@Configuration
public class RestTemplateConfig {/*** 没有实例化RestTemplate时,初始化RestTemplate*/@ConditionalOnMissingBean(RestTemplate.class)@Beanpublic RestTemplate restTemplate(){RestTemplate restTemplate = new RestTemplate();return restTemplate;}
}

默认使用了 JDK 自带的HttpURLConnection作为底层 HTTP 客户端实现,可以使用ClientHttpRequestFactory指定不同的 HTTP 连接方式。比如,将其改成HttpClient客户端:

@Configuration
public class RestTemplateConfig {@ConditionalOnMissingBean(RestTemplate.class)@Beanpublic RestTemplate restTemplate(ClientHttpRequestFactory clientHttpRequestFactory){RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);return restTemplate;}/*** 使用HttpClient作为底层客户端* @return*/@Beanpublic ClientHttpRequestFactory clientHttpRequestFactory() {int timeout = 5000;RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout).setConnectionRequestTimeout(timeout).setSocketTimeout(timeout).build();CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();return new HttpComponentsClientHttpRequestFactory(client);}
}

在需要使用RestTemplate的位置,注入并使用即可!

@Autowired
private RestTemplate restTemplate;

从开发人员的反馈,和网上的各种 HTTP 客户端性能以及易用程度评测来看,OkHttp 优于 Apache的HttpClientApache的HttpClient优于HttpURLConnection

因此,我们还可以通过如下方式,将底层的 HTTP 客户端换成OkHttp

/*** 使用OkHttpClient作为底层客户端* @return*/
@Bean
public ClientHttpRequestFactory clientHttpRequestFactory() {OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).writeTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS).build();return new OkHttp3ClientHttpRequestFactory(okHttpClient);
}

如果需要配置http连接管理器,完整配置如下:

@Configuration
public class RestTemplateConfig {/*** http连接管理器* @return*/@Beanpublic HttpClientConnectionManager poolingHttpClientConnectionManager() {/*// 注册http和https请求Registry registry = RegistryBuilder.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*/@Beanpublic HttpClient httpClient(HttpClientConnectionManager poolingHttpClientConnectionManager) {HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();// 设置http连接管理器httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);/*// 设置重试次数httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true));*/// 设置默认请求头/*List
headers = new ArrayList<>();headers.add(new BasicHeader("Connection", "Keep-Alive"));httpClientBuilder.setDefaultHeaders(headers);*/return httpClientBuilder.build();}/*** 请求连接池配置* @param httpClient* @return*/@Beanpublic 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*/@Beanpublic RestTemplate restTemplate(ClientHttpRequestFactory clientHttpRequestFactory) {// boot中可使用RestTemplateBuilder.build创建RestTemplate restTemplate = new RestTemplate();// 配置请求工厂restTemplate.setRequestFactory(clientHttpRequestFactory);return restTemplate;}}

2. GET请求

在这里插入图片描述

  • getForObject():返回值是 HTTP 协议的响应体
  • getForEntity():返回的是ResponseEntityResponseEntity是对 HTTP 响应的封装,除了包含响应体,还包含HTTP状态码contentTypecontentLengthHeader等信息

2.1. getForObject

2.1.1. 带参的get请求(restful风格):

服务端:

@RestController
public class HelloController {@GetMapping("/testGet/{name}/{age}")public ResponseBean testGet(@PathVariable("name") String name, @PathVariable("age") int age){System.out.println("name="+name+",age="+age);ResponseBean response = new ResponseBean();response.setCode("200");response.setMsg("请求成功,方法:testGetByRestFul,请求参数id:" +  name + "、请求参数name:" + age);return response;}
}

响应类:

@Data
public class ResponseBean {private String code;private String msg;
}

请求端:

@RestController
public class TestRestTemplateController {@AutowiredRestTemplate restTemplate;@RequestMapping("/testRestGet1")public void  testRestGet1(){//请求地址String url = "http://localhost:8080/testGet/{1}/{2}";//发起请求,直接返回对象(restful风格)ResponseBean response = restTemplate.getForObject(url, ResponseBean.class, "lili", 23);System.out.println(response);}
}

访问地址:http://192.168.1.166:8080/testRestGet1

在这里插入图片描述

2.1.2. 带参的get请求(使用占位符号传参):

服务端:

@RestController
public class HelloController {@GetMapping("/testGet2")public ResponseBean testGet2(@RequestParam("name") String name, @RequestParam("age") int age){System.out.println("name="+name+",age="+age);ResponseBean response = new ResponseBean();response.setCode("200");response.setMsg("请求成功,方法:testGetByParam,请求参数id:" +  name + "、请求参数name:" + age);return response;}
}

请求端:

@RestController
public class TestRestTemplateController {@AutowiredRestTemplate restTemplate;@RequestMapping("/testRestGet2")public void  testRestGet2(){//请求地址String url = "http://localhost:8080/testGet2?name={name}&age={age}";//请求参数HashMap map = new HashMap<>();map.put("name","lili");map.put("age",25);//发起请求,直接返回对象(带参数请求)ResponseBean responseBean = restTemplate.getForObject(url, ResponseBean.class, map);System.out.println(responseBean.toString());}
}

访问地址:http://192.168.1.166:8080/testRestGet2

在这里插入图片描述

使用name={name}&age={age}这种形式,最后一个参数是一个 map,map 的 key 即为前边占位符的名字,map 的 value 为参数值。

如果你只关注返回的消息体的内容,对其他信息都不关注,此时可以使用getForObject

2.2. getForEntity

上面的所有的getForObject请求传参方法,getForEntity都可以使用,使用方法上也几乎是一致的,只是在返回结果接收的时候略有差别。

getForEntity方法的返回值是一个ResponseEntityResponseEntity是 Spring 对 HTTP 请求响应的封装,包括了几个重要的元素,如响应码、contentType、contentLength、响应消息体等。responseEntity.getBody()获取响应体。

请求端:

@RestController
public class TestRestTemplateController {@AutowiredRestTemplate restTemplate;@RequestMapping("/testRestGet2")public void  testRestGet2(){//请求地址String url = "http://localhost:8080/testGet2?name={name}&age={age}";//请求参数HashMap map = new HashMap<>();map.put("name","lili");map.put("age",25);//发起请求ResponseEntity response = restTemplate.getForEntity(url, ResponseBean.class, map);// 获取响应体System.out.println("HTTP 响应body:[" + response.getBody().toString() + "]");// 以下是getForEntity比getForObject多出来的内容HttpStatus statusCode = response.getStatusCode();int statusCodeValue = response.getStatusCodeValue();HttpHeaders headers = response.getHeaders();System.out.println("HTTP 响应状态:[" + statusCode + "]");System.out.println("HTTP 响应状态码:[" + statusCodeValue + "]");System.out.println("HTTP Headers信息:[" + headers + "]");}
}

访问地址:http://192.168.1.166:8080/testRestGet2

在这里插入图片描述

注1:restTemplate 会根据 params 的具体类型,调用合适的 HttpMessageConvert 将请求参数写到请求体 body 中,并在请求头中添加合适的 content-type;

注2:也会根据 responseType 的类型(本例返回类类型,默认是 application/json),设置 head 中的 accept 字段,当响应返回的时候再调用合适的 HttpMessageConvert 进行响应转换。


3. POST请求

在这里插入图片描述

其实 POST 请求方法和 GET 请求方法上大同小异,RestTemplate 的 POST 请求也包含两个主要方法:

  • postForObject():返回body对象
  • postForEntity():返回全部的信息

3.1. postForObject

3.1.1. 表单请求:

服务端:

@RestController
public class HelloController {@PostMapping("testPost")public ResponseBean testPost(@RequestParam("name") String name,@RequestParam("age") String age){ResponseBean result = new ResponseBean();result.setCode("200");result.setMsg("请求成功,方法:testPostByForm,请求参数name:" + name + ",age:" + age);return result;}
}

请求类:

@Data
public class RequestBean {private String name;private String age;
}

请求端:

@RestController
public class TestRestTemplateController {@AutowiredRestTemplate restTemplate;@RequestMapping("/testRestPost1")public void  testRestPost1(){// 1. 请求地址String url = "http://localhost:8080/testPost";// 2.1 请求头设置,x-www-form-urlencoded格式的数据HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);// 2.2 提交参数设置MultiValueMap map = new LinkedMultiValueMap<>();map.add("name", "唐三藏");map.add("age", "25");// 2.3组装请求体HttpEntity> request = new HttpEntity<>(map, headers);// 3. 发起请求ResponseBean responseBean = restTemplate.postForObject(url, request, ResponseBean.class);System.out.println(responseBean.toString());}
}

访问地址:http://192.168.1.166:8080/testRestPost1

在这里插入图片描述
POST请求报文体需要使用MultiValueMap,不能使用HashMap

3.1.2. 表单请求(传递对象):

服务端:

@RestController
public class HelloController {@PostMapping("testPost2")public ResponseBean testPost2(@RequestBody RequestBean request){ResponseBean result = new ResponseBean();result.setCode("200");result.setMsg("请求成功,方法:testPostByFormAndObj,请求参数:" + request);return result;}
}

请求端:

@RestController
public class TestRestTemplateController {@AutowiredRestTemplate restTemplate;@RequestMapping("/testRestPost2")public void  testRestPost2(){// 1. 请求地址String url = "http://localhost:8080/testPost2";// 2. 入参RequestBean request = new RequestBean();request.setName("唐三藏");request.setAge("23");// 3. 发起请求ResponseBean responseBean = restTemplate.postForObject(url, request, ResponseBean.class);System.out.println(responseBean.toString());}
}

访问地址:http://192.168.1.166:8080/testRestPost2

在这里插入图片描述

3.2. postForEntity

上面的所有的postForObject请求传参方法,postForEntity都可以使用,使用方法上也几乎是一致的,只是在返回结果接收的时候略有差别。

请求端:

@RestController
public class TestRestTemplateController {@AutowiredRestTemplate restTemplate;@RequestMapping("/testRestPost2")public void  testRestPost2(){// 1. 请求地址String url = "http://localhost:8080/testPost2";// 2. 入参RequestBean request = new RequestBean();request.setName("唐三藏");request.setAge("23");// 3. 发起请求ResponseEntity response = restTemplate.postForEntity(url, request, ResponseBean.class);System.out.println("HTTP 响应状态码:[" + response.getBody() + "]");System.out.println("HTTP 响应状态:[" + response.getStatusCode() + "]");System.out.println("HTTP 响应状态码:[" + response.getStatusCodeValue() + "]");System.out.println("HTTP Headers信息:[" + response.getHeaders() + "]");}
}

访问地址:http://192.168.1.166:8080/testRestPost2

在这里插入图片描述

3.3 postForLocation

postForLocation用于页面重定向,postForLocation 的参数和前面两种的参数基本一致,只不过该方法的返回值为 URI ,这个只需要服务提供者返回一个 URI 即可,该 URI 表示新资源的位置。

服务端:

@RestController
public class HelloController {@PostMapping("testPostByLocation")public String testPostByLocation(@RequestBody RequestBean request){return "redirect:index.html";}
}

请求端:

@RestController
public class TestRestTemplateController {@AutowiredRestTemplate restTemplate;@RequestMapping("/testRestLocation")public void  testRestLocation(){// 1. 请求地址String url = "http://localhost:8080/testPostByLocation";// 2. 入参RequestBean request = new RequestBean();request.setName("唐三藏");request.setAge("23");// 3. 用于提交完成数据之后的页面跳转,返回跳转urlURI uri = restTemplate.postForLocation(url, request);System.out.println(uri.toString());}
}

4. PUT

PUT方法的参数和前面介绍的 postForEntity 方法的参数基本一致,只是 put 方法没有返回值而已。它指的是修改一个已经存在的资源或者插入资源,该方法会向URL代表的资源发送一个HTTP PUT方法请求。

在这里插入图片描述

服务端:

@RestController
public class HelloController {/*** 模拟JSON请求,put方法测试*/@PutMapping("testPutByJson")public void testPutByJson(@RequestBody RequestBean request){System.out.println("请求成功,方法:testPutByJson,请求参数:" + request);}
}

请求端:

@RestController
public class TestRestTemplateController {@AutowiredRestTemplate restTemplate;/*** 模拟JSON提交,put请求*/@RequestMapping("/testPutByJson")public void testPutByJson(){//请求地址String url = "http://localhost:8080/testPutByJson";//入参RequestBean request = new RequestBean();request.setName("唐三藏");request.setAge("23");//模拟JSON提交,put请求restTemplate.put(url, request);}
}

5. DELETE

delete方法协议,表示删除一个已经存在的资源,该方法会向URL代表的资源发送一个HTTP DELETE方法请求。

在这里插入图片描述

服务端:

@RestController
public class HelloController {/*** 模拟JSON请求,delete方法测试*/@DeleteMapping("testDeleteByJson")public void testDeleteByJson(){System.out.println("请求成功,方法:testDeleteByJson");}
}

请求端:

@RestController
public class TestRestTemplateController {@AutowiredRestTemplate restTemplate;@RequestMapping("/testDeleteByJson")public void testDeleteByJson(){//请求地址String url = "http://localhost:8080/testDeleteByJson";//模拟JSON提交,delete请求restTemplate.delete(url);}
}

6. EXCHANGE

如果以上方法还不满足你的要求。在RestTemplate工具类里面,还有一个exchange通用协议请求方法,它可以发送GET、POST、DELETE、PUT、OPTIONS、PATCH等 HTTP 方法请求。

  1. 允许调用者指定 HTTP 请求的方法(GET,POST,PUT等)
  2. 可以在请求中增加 body 以及头信息,其内容通过参数RequestEntity requestEntity描述
  3. exchange支持‘含参数的类型’(即泛型类)作为返回类型,该特性通过ParameterizedTypeReferenceresponseType描述

服务端:

@RestController
public class HelloController {@PostMapping("testExchange")public ResponseBean testExchange(@RequestBody RequestBean request){ResponseBean result = new ResponseBean();result.setCode("200");result.setMsg("请求成功,方法:testExchange,请求参数:" + request);return result;}
}

请求端:

@RestController
public class TestRestTemplateController {@AutowiredRestTemplate restTemplate;@RequestMapping("/testExchange")public void testExchange() {UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl("http://localhost:8080").path("/testExchange").build(true);URI uri = uriComponents.toUri();RequestBean request = new RequestBean();request.setName("唐三藏");request.setAge("23");RequestEntity requestEntity = RequestEntity.post(uri).header(HttpHeaders.COOKIE,"key1=value1").accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON).body(request);ResponseEntity responseEntity = restTemplate.exchange(requestEntity, ResponseBean.class);// 响应结果ResponseBean response = responseEntity.getBody();System.out.println("返回报文=" + response);}
}

访问地址:http://192.168.1.166:8080/testExchange

在这里插入图片描述

public ResponseEntity exchange(RequestEntity requestEntity, Class responseType)中,RequestEntity requestEntity包含method,URL,contentType、accept、请求报文体等请求配置,Class responseType指定响应参数类型。


7. 文件上传

参考Spring之RestTemplate详解,懒得写了。


一些其他设置

1. 拦截器配置
RestTemplate 也可以设置拦截器做一些统一处理。这个功能感觉和 Spring MVC 的拦截器类似。配置也很简单:

class MyInterceptor implements ClientHttpRequestInterceptor{@Overridepublic ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {logger.info("enter interceptor...");return execution.execute(request,body);}}
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {RestTemplate restTemplate = new RestTemplate(factory);MyInterceptor myInterceptor = new MyInterceptor();List list = new ArrayList<>();list.add(myInterceptor);restTemplate.setInterceptors(list);return restTemplate;
}

2. ErrorHandler 配置
3. HttpMessageConverter
配置 RestTemplate 也可以配置 HttpMessageConverter,配置的原理和 Spring MVC 中类似。

引用:
Spring之RestTemplate详解

相关内容

热门资讯

特朗普:泽连斯基必须同意美国支... △美国总统特朗普(资料图) 当地时间21日,美国总统特朗普在白宫接受媒体采访时表示,乌克兰总统泽连斯...
库里空砍38分杨瀚森DNP N... 【搜狐体育战报】北京时间11月22日,2025-26赛季NBA常规赛继续进行,波特兰开拓者客场挑战金...
评论丨“劫囚大嫂”不是传奇,而... 当我们为“复仇爽文”“黑道传奇”拍手叫好时,是否也在默许对法律的轻蔑、对暴力的暧昧、对他人隐私的消费...
原创 2... 云南曲靖村民吴某为给次女办理落户上学,2015年被迫与村委会签订协议,2017年缴纳2万元“计划生育...
台当局宣布全面解禁日本食品进口... 【文/观察者网 齐倩】 日本首相高市早苗炒作“台湾有事”论调,导致中日关系恶化。中方已宣布暂停进口...
惠城区开展第九期“法律明白人”... 为深入推进基层依法治理,提升物业服务规范化水平,日前,惠城区司法局在龙丰司法所组织开展了第九期“法律...
荷兰驻华大使:暂停安世行政令后... 荷兰驻华大使昊使博在2025第十届中国全球智库创新年会上发言。 摄影/江玮 昊使博强调,行政令不是针...
原创 中... 据中国青年报报道,近日,中国四艘海警船编队进入钓鱼岛海域进行常规巡航,依照既定的维权程序,船队在海域...
原创 特... 2025年11月9日,美国总统特朗普在自己的社交平台TruthSocial上宣布,他提名约翰·科尔担...