当前位置: 首页 > article >正文

【springboot应用-RestTemplate】

简介

RestTemplate 提供了一个高层次的抽象来访问 HTTP 资源,支持通过模板方法执行常见的 HTTP 请求操作,如 GET、POST、PUT、DELETE 等。它简化了与 HTTP 服务的交互,使得代码更简洁、易读。

功能特点

  • 多种请求方式:支持 GET、POST、PUT、DELETE 等多种 HTTP 方法。
  • 连接管理:内部使用连接池来管理 HTTP 连接,提高性能。
  • 错误处理:提供了异常处理机制,方便错误管理。
  • 消息转换:支持多种消息转换方式,如 JSON、XML 等。
  • 模板方法:提供了模板方法来简化请求参数的设置。

使用步骤

  1. 添加依赖
    如果您使用的是 Maven,确保在 pom.xml 文件中添加了 Spring Web 依赖:
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.3.10</version>
</dependency>
  1. 创建 RestTemplate 实例
@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}
  1. 执行 GET 请求
    使用 RestTemplate 发送 GET 请求并接收响应:
String url = "http://example.com/api/data";
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
String responseBody = response.getBody();
  1. 执行 POST 请求
    发送一个包含请求体的 POST 请求:
MyRequestData data = new MyRequestData();
data.setName("lixiaoyi");
ResponseEntity<MyResponseData> response = restTemplate.postForEntity(url, data, MyResponseData.class);
MyResponseData responseBody = response.getBody();
  1. 配置请求
    可以配置 RestTemplate 以自定义连接工厂、消息转换器等:
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5000);
factory.setReadTimeout(5000);
restTemplate.setRequestFactory(factory);
  1. 异常处理
    RestTemplate 可能会抛出 RestClientException,您可以捕获并处理这个异常:
try {
    restTemplate.getForObject(url, String.class);
} catch (RestClientException e) {
    // 处理异常
}

注意事项

  • 异常处理:RestTemplate 抛出的异常应该被捕获并适当处理。
  • 线程安全:RestTemplate 是线程安全的,可以在多个线程中使用同一个实例。
  • 响应类型:在定义响应类型时,确保与返回的数据类型匹配。

实战项目

封装请求工具类

  • RestUtil
/**
     * RestAPI 调用器
     */
    private final static RestTemplate RT;

    static {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(30000);
        requestFactory.setReadTimeout(4000000);
        RT = new RestTemplate(requestFactory);
        // 解决乱码问题
        RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        // 新增个性化日志
        List<ClientHttpRequestInterceptor> interceptors = Optional.ofNullable(RT.getInterceptors()).orElse(new ArrayList<>());
        RestTemplateLogInterceptor restTemplateLogInterceptor = SpringContextUtils.getBean(RestTemplateLogInterceptor.class);
        interceptors.add(restTemplateLogInterceptor);
        RT.setInterceptors(interceptors);
    }

    public static RestTemplate getRestTemplate() {
        return RT;
    }
    
 	public static <T> ResponseEntity<T> request(String url, HttpMethod method, HttpHeaders headers, JSONObject variables, JSONObject params, Class<T> responseType) {
        if (StringUtils.isEmpty(url)) {
            throw new RuntimeException("url 不能为空");
        }
        if (method == null) {
            throw new RuntimeException("method 不能为空");
        }
        if (headers == null) {
            headers = new HttpHeaders();
        }
        // 请求体
        String body = "";
        if (params != null) {
            body = JSONArray.toJSONString(params, SerializerFeature.WriteMapNullValue);
        }
        // 拼接 url 参数
        if (variables != null) {
            url += ("?" + asUrlVariables(variables));
        }
        // 发送请求
        HttpEntity<String> request = new HttpEntity<>(body, headers);
        return RT.exchange(url, method, request, responseType);
    }
  • RestTemplateLogInterceptor 定义的抽象接口,实现交给各个业务模块
/**
 * @author: lixiaoyi
 * @date: 2024年10月20日20:09:03
 * @description: 记录restTemplate日志 , 实现交给各个模块
 */
public interface RestTemplateLogInterceptor extends ClientHttpRequestInterceptor {
}

  • LoggingInterceptor 日志实现
