SpringBoot中的RestTemplate使用笔记

SpringBoot中的RestTemplate使用笔记

为了方便使用,这里我封装成一个工具类来静态调用RestTemplate

以下代码是基于SpringBoot2.4.2版本写的案例

需要配置的application.yml如下

server:
  port: 7024
  servlet:
    context-path: /demo
    session:
      timeout: 30m  #默认会话过期时间30分钟
    encoding:
      enabled: true
      charset: UTF-8
      force: true
  tomcat:
    uri-encoding: UTF-8

spring:
  servlet:
    multipart:
      max-file-size: 50MB  #单个文件的最大上限
      max-request-size: 200MB  #单个请求的文件总大小限制
      location: ${user.home}/.${spring.application.name}/tempDir
  application:
    name: demo
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
logging:
  file:
    #最终的存储路径是:  系统用户目录/.应用名称/logs/端口号/spring.log
    path: ${user.home}/.${spring.application.name}/logs/${server.port}
  logback:
    rollingpolicy:
      max-file-size: 1MB
      max-history: 7
  pattern:
    console: "%date  %clr(%level) [${PID}]  [%thread] [%magenta(%X{traceId})] %cyan(%logger{10}) [%file : %line] %msg%n"
    file: "%date %level [${PID}]   [%thread] [%X{traceId}] %logger{10} [%file : %line] %msg%n"

RestTemplateUtil工具类

