How to use RestTemplate in Spring boot, part II

news/2024/10/30 13:32:03/

How to use RestTemplate in Spring boot, part II

  • Consumer Service
    • pom
    • Controller
    • Business
      • ConsumerBusiness
      • ConsumerBusinessImpl
    • Result
      • MaoResult
      • MaoResultCode
    • Request
    • Config
      • application.yml
      • JurongConfig
      • knife4jConfig
  • Summary

考虑到篇幅问题,这里将一篇文章切割成了两部分,我们将在How to use RestTemplate in Spring boot, part I的基础上继续介绍。

Consumer Service

pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.qwfys.sample</groupId><artifactId>maoshan</artifactId><version>0.0.1-SNAPSHOT</version></parent><groupId>com.qwfys.sample</groupId><artifactId>maoshan-jurong</artifactId><version>0.0.1-SNAPSHOT</version><dependencies><dependency><groupId>com.qwfys.sample</groupId><artifactId>maoshan-common</artifactId></dependency></dependencies></project>

Controller

package com.qwfys.sample.maoshan.jurong.controller;import com.qwfys.sample.maoshan.common.vo.AccountDetailVO;
import com.qwfys.sample.maoshan.jurong.business.spec.ConsumerBusiness;
import com.qwfys.sample.maoshan.jurong.comon.result.MaoResultCode;
import com.qwfys.sample.maoshan.jurong.comon.result.MaoResult;
import com.qwfys.sample.maoshan.jurong.request.AccountDetailRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;@Slf4j
@RestController
@Tag(name = "消费方管理")
public class ConsumerController {@Autowiredprivate ConsumerBusiness consumerBusiness;@PostMapping("/consumer/account/detail")@Operation(summary = "获取消费方账号详情")public MaoResult<AccountDetailVO> viewAccountDetail(@RequestHeader("Authorization") String token, @RequestBody AccountDetailRequest param) {MaoResult<AccountDetailVO> result = null;try {AccountDetailVO detailVO = consumerBusiness.viewAccountDetail(token, param);result = MaoResult.success(detailVO);} catch (Exception e) {log.error(e.getMessage(), e);result = MaoResult.fail(MaoResultCode.EXCEPTION);}log.info("response: {}", result);return result;}
}

Business

ConsumerBusiness

package com.qwfys.sample.maoshan.jurong.business.spec;import com.qwfys.sample.maoshan.common.vo.AccountDetailVO;
import com.qwfys.sample.maoshan.jurong.request.AccountDetailRequest;/*** @author liuwenke* @since 0.0.1*/
public interface ConsumerBusiness {AccountDetailVO viewAccountDetail(String token, AccountDetailRequest param);
}

ConsumerBusinessImpl

package com.qwfys.sample.maoshan.jurong.business.impl;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qwfys.sample.maoshan.common.result.HuaResult;
import com.qwfys.sample.maoshan.common.vo.AccountDetailVO;
import com.qwfys.sample.maoshan.jurong.business.spec.ConsumerBusiness;
import com.qwfys.sample.maoshan.jurong.request.AccountDetailRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;/*** @author liuwenke* @since 0.0.1*/@Slf4j
@Service
public class ConsumerBusinessImpl implements ConsumerBusiness {@Autowiredprivate RestTemplate restTemplate;@Overridepublic AccountDetailVO viewAccountDetail(String token, AccountDetailRequest param) {HttpHeaders headers = new HttpHeaders();headers.set("Authorization", token);headers.setContentType(MediaType.APPLICATION_PROBLEM_JSON);ObjectMapper mapper = new ObjectMapper();String body = null;try {body = mapper.writeValueAsString(param);} catch (JsonProcessingException e) {log.error(e.getMessage(), e);throw new RuntimeException(e);}HttpEntity<?> httpEntity = new HttpEntity<>(body, headers);String apiUrl = "http://127.0.0.1:19000/provider/account/detail";HttpMethod httpMethod = HttpMethod.POST;ResponseEntity<HuaResult<AccountDetailVO>> responseEntity = restTemplate.exchange(apiUrl,httpMethod,httpEntity,new ParameterizedTypeReference<HuaResult<AccountDetailVO>>() {});Assert.notNull(responseEntity, "responseEntity为空");HuaResult<AccountDetailVO> huaResult = responseEntity.getBody();Assert.notNull(huaResult, "result不能为空");Assert.isTrue(huaResult.getIsSuccess(), "code:" + huaResult.getResultCode() + " message:" + huaResult.getResultMessage());AccountDetailVO accountDetail = huaResult.getData();return accountDetail;}
}

