> 文档中心 > RestTemplate通过泛型实现POST、PUT、DELETE、GET、集合请求以及文件上传(可批量文件、可带参数)的统一封装(可打印日志)

RestTemplate通过泛型实现POST、PUT、DELETE、GET、集合请求以及文件上传(可批量文件、可带参数)的统一封装(可打印日志)

目录

  • 1、RestTemplate配置
  • 2、请求体封装
  • 3、GET请求
  • 4、POST请求
  • 5、PUT请求
  • 6、DELETE请求
  • 7、List集合响应请求
  • 8、文件传递请求(可批量文件、可带参数)

1、RestTemplate配置

引入POM:

<dependency>    <groupId>org.apache.httpcomponents</groupId>    <artifactId>httpclient</artifactId>    <version>4.5.13</version></dependency>

RestTemplateLog(请求日志打印) :

import lombok.extern.slf4j.Slf4j;import org.springframework.http.HttpRequest;import org.springframework.http.client.ClientHttpRequestExecution;import org.springframework.http.client.ClientHttpRequestInterceptor;import org.springframework.http.client.ClientHttpResponse;import org.springframework.stereotype.Component;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.nio.charset.StandardCharsets;@Slf4j@Componentpublic class RestTemplateLog implements ClientHttpRequestInterceptor {    @Override    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)     throws IOException { traceRequest(request, body); ClientHttpResponse response = execution.execute(request, body); traceResponse(response); return response;    }    private void traceRequest(HttpRequest request, byte[] body) { String path = request.getURI().getPath(); String header = String.valueOf(request.getHeaders()); String param = new String(body, StandardCharsets.UTF_8); log.info("RestTemplate请求信息:【请求URL:{},请求头:{},请求参数:{}】", path, header, param);    }    private void traceResponse(ClientHttpResponse response) throws IOException { StringBuilder inputStringBuilder = new StringBuilder(); try (BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(response.getBody(), StandardCharsets.UTF_8))) {     String line = bufferedReader.readLine();     while (line != null) {  inputStringBuilder.append(line);  inputStringBuilder.append('\n');  line = bufferedReader.readLine();     } } int status = response.getStatusCode().value(); String body = String.valueOf(inputStringBuilder).trim(); log.info("RestTemplate响应信息:【状态码:{},响应参数:{}】", status, body);    }}

RestTemplateConfig(请求配置):