package cn.test.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class RestTemplateUtil {
    public RestTemplateUtil() {
    }

    private static RestTemplate template;

    static {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        //http 读超时5s
        factory.setReadTimeout(5000);
        //http 连接超时5s
        factory.setConnectTimeout(5000);
        template = new RestTemplate(factory);
        List<ClientHttpRequestInterceptor> interceptorList = new ArrayList<>();
        interceptorList.add(new RestTemplateLogging());
        template.setInterceptors(interceptorList);
    }

    /**
     * get请求-无参数
     *
     * @param url          请求url,如http://localhost:7024/demo/lic/getCheckInfo
     * @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class
     * @return T 返回对象 如String/ Map /Resp/Result
     * 

* 例: * String s = RestTemplateUtil.doHttpGet( * "http://localhost:7024/demo/lic/getCheckInfo", * String.class); */ public static <T> T doSimpleHttpGet(String url, Class<T> responseType, Map<String, String> reqHeaderMap) { return doGetHttp(url, responseType, new HashMap<>(), reqHeaderMap); } /** * get请求-可替换参数url * * @param replaceUrl 可替换参数url 如http://localhost:7024/demo/t2/{v1}/{v2} * @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class * @param urlPathVars 要替换的参数项 ,类型可以是字符串或数字 * @return T 返回对象 如String/ Map /Resp/Result *

* 例: * Map s1 = RestTemplateUtil.doGetHttpPathVar( * "http://localhost:7024/demo/t2/{v1}/{v2}", * Map.class, * "v1wer", "v2r23r"); */ public static <T> T doGetHttpPathVar(String replaceUrl, Class<T> responseType, Object... urlPathVars) { return template.getForObject(replaceUrl, responseType, urlPathVars); } /** * get请求-url为QueryString形式 * * @param qsUrl 请求url,如 http://localhost:7024/demo/t3?a={a}&b={b} * @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class * @param queryStringMap {a=e12, b=r23r} * @return T 返回对象 如String/ Map /Resp/Result */ public static <T> T doGetHttpQueryString(String qsUrl, Class<T> responseType, Map<String, String> queryStringMap, Map<String, String> reqHeaderMap) { if (queryStringMap == null) { queryStringMap = new HashMap<>(); } return doGetHttp(qsUrl, responseType, queryStringMap, reqHeaderMap); } private static <T> T doGetHttp(String qsUrl, Class<T> responseType, Map<String, String> queryStringMap, Map<String, String> reqHeaderMap) { HttpHeaders httpHeaders = new HttpHeaders(); if (reqHeaderMap != null && !reqHeaderMap.isEmpty()) { for (String s : reqHeaderMap.keySet()) { httpHeaders.add(s, reqHeaderMap.get(s)); } } HttpEntity<String> httpEntity = new HttpEntity<>(null, httpHeaders); ResponseEntity<T> tResponseEntity = template.exchange( qsUrl, HttpMethod.GET, httpEntity, responseType, queryStringMap); return tResponseEntity.getBody(); } /** * post-body-json 形式的请求 * * @param url 请求url,如 http://localhost:7024/demo/t5 * @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class * @param reqJson json字符串 如: {"macAddress":"8C:EC:4B:55:0E:EC","version":"v2123rt"} * @param reqHeaderMap 可选的请求头 * @return T 返回对象 如String/ Map /Resp/Result */ public static <T> T doPostHttpJsonBody(String url, Class<T> responseType, String reqJson, Map<String, String> reqHeaderMap) { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); if (reqHeaderMap != null && !reqHeaderMap.isEmpty()) { for (String s : reqHeaderMap.keySet()) { httpHeaders.add(s, reqHeaderMap.get(s)); } } HttpEntity<String> httpEntity = new HttpEntity<>(reqJson, httpHeaders); return template.postForObject(url, httpEntity, responseType); } /** * post-formData 形式的请求 * * @param url 请求url,如 http://localhost:7024/demo/t4 * @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class * @param formDataMap {a=e12, b=r23r,c=123,d=true} * @param reqHeaderMap 可选的请求头 * @return T 返回对象 如String/ Map /Resp/Result */ public static <T> T doPostHttpFormData(String url, Class<T> responseType, Map<String, Object> formDataMap, Map<String, String> reqHeaderMap) { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); //可选的请求头 if (reqHeaderMap != null && !reqHeaderMap.isEmpty()) { for (String s : reqHeaderMap.keySet()) { httpHeaders.add(s, reqHeaderMap.get(s)); } } //构建填充formData MultiValueMap<String, Object> formDataParam = new LinkedMultiValueMap<>(); if (formDataMap != null && !formDataMap.isEmpty()) { for (String key : formDataMap.keySet()) { formDataParam.add(key, formDataMap.get(key)); } } HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(formDataParam, httpHeaders); return template.postForObject(url, httpEntity, responseType); } /** * post-上传MultipartFile文件 * * @param url 请求url,如 http://localhost:7024/demo/t6 * @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class * @param file java File 对象 * @param reqHeaderMap 可选的请求头 * @return T 返回对象 如String/ Map /Resp/Result */ public static <T> T doPostHttpUploadFile(String url, Class<T> responseType, File file, Map<String, String> reqHeaderMap) { Map<String, Object> formDataMap = new HashMap<>(); //支持传输 MultipartFile formDataMap.put("file", new FileSystemResource(file)); return doPostHttpFormData(url, responseType, formDataMap, reqHeaderMap); } /** * post-body-binary 二进制流 上传 * @param url 请求url,如 http://localhost:7024/demo/t62 * @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class * @param file java File 对象 * @return T 返回对象 如String/ Map /Resp/Result * @throws IOException */ public static <T> T doPostHttpBinaryStream(String url, Class<T> responseType, File file) throws IOException { HttpHeaders httpHeaders = new HttpHeaders(); //固定请求头 httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); httpHeaders.add("Content-Disposition", file.getName()); //file转byte[] 字节流 String absolutePath = file.getAbsolutePath(); Path path = Paths.get(absolutePath); byte[] bytes = Files.readAllBytes(path); HttpEntity<byte[]> httpEntity = new HttpEntity<>(bytes, httpHeaders); return template.postForObject(url, httpEntity, responseType); } /** * put请求,常用于 更新(修改)已存在的数据 * * @param url 请求url,如 http://localhost:7024/demo/t7 * @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class * @param reqJson 实际开发中put请求一般传json参数,json里要有唯一键如id * @return T 返回对象 如String/ Map /Resp/Result */ public static <T> T doSimplePutJson(String url, Class<T> responseType, String reqJson) { return doPutJsonHttp(url, responseType, reqJson, null); } public static <T> T doPutJsonHttp(String url, Class<T> responseType, String reqJson, Map<String, String> reqHeaderMap) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); if (reqHeaderMap != null && !reqHeaderMap.isEmpty()) { for (String s : reqHeaderMap.keySet()) { headers.add(s, reqHeaderMap.get(s)); } } ResponseEntity<T> tResponseEntity = template.exchange( url, HttpMethod.PUT, new HttpEntity<>(reqJson, headers), responseType, new HashMap<>()); return tResponseEntity.getBody(); } /** * DELETE--单个删除请求 * * @param url 可替换参数url 如http://localhost:7024/demo/t8/{id} * @param oneUrlPathVar 对应id值 */ public static void doDeleteHttpOnePathVar(String url, Object oneUrlPathVar) { template.delete(url, oneUrlPathVar); } /** * DELETE--动态条件删除请求 * * @param url 请求url,如 http://localhost:7024/demo/t9?a={a}&b={b} * @param queryStringMap {a=e12, b=r23r} */ public static void doDeleteWhereHttp(String url, Map<String, String> queryStringMap) { template.delete(url, queryStringMap); } /** * DELETE--批量删除请求 * * @param url 请求url,如 http://localhost:7024/demo/t10 * @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class * @param reqJson 传json参数,json里要有唯一键数组如 {"ids":[1,2,3],"remark":"r23r","ts":1351311410} * @param reqHeaderMap 可选的请求头 * @return T 返回对象 如String/ Map /Resp/Result */ public static <T> T doDeleteBatchByJson(String url, Class<T> responseType, String reqJson, Map<String, String> reqHeaderMap) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); if (reqHeaderMap != null && !reqHeaderMap.isEmpty()) { for (String s : reqHeaderMap.keySet()) { headers.add(s, reqHeaderMap.get(s)); } } ResponseEntity<T> exchange = template.exchange( url, HttpMethod.DELETE, new HttpEntity<>(reqJson, headers), responseType, new HashMap<>()); return exchange.getBody(); } }