Result

MaoResult

package com.qwfys.sample.maoshan.jurong.comon.result;import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;import java.util.Objects;@Slf4j
@Builder
@Data
@AllArgsConstructor
@Schema(description = "统一返回实体")
public class MaoResult<T> {/*** 状态码*/private String code;/*** 信息*/private String msg;/*** 数据*/private T data;public MaoResult() {}public boolean isSuccess() {return Objects.equals(MaoResultCode.OK.value(), this.code);}public boolean isFail() {return !Objects.equals(MaoResultCode.OK.value(), this.code);}public static <T> MaoResult<T> success(T data) {MaoResult<T> maoResult = new MaoResult<>();maoResult.setData(data);maoResult.setCode(MaoResultCode.OK.value());return maoResult;}public static <T> MaoResult<T> success() {MaoResult<T> maoResult = new MaoResult<>();maoResult.setCode(MaoResultCode.OK.value());maoResult.setMsg(MaoResultCode.OK.getMsg());return maoResult;}public static <T> MaoResult<T> success(Integer code, T data) {return success(String.valueOf(code), data);}public static <T> MaoResult<T> success(String code, T data) {MaoResult<T> maoResult = new MaoResult<>();maoResult.setCode(code);maoResult.setData(data);return maoResult;}public static <T> MaoResult<T> showFailMsg(String msg) {log.error(msg);MaoResult<T> maoResult = new MaoResult<>();maoResult.setMsg(msg);maoResult.setCode(MaoResultCode.SHOW_FAIL.value());return maoResult;}public static <T> MaoResult<T> fail(MaoResultCode maoResultCode) {log.error(maoResultCode.toString());MaoResult<T> maoResult = new MaoResult<>();maoResult.setMsg(maoResultCode.getMsg());maoResult.setCode(maoResultCode.value());return maoResult;}public static <T> MaoResult<T> fail(MaoResultCode maoResultCode, T data) {log.error(maoResultCode.toString());MaoResult<T> maoResult = new MaoResult<>();maoResult.setMsg(maoResultCode.getMsg());maoResult.setCode(maoResultCode.value());maoResult.setData(data);return maoResult;}public static <T> MaoResult<T> fail(String code, String msg, T data) {log.error(msg);MaoResult<T> maoResult = new MaoResult<>();maoResult.setMsg(msg);maoResult.setCode(code);maoResult.setData(data);return maoResult;}public static <T> MaoResult<T> fail(String code, String msg) {return fail(code, msg, null);}public static <T> MaoResult<T> fail(Integer code, T data) {MaoResult<T> maoResult = new MaoResult<>();maoResult.setCode(String.valueOf(code));maoResult.setData(data);return maoResult;}
}

MaoResultCode

package com.qwfys.sample.maoshan.jurong.comon.result;import lombok.ToString;/*** @author liuwenke* @since 0.0.1*/
@ToString
public enum MaoResultCode {OK("00000", "ok"),SHOW_FAIL("A00001", ""),REMOTE_CALL_FAIL("REMOTE_CALL_FAIL", "远程接口调用失败"),PARSING_JSON_FAIL("PARSING_JSON_FAIL", "JSON解析失败"),/*** 用于直接显示提示系统的成功,内容由输入内容决定*/SHOW_SUCCESS("A00002", ""),/*** 未授权*/UNAUTHORIZED("A00004", "Unauthorized"),/*** 服务器出了点小差*/EXCEPTION("A00005", "服务器出了点小差"),/*** 方法参数没有校验,内容由输入内容决定*/METHOD_ARGUMENT_NOT_VALID("A00014", "方法参数没有校验");private final String code;private final String msg;public String value() {return code;}public String getMsg() {return msg;}MaoResultCode(String code, String msg) {this.code = code;this.msg = msg;}
}

Request

package com.qwfys.sample.maoshan.jurong.request;import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;@Schema(description = "账号详情请求参数")
@Data
@Accessors(chain = true)
public class AccountDetailRequest {@Schema(description = "用户ID")private Long userId;
}