import org.apache.http.conn.HttpClientConnectionManager;import org.apache.http.impl.client.HttpClientBuilder;import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;import org.springframework.boot.web.client.RestTemplateBuilder;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.http.converter.HttpMessageConverter;import org.springframework.http.converter.StringHttpMessageConverter;import org.springframework.web.client.RestTemplate;import java.nio.charset.StandardCharsets;import java.util.Iterator;import java.util.List;@Configurationpublic class RestTemplateConfig {    @Resource    private RestTemplateLog restTemplateLog;    @Bean    public RestTemplate restTemplate(RestTemplateBuilder builder) { RestTemplate restTemplate = builder.build(); // 添加拦截器 List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>(); interceptors.add(restTemplateLog); restTemplate.setInterceptors(interceptors); restTemplate.setRequestFactory(clientHttpRequestFactory()); // 使用 utf-8 编码集的 conver 替换默认的 conver(默认的 string conver 的编码集为"ISO-8859-1") List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters(); Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator(); while (iterator.hasNext()) {     HttpMessageConverter<?> converter = iterator.next();     if (converter instanceof StringHttpMessageConverter) {  iterator.remove();     } } messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8)); return restTemplate;    }    @Bean    public HttpClientConnectionManager poolingConnectionManager() { PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(); // 连接池最大连接数 poolingConnectionManager.setMaxTotal(10000); // 每个主机的并发 poolingConnectionManager.setDefaultMaxPerRoute(10000); return poolingConnectionManager;    }    @Bean    public HttpClientBuilder httpClientBuilder() { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); //设置HTTP连接管理器 httpClientBuilder.setConnectionManager(poolingConnectionManager()); return httpClientBuilder;    }    @Bean    public ClientHttpRequestFactory clientHttpRequestFactory() { HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(); clientHttpRequestFactory.setHttpClient(httpClientBuilder().build()); // 连接超时,毫秒 clientHttpRequestFactory.setConnectTimeout(6000); // 读写超时,毫秒 clientHttpRequestFactory.setReadTimeout(6000); return clientHttpRequestFactory;    }}

2、请求体封装

通过RestTemplate封装统一的POST、PUT、DELETE、GET,适合返回任意类型的对象,分别为doHttpdoHttpList两个方法,一个方法接收单个对象类型,一个方法接收集合对象;

FileRequestServer:

import org.springframework.core.ParameterizedTypeReference;import org.springframework.http.*;import org.springframework.stereotype.Component;import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.List;import java.util.Map;@Componentpublic class FileRequestServer {    @Resource    private RestTemplate restTemplate;    /     * 默认不带头,并且请求类型为json     *     * @param url     * @param method     * @param obj     * @param tClass 为需要返回的实体类型     * @return     */    public <T> T doHttp(String url, HttpMethod method, Object obj, Class<T> tClass) { return doHttp(url, MediaType.APPLICATION_JSON, null, method, obj, tClass);    }    /     * 默认不带头     *     * @param url     * @param contentType     * @param method     * @param obj     * @param tClass      为需要返回的实体类型     * @return     */    public <T> T doHttp(String url, MediaType contentType, HttpMethod method, Object obj, Class<T> tClass) { return doHttp(url, contentType, null, method, obj, tClass);    }    /     * 默认带头,并且请求类型为json     *     * @param url     * @param headerMap     * @param method     * @param obj     * @param tClass    为需要返回的实体类型     * @return     */    public <T> T doHttp(String url, Map<String, String> headerMap, HttpMethod method, Object obj, Class<T> tClass) { return doHttp(url, null, headerMap, method, obj, tClass);    }    /     * @param url     * @param contentType     * @param headerMap     * @param method     * @param obj     * @param tClass      为需要返回的实体类型     * @return     */    public <T> T doHttp(String url, MediaType contentType, Map<String, String> headerMap, HttpMethod method, Object obj, Class<T> tClass) { HttpHeaders headers = new HttpHeaders(); contentType = contentType == null ? MediaType.APPLICATION_JSON : contentType; headers.setContentType(contentType); if (headerMap != null && headerMap.size() > 0) {     for (Map.Entry<String, String> entry : headerMap.entrySet()) {  headers.add(entry.getKey(), entry.getValue());     } } HttpEntity entity = new HttpEntity(obj, headers); ResponseEntity<T> exchange = restTemplate.exchange(url, method, entity, tClass); return exchange.getBody();    }    /     * 默认不带头,并且请求类型为json,返回List集合对象     *     * @param url     * @param method     * @param obj     * @param tClass     * @return     */    public <T> List<T> doHttpList(String url, HttpMethod method, Object obj, Class<T> tClass) { return doHttpList(url, MediaType.APPLICATION_JSON, null, method, obj, tClass);    }    /     * 默认不带头,返回List集合对象     *     * @param url     * @param contentType     * @param method     * @param obj     * @param tClass      为需要返回的实体类型     * @return     */    public <     T> List<T> doHttpList(String url, MediaType contentType, HttpMethod method, Object obj, Class<T> tClass) { return doHttpList(url, contentType, null, method, obj, tClass);    }    /     * 默认带头,并且请求类型为json,返回List集合对象     *     * @param url     * @param headerMap     * @param method     * @param obj     * @param tClass     * @return     */    public <     T> List<T> doHttpList(String url, Map<String, String> headerMap, HttpMethod method, Object obj, Class<T> tClass) { return doHttpList(url, null, headerMap, method, obj, tClass);    }    /     * 返回List集合对象     *     * @param url     * @param contentType     * @param headerMap     * @param method     * @param obj     * @param tClass      为需要返回的实体类型     * @param      * @return     */    public <     T> List<T> doHttpList(String url, MediaType contentType, Map<String, String> headerMap, HttpMethod method, Object obj, Class<T> tClass) { HttpHeaders headers = new HttpHeaders(); contentType = contentType == null ? MediaType.APPLICATION_JSON : contentType; headers.setContentType(contentType); if (headerMap != null && headerMap.size() > 0) {     for (Map.Entry<String, String> entry : headerMap.entrySet()) {  headers.add(entry.getKey(), entry.getValue());     } } HttpEntity entity = new HttpEntity(obj, headers); ParameterizedTypeReference<List<T>> responseType = new ParameterizedTypeReference<List<T>>() { }; ResponseEntity<List<T>> exchange = restTemplate.exchange(url, method, entity, responseType); // RestTemplate 会将List转为List List<T> list = exchange.getBody(); return mapToEntity(list, tClass);    }    public static <T> List<T> mapToEntity(List<T> body, Class<T> clazz) { List<T> list = new ArrayList<>(); if (body.size() <= 0) {     return list; } List<Map<String, Object>> mapList = new ArrayList<>(); for (T t : body) {     Map<String, Object> map = (Map<String, Object>) t;     mapList.add(map); } try {     Field[] declaredFields = clazz.getDeclaredFields();     for (Map<String, Object> map : mapList) {  T t = clazz.newInstance();  for (Field declaredField : declaredFields) {      declaredField.setAccessible(true);      String name = declaredField.getName();      if (null != map.get(name)) {   declaredField.set(t, map.get(name));      }  }  list.add(t);     } } catch (Exception e) {     throw new RuntimeException("属性设置失败!"); } return list;    }}

3、GET请求

@RestControllerpublic class Controller {@RequestMapping("/test")public String sendThymeleaf() {// 请求URL(有参数就封装)String url = "http://127.0.0.1:9898/other/test2?name=测试&age=123"; // 封装头 Map<String, String> headerMap = new HashMap<>(); headerMap.put("token", "123456"); // 设置响应实体,比如为User,那么传入User.class即可 User user = fileRequestServer.doHttp(url, MediaType.APPLICATION_JSON, headerMap, HttpMethod.GET, null, User.class); System.out.println(user.toString());    }}

4、POST请求

@RestControllerpublic class Controller {@RequestMapping("/test")public String sendThymeleaf() {String url = "http://127.0.0.1:9898/other/test2"; // POST请求时,参数可以为Map对象也可以为具体的实体对象,二选一 Map<String, Object> paramMap = new HashMap<>(); paramMap.put("name", "测试名称"); paramMap.put("gender", "男"); paramMap.put("age", 10);// POST请求时,参数可以为Map对象也可以为具体的实体对象,二选一 // UserParam param= new UserParam (); // param.setName("测试名称"); // param.setgender("男"); // param.setAge(10); // 封装头 Map<String, String> headerMap = new HashMap<>(); headerMap.put("token", "123456"); // 设置响应实体,比如为User,那么传入User.class即可 User user = fileRequestServer.doHttp(url, MediaType.APPLICATION_JSON, headerMap, HttpMethod.POST, paramMap, User.class); System.out.println(user.toString());    }}

5、PUT请求

@RestControllerpublic class Controller {@RequestMapping("/test")public String sendThymeleaf() {String url = "http://127.0.0.1:9898/other/test2"; // PUT请求时,参数可以为Map对象也可以为具体的实体对象,二选一 // Map paramMap = new HashMap(); // paramMap.put("name", "测试名称"); // paramMap.put("gender", "男"); // paramMap.put("age", 10);// PUT请求时,参数可以为Map对象也可以为具体的实体对象,二选一 UserParam param= new UserParam (); param.setName("测试名称"); param.setgender("男"); param.setAge(10); // 封装头 Map<String, String> headerMap = new HashMap<>(); headerMap.put("token", "123456"); // 设置响应实体,比如为User,那么传入User.class即可 User user = fileRequestServer.doHttp(url, MediaType.APPLICATION_JSON, headerMap, HttpMethod.PUT, param, User.class); System.out.println(user.toString());    }}

6、DELETE请求

@RestControllerpublic class Controller {@RequestMapping("/test")public String sendThymeleaf() {// 123456为DELETE请求时的参数,比如:test2/{id}String url = "http://127.0.0.1:9898/other/test2/123456"; // DELETE请求时,如果需要body参数,那么可以为Map对象也可以为具体的实体对象,二选一 // Map paramMap = new HashMap(); // paramMap.put("name", "测试名称"); // paramMap.put("gender", "男"); // paramMap.put("age", 10); // DELETE请求时,如果需要body参数,那么可以为Map对象也可以为具体的实体对象,二选一 // UserParam param= new UserParam (); // param.setName("测试名称"); // param.setgender("男"); // param.setAge(10); // 封装头 Map<String, String> headerMap = new HashMap<>(); headerMap.put("token", "123456"); // 设置响应实体,比如为User,那么传入User.class即可 // DELETE 如果不需要参数,那么obj传入null即可,如果需要body参数就传递响应参数 User user = fileRequestServer.doHttp(url, MediaType.APPLICATION_JSON, headerMap, HttpMethod.PUT, null, User.class); System.out.println(user.toString());    }}

7、List集合响应请求

当返回对象是一个List时,则使用doHttpList()方法;

@RestControllerpublic class Controller {@RequestMapping("/test")public String sendThymeleaf() {// 请求URL(有参数就封装)String url = "http://127.0.0.1:9898/other/test2?name=测试&age=123"; // 封装头 Map<String, String> headerMap = new HashMap<>(); headerMap.put("token", "123456"); // 设置响应实体,比如为User,那么传入User.class即可 List<User> user = fileRequestServer.doHttpList(url, MediaType.APPLICATION_JSON, headerMap, HttpMethod.GET, null, User.class); System.out.println(user.toString());    }}

8、文件传递请求(可批量文件、可带参数)

@RestControllerpublic class Controller {@PostMapping("/test")    public void test(@RequestParam("files") MultipartFile[] file) throws IOException { String url = "http://127.0.0.1:9898/other/test"; // 上传文件 String originalFilename = file.getOriginalFilename(); System.out.println("文件名称:" + originalFilename);MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>(); // 遍历多个MultipartFile对象; for (MultipartFile file : files) {     ByteArrayResource resource = new ByteArrayResource(file.getBytes()) {  @Override  public String getFilename() {      return file.getOriginalFilename();  }     };     // 写入文件流:每遍历一次,就add一次     paramMap.add("files", resource); } // 其他参数 paramMap.add("name", "测试名称"); paramMap.add("age", 10); // 封装头 Map<String, String> headerMap = new HashMap<>(); headerMap.put("token", "12333"); String s = fileRequestServer.doHttp(url, MediaType.MULTIPART_FORM_DATA, headerMap, HttpMethod.POST, paramMap, String.class); System.out.println(s);    }}

被调用方Controller层定义:
如果在传入文件流的同时,还存在参数的话,那么参与需要使用@RequestParam进行定义;

public String test(@RequestParam("files") MultipartFile[] file, @RequestParam String name, @RequestParam Integer age){............}