restTemplate日志拦截器

package cn.test.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpRequest;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Slf4j
public class RestTemplateLogging implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest request,
                                        byte[] body,
                                        ClientHttpRequestExecution execution) throws IOException {
        log.info("req method:{},url:{}", request.getMethod(),request.getURI());
        log.info("req headers:{}", request.getHeaders());
        if (MediaType.APPLICATION_JSON.equals(request.getHeaders().getContentType())) {
            log.info("req body:{}", new String(body, StandardCharsets.UTF_8));
        }

        ClientHttpResponse response = execution.execute(request, body);
        log.info("resp statCode:{}", response.getStatusCode());
        log.info("resp headers:{}", response.getHeaders());

        return response;
    }
}

测试效果

定义一些API接口

package cn.test.web;

import cn.hutool.core.io.IoUtil;
import cn.test.lic.bean.CheckInfo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

@RestController
public class TestController {

    /**
     * 含请求头参数的url ,必须用@RequestHeader 接收请求头
     *
     * @param upk
     * @return
     */
    @GetMapping("/t1")
    public String t1(@RequestHeader("upk") String upk) {
        System.err.println(upk);
        return "ewr21r12r";
    }


    /**
     * url路径变量 形式的http请求,必须用@PathVariable接收
     *
     * @param v1
     * @param v2
     * @return
     */
    @GetMapping("/t2/{v1}/{v2}")
    public TestResp t2(@PathVariable("v1") String v1,
                       @PathVariable("v2") String v2) {
        TestResp build = TestResp.builder()
                .v1(v1)
                .v2(v2)
                .build();
        //{"v1":"re","v2":"r23r"}
        return build;
    }

    /**
     * queryString形式的get查询
     * http://localhost:7024/demo/t3?a=e12&b=r23r
     *
     * @param a
     * @param b
     * @return
     */
    @GetMapping("/t3")
    public TestResp t3(@RequestParam String a,
                       @RequestParam String b) {
        TestResp build = TestResp.builder()
                .v1(a)
                .v2(b)
                .build();
        return build;
    }


    /**
     * post-formData 形式的请求
     *
     * @param a post-form参数
     * @param b post-form参数
     * @return
     */
    @PostMapping("/t4")
    public TestResp t4(@RequestParam String a,
                       @RequestParam String b,
                       int c,
                       boolean d) {
        TestResp build = TestResp.builder()
                .v1(a)
                .v2(b).c(c).d(d)
                .build();
        return build;
    }