Config

application.yml

mybatis-plus:global-config:banner: falseserver:port: 19001spring:datasource:url: jdbc:mysql://127.0.0.1:23306/jurong?allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=trueusername: rootpassword: Gah6kuP7ohfio4driver-class-name: com.mysql.cj.jdbc.Drivertype: com.zaxxer.hikari.HikariDataSourcehikari:minimum-idle: 0maximum-pool-size: 20idle-timeout: 10000auto-commit: trueconnection-test-query: SELECT 1

JurongConfig

package com.qwfys.sample.maoshan.jurong.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;/*** @author liuwenke* @since 0.0.1*/
@Configuration
public class JurongConfig {private static final int CONNECT_TIMEOUT = 8000;private static final int SOCKET_TIMEOUT = 8000;@Beanpublic RestTemplate restTemplate() {SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();//factory.setConnectTimeout(CONNECT_TIMEOUT);//factory.setReadTimeout(SOCKET_TIMEOUT);return new RestTemplate(factory);//return new RestTemplate();}
}

knife4jConfig

package com.qwfys.sample.maoshan.jurong.config;import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author liuwenke* @since 0.0.1*/
@Configuration
public class knife4jConfig {@Beanpublic GroupedOpenApi baseRestApi() {return GroupedOpenApi.builder().group("接口文档").packagesToScan("com.qwfys.sample.maoshan").build();}@Beanpublic OpenAPI springShopOpenApi() {return new OpenAPI().info(new Info().title("Service Consumer接口文档").description("Service Consumer接口文档").version("0.0.1-SNAPSHOT").license(new License().name("使用请遵守MIT License授权协议").url("https://github.com/ab-sample/maoshan")));}
}

Summary

1、借助RestTemplate取到json数据以后,很多时候,我们都期望将json数据反序列化为Java Bean对象。

如果Java Bean不包含泛型,可以借助如下方法完成数据的接收与反序列化:

public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {@Overridepublic <T> ResponseEntity<T> exchange(String url, HttpMethod method,@Nullable HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables)throws RestClientException {RequestCallback requestCallback = httpEntityCallback(requestEntity, responseType);ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);return nonNull(execute(url, method, requestCallback, responseExtractor, uriVariables));}
}

将json反序列化后的Java Bean对应的class传给方法的参数responseType。

如果Java Bean包含泛型,可以借助如下方法完成数据的接收与反序列化:

public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {@Overridepublic <T> ResponseEntity<T> exchange(String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity,ParameterizedTypeReference<T> responseType, Object... uriVariables) throws RestClientException {Type type = responseType.getType();RequestCallback requestCallback = httpEntityCallback(requestEntity, type);ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(type);return nonNull(execute(url, method, requestCallback, responseExtractor, uriVariables));}
}

这个时候,我们要实例化一个ParameterizedTypeReference的对象出来,实例化的时候,需要将json反序列化后的Java Bean做为ParameterizedTypeReference的泛型参数来实例化,如:

public AccountDetailVO viewAccountDetail(String token, AccountDetailRequest param) {HttpHeaders headers = new HttpHeaders();headers.set("Authorization", token);headers.setContentType(MediaType.APPLICATION_PROBLEM_JSON);ObjectMapper mapper = new ObjectMapper();String body = null;try {body = mapper.writeValueAsString(param);} catch (JsonProcessingException e) {log.error(e.getMessage(), e);throw new RuntimeException(e);}HttpEntity<?> httpEntity = new HttpEntity<>(body, headers);String apiUrl = "http://127.0.0.1:19000/provider/account/detail";HttpMethod httpMethod = HttpMethod.POST;ResponseEntity<HuaResult<AccountDetailVO>> responseEntity = restTemplate.exchange(apiUrl,httpMethod,httpEntity,new ParameterizedTypeReference<HuaResult<AccountDetailVO>>() {});Assert.notNull(responseEntity, "responseEntity为空");HuaResult<AccountDetailVO> huaResult = responseEntity.getBody();Assert.notNull(huaResult, "result不能为空");Assert.isTrue(huaResult.getIsSuccess(), "code:" + huaResult.getResultCode() + " message:" + huaResult.getResultMessage());AccountDetailVO accountDetail = huaResult.getData();return accountDetail;}