@Component
public class LoggingInterceptor implements RestTemplateLogInterceptor {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        ClientHttpResponse response = execution.execute(request, body);
        try {
            // 记录日志
            ApiForOtherRestUtil.saveLog(request.getURI().toString(), getRequest(request,body), getResponseBody(response));
        }catch (Exception e){
            e.printStackTrace();
        }
        return response;
    }

    private String getRequest(HttpRequest request, byte[] body) {
        // 记录请求方法、URL、头信息和请求体
        return new String(body);
    }

    private String getResponseBody(ClientHttpResponse response) throws IOException {
        InputStream inputStream = response.getBody();
        // 记录响应状态码、头信息和响应体
        StringBuilder responseBody = new StringBuilder();
        // 使用try-with-resources语句自动关闭流
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                responseBody.append(line).append(System.lineSeparator());
            }
        } catch (IOException e) {
            // 处理或记录异常
            e.printStackTrace();
        }
        // 打印响应状态码和响应体
        return responseBody.toString();
    }
}

和HttpClient 对比

  • RestTemplate 优势
    • 集成性:RestTemplate 是 Spring 框架的一部分,与 Spring 框架集成良好,提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率
    • 易用性:RestTemplate 提供了同步的 API 来发送 HTTP 请求,使用起来相对简单,适合快速开发。
      模板方法:提供了模板方法来简化请求参数的设置,使得代码更加简洁。
      错误处理:提供了异常处理机制,方便错误管理。
  • RestTemplate 劣势
    • 性能:默认情况下,RestTemplate 使用 HttpURLConnection,没有连接池,性能相对较低。
    • 非异步:RestTemplate 是同步的,不适合需要异步处理的场景。
    • 资源管理:需要手动管理连接的关闭,否则可能会导致资源泄露。
  • HttpClient 优势
    • 连接池:HttpClient 支持连接池,可以提高频繁请求的性能。
    • 异步支持:HttpClient 支持异步请求,适合需要异步处理的场景。
    • 配置灵活:HttpClient 提供了灵活的配置选项,包括超时设置、重试策略等。
    • 协议支持:HttpClient 支持多种 HTTP 协议的方法,包括但不限于 GET、POST、PUT、DELETE 等。
  • HttpClient 劣势
    • 复杂性:HttpClient 的 API 相对复杂,需要更多的配置和手动管理。
    • 资源管理:虽然支持连接池,但也意味着需要正确管理资源,否则可能会导致资源泄露。
    • 社区活跃度:由于 Android 等平台的更新,HttpClient 的社区活跃度有所下降,一些新的优化和改进可能不如其他库及时。

http://www.kler.cn/news/363748.html

相关文章:

  • reactor 安装
  • 链表(虚拟头节点)
  • JavaScript进阶:手写代码挑战(二)
  • Unity3D 自动化资源打AB包详解
  • 定时任务使用kafka
  • stable-zero123模型构建指南
  • RHCE--nginx实现多IP访问多网站
  • 形式架构定义语言(ADL)
  • React综合指南(二)
  • Threejs 实现3D 地图(02)创建3d 地图
  • 【python】sorted() list.sort()
  • LeetCode300:最长递增子序列
  • 【网络安全】简单P1:通过开发者工具解锁专业版和企业版功能
  • PostgreSQL DBA月度检查列表
  • 05 go语言(golang) - 常量和条件语句
  • C++(标准输入输出流、命名空间、string字符串、引用)
  • 怎么快速在ppt中添加文本框?2个常用的ppt使用技巧盘点!
  • 【Linux实验】拆分文件命令
  • 【zookeeper】集群配置
  • MySQL的 Next-Key Lock 底层原理详解
  • Leetcode 赎金信
  • Matlab|基于氢储能的热电联供型微电网优化调度方法
  • WebGL 添加背景图
  • SQL 自学:游标(Cursors)的理解与应用
  • 线性可分支持向量机的原理推导 9-19基于拉格朗日函数L(w,b,α) 对b求偏导 公式解析
  • 如何在分布式环境中实现高可靠性分布式锁