    /**
     * post-body-json 形式的请求
     *
     * @param checkInfo post-body-json参数
     * @return
     */
    @PostMapping("/t5")
    public CheckInfo t5(@RequestBody CheckInfo checkInfo) {
        return checkInfo;
    }


    /**
     * 文件上传------MultipartFile方式,本质还是formData 形式的请求
     *
     * @param file
     * @param upk
     * @return
     * @throws IOException
     */
    @PostMapping("/t6")
    public String t6(@RequestPart("file") MultipartFile file,
                     @RequestHeader("upk") String upk) throws IOException {
        System.out.println("upk:" + upk);
        if (!file.isEmpty()) {
            System.out.println(file.getName());
            System.out.println(file.getOriginalFilename());
            File file1 = new File("D:\\test7025\\" + file.getOriginalFilename());
            file1.delete();
            file.transferTo(file1);
        }
        return "ok!";
    }


    /**
     * post-body-binary 二进制流 上传 ,需要请求方声明固定的ContentType=application/octet-stream
     *
     * @param request
     * @param name
     * @return
     * @throws Exception
     */
    @PostMapping("/t62")
    public TestResp t62(HttpServletRequest request,
                        @RequestHeader("Content-Disposition") String name) throws Exception {
        System.out.println(name);
        ServletInputStream inputStream = request.getInputStream();
        File file1 = new File("D:\\test7025\\" + name);
        if (!file1.exists()) {
            file1.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(file1);
        IoUtil.copy(inputStream, fos);
        IoUtil.closeIfPosible(inputStream);
        IoUtil.closeIfPosible(fos);

        TestResp build = TestResp.builder()
                .v1("f3rtf23t")
                .v2("bsft23gf3g2")
                .build();

        return build;
    }


    /**
     * put +传json 的请求, 常用于修改某个数据
     *
     * @param req TestReq ,一般要规定json里的唯一键必填,如id
     * @return TestReq
     */
    @PutMapping("/t7")
    public TestReq t7(@RequestBody @Validated TestReq req) {
        System.out.println(req);
        return req;
    }

    /**
     * Delete请求
     * restful形式 删除单条数据,一般传数字id
     *
     * @param id
     */
    @DeleteMapping("/t8/{id}")
    public void t8(@PathVariable("id") Long id) {
        System.err.println(id);
    }

    /**
     * Delete请求
     * 按多个条件删除数据,条件一般要必填
     *
     * @param a
     * @param b
     */
    @DeleteMapping("/t9")
    public void t9(@RequestParam String a,
                   @RequestParam String b) {
        System.err.println(a);
        System.err.println(b);
    }

    /**
     * Delete请求
     * 批量删除数据,一般至少要提供ids数组
     *
     * @param req json里ids数组必填
     * @return
     */
    @DeleteMapping("/t10")
    public Test2Req t10(@RequestBody Test2Req req) {
        System.err.println(req);
        return req;
    }

}


package cn.test.web;

import lombok.Data;

@Data
public class Test2Req {
    private Long[] ids;
    private String remark;
}

package cn.test.web;

import lombok.Data;

import javax.validation.constraints.NotNull;

@Data
public class TestReq {
    @NotNull
    private Long id;
    private String name;
    private String remark;
}

package cn.test.web;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TestResp {
    private String v1;
    private String v2;

    private int c;
    private boolean d;
}

测试使用RestTemplateUtil

package cn.test;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.test.lic.api.CheckInfoResp;
import cn.test.lic.api.ResultVO;
import cn.test.util.JacksonUtil;
import cn.test.util.RestTemplateUtil;
import cn.test.web.Test2Req;
import cn.test.web.TestReq;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@SpringBootTest
public class LicClientDemoAppTests {

