RestTemplate是Spring框架提供的一个工具类,用于进行网络请求。通过RestTemplate,可以简化开发,提高开发效率,避免重复造轮子等。本文将介绍RestTemplate的常见用法,包括GET和POST请求、文件上传、以及常用配置。
RestTemplate简单使用
创建RestTemplate
使用RestTemplate需要创建一个RestTemplate对象。下面的代码展示了如何创建一个RestTemplate对象:
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
return restTemplate;
}
/**
* 可以通过 ClientHttpRequestFactory 配置最大链接数,
* 忽略SSL证书等,可以根据具体开发需求进行配置。
*/
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);
factory.setConnectTimeout(15000);
// 设置代理
//factory.setProxy(null);
return factory;
}
}
接口调用
Get请求
RestTemplate提供了两种发送HTTP GET请求的方法:getForObject()和getForEntity()。其中,getForObject()返回值是HTTP协议的响应体,而getForEntity()返回的是ResponseEntity,ResponseEntity是对HTTP响应的封装,除了包含响应体,还包含HTTP状态码、contentType、contentLength、Header等信息。下面的代码展示了如何发送HTTP GET请求:
public void getTest() {
// 1. 简单参数拼接
long id = 1L;
String result1 = restTemplate.getForObject("http://localhost:8000/req?id=" + id, String.class);
// 2. 通过占位符
String url = "http://127.0.0.1:8080/hello/get/{class}/sex/{sex}";
Map<String, String> vars = Collections.singletonMap("三年二班", "男");
// 返回数组
String[] result2 = restTemplate.getForObject(url, String[].class, vars);
// 带头部的get请求
String requestParam = "三年二班";
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl("127.0.0.1:8080").
path("/class").build(true);
URI uri = uriComponents.toUri();
RequestEntity<JSONObject> requestEntity = RequestEntity.post(uri)
// 添加 cookie
.header(HttpHeaders.COOKIE, "key1=value1")
// 添加 header
.header(("MyRequestHeader", "MyValue")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.body(requestParam);
ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(requestEntity, JSONObject.class);
JSONObject responseEntityBody = responseEntity.getBody();
}
Post请求
RestTemplate的POST请求包含两个主要方法:postForObject()和postForEntity()。这两个方法的主要区别在于,postForObject()返回HTTP协议的响应体,而postForEntity()返回的是ResponseEntity。ResponseEntity是对HTTP响应的封装,除了包含响应体外,还包含HTTP状态码、contentType、contentLength、Header等信息。
public void sendPostRequest1() {
// 请求地址
String url = "http://127.0.0.1:8080/hello";
// 要发送的数据对象
ClassInfo classInfo = new ClassInfo();
classInfo.setClassName("三年二班");
classInfo.setSex("男");
// 发送post请求,并输出结果
ResponseEntity<Result<String>> responseEntity = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(classInfo), new ParameterizedTypeReference<Result<String>>() {});
Result<String> result = responseEntity.getBody();
String body = result.getData();
}
private void sendPostRequest2() {
// 发送post请求,x-www-form-urlencoded格式的数据
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("class", "三年二班");
map.add("sex", "男");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
// 发送post请求
String result2 = restTemplate.postForObject(url, request, String.class);
}
RestTemplate发送/下载文件
上传文件
public String fileUpload(String url, File value) {
String uploadUrl = "http://localhost:8888/hello/m3";
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
// 创建MultiValueMap对象,用于设置请求体的参数
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
// 添加文件对象
parts.add("file", new FileSystemResource(value));
// 创建HttpEntity对象,用于设置请求体和请求头
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);
return restTemplate.postForObject(uploadUrl, requestEntity, String.class);
}
下载文件
public void download(String fileName, HttpServletResponse httpResponse) throws IOException {
String downloadUrl = "http://localhost:8888/hello/m3";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
ResponseEntity<byte[]> response = restTemplate.exchange(downloadUrl, HttpMethod.GET,
new HttpEntity<>(headers), byte[].class);
byte[] fileBytes = response.getBody();
httpResponse.setHeader("Content-Disposition", "attachment; filename=" + "file.txt");
httpResponse.getOutputStream().write(fileBytes);
}
其他
拦截器
定义了一个CustomClientHttpRequestInterceptor类,它实现了ClientHttpRequestInterceptor接口,这个接口定义了一个intercept方法,该方法在每个HTTP请求发送前都会被调用。
public class CustomClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
// 添加自定义的逻辑
HttpHeaders headers = request.getHeaders();
headers.add("Authorization", "Bearer your-access-token");
return execution.execute(request, body);
}
}
public class CustomRestTemplate extends RestTemplate {
public CustomRestTemplate() {
List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
interceptors.add(new CustomClientHttpRequestInterceptor());
setInterceptors(interceptors);
}
}
接下来,我们定义了一个CustomRestTemplate类,它扩展了RestTemplate类。在CustomRestTemplate的构造函数中,我们将CustomClientHttpRequestInterceptor添加到了RestTemplate的拦截器列表中。
现在,我们可以使用CustomRestTemplate来发送HTTP请求,它会自动将我们定义的拦截器应用到所有的HTTP请求中:
CustomRestTemplate restTemplate = new CustomRestTemplate();
String response = restTemplate.getForObject("https://api.example.com/resource", String.class);
在上面的例子中,我们使用CustomRestTemplate来发送GET请求。由于我们已经添加了一个拦截器,所以在请求发送之前,CustomClientHttpRequestInterceptor的intercept方法会被调用,我们的自定义逻辑也会被执行。
**ErrorHandler **
在使用RestTemplate发送HTTP请求时,有时我们可能需要处理一些异常情况,例如请求超时、连接失败等。为了处理这些异常,RestTemplate提供了一个ErrorHandler接口,可以让我们自定义异常处理逻辑。
ErrorHandler接口定义了两个方法:hasError和handleError。hasError方法用于判断HTTP响应是否包含错误信息,而handleError方法则用于处理异常情况。以下是一个简单的例子,演示了如何在RestTemplate中使用ErrorHandler:
public class CustomResponseErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return response.getStatusCode().is4xxClientError()
|| response.getStatusCode().is5xxServerError();
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
if (response.getStatusCode().is4xxClientError()) {
// 处理4xx错误
throw new HttpClientErrorException(response.getStatusCode());
} else if (response.getStatusCode().is5xxServerError()) {
// 处理5xx错误
throw new HttpServerErrorException(response.getStatusCode());
}
}
}
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new CustomResponseErrorHandler());
String response = restTemplate.getForObject("https://api.example.com/resource", String.class);
在上面的例子中,我们定义了一个CustomResponseErrorHandler类,它实现了ResponseErrorHandler接口。在CustomResponseErrorHandler的hasError方法中,我们判断HTTP响应是否包含错误信息。在这个例子中,我们只处理4xx和5xx的错误。如果HTTP响应包含错误信息,hasError方法会返回true,否则返回false。
在CustomResponseErrorHandler的handleError方法中,我们处理异常情况。在这个例子中,我们只是抛出了一个HttpClientErrorException或HttpServerErrorException异常,以便让调用者可以处理异常。
最后,我们将CustomResponseErrorHandler添加到RestTemplate的errorHandler属性中。这样,当RestTemplate发生异常时,它会自动调用CustomResponseErrorHandler的hasError和handleError方法来处理异常。