这里将HuaResult<AccountDetailVO>做为ParameterizedTypeReference的泛型参数传入,完成实例化。

2、如果要对RestTemplate实例做定制化,在创建的时候,可以基于相应的工厂方法实现,如:

@Configuration
public class JurongConfig {private static final int CONNECT_TIMEOUT = 8000;private static final int SOCKET_TIMEOUT = 8000;@Beanpublic RestTemplate restTemplate() {SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();factory.setConnectTimeout(CONNECT_TIMEOUT);factory.setReadTimeout(SOCKET_TIMEOUT);return new RestTemplate(factory);//return new RestTemplate();}
}

如果只是简单用一下,可以用如下方式完成实例化:

@Configuration
public class JurongConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}

完整的样例代码我放到github上的maoshan代码仓库了,如果想看完整的代码可以到github下载。


http://www.ppmy.cn/news/78497.html

相关文章

Smartbi电子表格故事之用数据进行销售问题分析

天津小麦商贸有限公司&#xff08;X&M&#xff09;成立于2012年11月&#xff0c;主营业务是商贸流通业&#xff0c;主要是日用商品的批发销售。 2012年前&#xff0c;公司创始人&#xff08;总经理和销售总监&#xff09;一直从事外贸的生意&#xff0c;自从2008年金融危机…

FreeRTOS学习之路,以STM32F103C8T6为实验MCU(序章——浅谈单片机以及FreeRTOS)

学习之路主要为FreeRTOS操作系统在STM32F103&#xff08;STM32F103C8T6&#xff09;上的运用&#xff0c;采用的是标准库编程的方式&#xff0c;使用的IDE为KEIL5。 注意&#xff01;&#xff01;&#xff01;本学习之路可以通过购买STM32最小系统板以及部分配件的方式进行学习…

kubelet源码分析 添加 /删除pod (SyncPod、SyncTerminatingPod、SyncTerminatedPod)篇

kubelet源码分析 添加 /删除pod (SyncPod、SyncTerminatingPod、SyncTerminatedPod) kubelet版本v1.27.1 前面讲过删除pod和添加pod&#xff0c;都是在kubelet文件的的HandlePodAdditions函数和pod_workers.go文件中主要流程。 这篇文章是当pod_workers.go流程结束后&#xf…

智慧档案馆一体化监控系统设计所需要的10条依据

1.科学性 本项目目标定位为&#xff1a;以科学技术为基础&#xff0c;依靠先进的设备和优越的设计理念、科学客观的管理&#xff0c;利用信息化管理及相关最新技术&#xff0c;将库房实际环境与存储技术、计算机技术、无线自动控制技术、通讯与信息处理技术等先进技术相结合&a…

论文阅读_语音合成_Spear-TTS

论文信息 number headings: auto, first-level 2, max 4, _.1.1 name_en: Speak, Read and Prompt: High-Fidelity Text-to-Speech with Minimal Supervision name_ch: 说话、阅读和提示&#xff1a;少量监督实现高保真文本转语音 paper_addr: http://arxiv.org/abs/2302.0354…

Vue3 權限路由

最近接觸到關於role 能夠查看相關頁面的功能 最初的作法是全部的路由使用動態加載&#xff0c;考慮到 跟權限有關係 &#xff0c;就有可能各種頁面都需要調用&#xff0c;因此這裡的role狀態會儲存在全局狀態管理中&#xff08;pinia&#xff09; 1.首先區隔出需要權限才能瀏覽…

性能优化常用的技巧,你都知道吗?

在实际工作中&#xff0c;提升MySQL数据库的查询性能是非常重要的。除了基本的索引和查询优化技巧外&#xff0c;还有一些更深层次的优化方案可以进一步优化性能。 1. 数据库表设计优化 选择字段类型&#xff1a; 根据数据类型和范围&#xff0c;选择适当的字段类型。例如&am…

SFM过程(一)

以图像为基础的三维重建过程SFM基本如下图所示&#xff1a; 以SfM-Toy-Library代码为例&#xff0c;如下&#xff1a; ErrorCode SfM::runSfM() {if (mImages.size() < 0) {cerr << "No images to work on." << endl;return ErrorCode::ERROR;}//in…