    @Test
    void test1() throws IOException {
        HashMap<String, String> reqHeaderMap = new HashMap<>();
        reqHeaderMap.put("upk","ryju56u");
        System.err.println("----=-=-=--------------===");


        String s = RestTemplateUtil.doSimpleHttpGet(
                "http://localhost:7024/demo/t1",
                String.class,reqHeaderMap);
        System.out.println(s);

        System.err.println("----=-=-=--------------===");


        ResultVO resultVO = RestTemplateUtil.doSimpleHttpGet(
                "http://localhost:7024/demo/lic/getCheckInfo",
                ResultVO.class,reqHeaderMap);
        CheckInfoResp content = Convert.convert(CheckInfoResp.class,resultVO.getContent());
        System.out.println(content);
        System.err.println("----=-=-=--------------===");


        Map s1 = RestTemplateUtil.doGetHttpPathVar(
                "http://localhost:7024/demo/t2/{v1}/{v2}",
                Map.class,
                "v1wer", "v2r23r");
        System.out.println(s1);

        System.err.println("----=-=-=--------------===");


        HashMap<String, String> sspMap = new HashMap<>();
        sspMap.put("a","r23r");
        sspMap.put("b","wer23r");
        String m1 = RestTemplateUtil.doGetHttpQueryString(
                "http://localhost:7024/demo/t3?a={a}&b={b}",
                String.class,
                sspMap,reqHeaderMap);
        System.out.println(m1);

        System.err.println("----=-=-=--------------===");


        HashMap<String, Object> reqMap = new HashMap<>();
        reqMap.put("version","v2123rt");
        reqMap.put("macAddress","8C:EC:4B:55:0E:EC");
        String json = JacksonUtil.obj2String(reqMap);
        String t = RestTemplateUtil.doPostHttpJsonBody(
                "http://localhost:7024/demo/t5",
                String.class, json,null);
        System.out.println(t);

        System.err.println("----=-=-=--------------===");

        HashMap<String, Object> formDataReq = new HashMap<>();
        formDataReq.put("a","v2123rt");
        formDataReq.put("b","8C:EC:4B:55:0E:EC");
        formDataReq.put("c",123);
        formDataReq.put("d",true);
        String s2 = RestTemplateUtil.doPostHttpFormData(
                "http://localhost:7024/demo/t4",
                String.class,
                formDataReq, null);
        System.out.println(s2);

        System.err.println("----=-=-=--------------===");



        //formData文件上传
        String s3 = RestTemplateUtil.doPostHttpUploadFile(
                "http://localhost:7024/demo/t6",
                String.class,
                new File("E:\\lay2023\\vitevue2023-know-wiki-frontend.rar"),
                reqHeaderMap);
        System.out.println(s3);

        System.err.println("----=-=-=--------------===");

        //body-binary二进制流上传
        String s325 = RestTemplateUtil.doPostHttpBinaryStream(
                "http://localhost:7024/demo/t62",
                String.class,
                new File("E:\\lay2023\\vitevue2023-know-wiki-frontend.rar")
                );
        System.err.println(s325);

        System.err.println("----=-=-=--------------===");

        TestReq req = new TestReq();
        req.setId(123L);
        req.setName("ert23t");
        req.setRemark("dhg3t4te");
        String s4 = RestTemplateUtil.doSimplePutJson("http://localhost:7024/demo/t7",
                String.class, JacksonUtil.obj2String(req));
        System.err.println(s4);

        System.err.println("----=-=-=--------------===");

        RestTemplateUtil.doDeleteHttpOnePathVar(
                "http://localhost:7024/demo/t8/{id}",
                321);

        System.err.println("----=-=-=--------------===");


        RestTemplateUtil.doDeleteWhereHttp(
                "http://localhost:7024/demo/t9?a={a}&b={b}",
                sspMap);
        System.err.println("----=-=-=--------------===");

        Test2Req req2 = new Test2Req();
        Long[] ids = {321L,341L};
        req2.setIds(ids);
        req2.setRemark("dhg3t4te");
        String s5 = RestTemplateUtil.doDeleteBatchByJson(
                "http://localhost:7024/demo/t10",
                String.class,
                JacksonUtil.obj2String(req2),
                null);
        System.out.println(s5);

    }


}

你可能感兴趣的:(JavaWeb笔记,SpringBoot技术笔记,spring,boot,笔记,后端,restTemplate,java)