前言
上一篇簡單的闡述了 spring-cloud-thrift-starter
這個外掛的配置和使用,並引入了一個calculator
的專案。本文將基於一個銀行存款、取款的業務場景,給出一套thrift
在生產環境的應用案例。
首先設計如下幾張簡單的資料庫表:銀行(bank
)、分支(branch
)、銀行卡(deposit_card
)、客戶(customer
)、存款歷史紀錄(deposit_history
)、取款歷史紀錄(withdraw_history
)。
正文
專案結構如下,依然是由三個模組組成:
- deposit
- deposit-client
- deposit-iface
- deposit-server
Thrift IDL編寫
關於 thrift
更復雜的用法可以參考Apache Thrift
基礎學習系列,根據資料庫表的設計編寫 deposit.thrift
。
deposit.thrift
定義了以下四個部分:名稱空間 (namespace
)、列舉型別 (enum
)、結構型別 (struct
)和服務型別 (service
)。
(a). 名稱空間 (namespace
)
// 指定編譯生成的原始碼的包路徑名稱
namespace java com.icekredit.rpc.thrift.examples.thrift
複製程式碼
(b). 列舉型別 (enum
)
// 通過列舉定義銀行分支所屬區域
enum ThriftRegion {
NORTH = 1,
CENTRAL = 2,
SOUTH = 3,
EAST = 4,
SOUTHWEST = 5,
NORTHWEST = 6,
NORTHEAST = 7
}
// 存款完成狀態
enum ThriftDepositStatus {
FINISHED = 1,
PROCCEDING = 2,
FAILED = 3
}
// 取款完成狀態
enum ThriftWithdrawStatus {
FINISHED = 1,
PROCCEDING = 2,
FAILED = 3
}
複製程式碼
(c). 結構型別 (struct
)
// 銀行
struct ThriftBank {
1: required i64 id,
2: required string code,
3: required string name,
4: optional string description,
5: optional map<ThriftRegion, list<ThriftBranch>> branches
}
// 銀行分支
struct ThriftBranch {
1: required i64 id,
2: required string code,
3: required string name,
4: required string address,
5: optional i32 staffs,
6: optional ThriftBank bank,
7: optional ThriftRegion region
}
// 客戶
struct ThriftCustomer {
1: required string IDNumber,
2: required string name,
3: required string birthday,
4: required i32 sex = 0,
5: required i32 age,
6: optional list<string> address,
7: optional set<ThriftDepositCard> depositCards
}
// 銀行卡
struct ThriftDepositCard {
1: required string id,
2: required bool isVip,
3: required string openingTime,
4: required double accountBalance,
5: optional double accountFlow,
6: optional ThriftBranch branch,
7: optional ThriftCustomer customer,
8: optional list<ThriftDeposit> depositHistory,
9: optional list<ThriftWithdraw> WithdrawHistory
}
// 存款歷史紀錄
struct ThriftDeposit {
1: required string serialNumber,
2: required double transactionAmount,
3: required string submittedTime,
4: optional string finishedTime,
5: optional ThriftDepositStatus status,
6: optional ThriftDepositCard depositCard
}
// 取款歷史紀錄
struct ThriftWithdraw {
1: required string serialNumber,
2: required double transactionAmount,
3: required string submittedTime,
4: optional string finishedTime,
5: optional ThriftWithdrawStatus status,
6: optional ThriftDepositCard depositCard
}
複製程式碼
(d). 服務型別 (service
)
// 銀行 - 業務服務定義
service ThriftBankService {
void registerNewBank(ThriftBank bank);
list<ThriftBank> queryAllBanks();
ThriftBank getBankById(i64 bankId);
map<ThriftRegion, list<ThriftBranch>> queryAllBranchesByRegion(i64 bankId);
}
// 銀行分支 - 業務服務定義
service ThriftBranchService {
void addNewBranch(i64 bankId, ThriftBranch branch);
list<ThriftBranch> queryAllBranches(i64 bankId);
ThriftBranch getBranchById(i64 branchId);
}
// 客戶 - 業務服務定義
service ThriftCustomerService {
ThriftCustomer getCustomerById(string customerId);
list<ThriftCustomer> queryAllCustomers();
void addNewUser(ThriftCustomer customer);
void modifyUserById(string customerId, ThriftCustomer customer);
i32 getTotalDepositCard(string customerId);
}
// 銀行卡 - 業務服務定義
service ThriftDepositCardService {
set<ThriftDepositCard> queryAllDepositCards(string customerId);
void addNewDepositCard(string customerId, ThriftDepositCard depositCard);
ThriftDepositStatus depositMoney(string depositCardId, double money);
ThriftWithdrawStatus withdrawMoney(string depositCardId, double money);
list<ThriftDeposit> queryDepositHistorys(string depositCardId);
list<ThriftWithdraw> queryWithdrawHistorys(string depositCardId);
}
複製程式碼
進入src/main/thrift
目錄,編譯生成所需的列舉類、結構類和業務服務類的原始檔。
thrift -gen java ./deposit.thrift
複製程式碼
所有生成的原始檔都位於同一個**名稱空間(包)**下面:com.icekredit.rpc.thrift.examples.thrift
中間契約(deposit-iface)
將上述原始檔拷貝到 deposit-iface
模組中。
通過Mybatis
逆向工程外掛生成SQLMapper
的XML
和介面檔案以及實體類。
友情提示:
Mybatis
逆向工程生成的實體類 (entity
),需要和Thrift
編譯生成器生成的結構類 (struct
) 區分開來。而Thrift
生成器生成的所有原始檔,都一定程度封裝了底層的通訊方式和相關協議,開發人員是不應該動手腳的。
為了在Thrift
中通過Mybatis
完成資料持久化,必須在實體類 (entity
)包裝一層與結構類 (struct
)相互轉換的方法。
在每個實體類中,根據業務新增以下兩個方法,以DepositCard
為例:
- toThrift():將實體類物件轉換為結構類物件。
public ThriftDepositCard toThrift() {
ThriftDepositCard thriftDepositCard = new ThriftDepositCard();
thriftDepositCard.setId(this.getId());
thriftDepositCard.setAccountBalance(this.getAccountBalance());
thriftDepositCard.setAccountFlow(this.getAccountFlow());
thriftDepositCard.setIsVip(this.getIsVip());
thriftDepositCard.setOpeningTime(this.getOpeningTime());
ThriftBranch thriftBranch = new ThriftBranch();
thriftBranch.setId(this.getBranchId());
thriftDepositCard.setBranch(thriftBranch);
ThriftCustomer thriftCustomer = new ThriftCustomer();
thriftCustomer.setIDNumber(this.getCustomerId());
thriftDepositCard.setCustomer(thriftCustomer);
return thriftDepositCard;
}
複製程式碼
- fromThrift():靜態方法,將結構類物件轉換為實體類物件。
public static DepositCard fromThrift(ThriftDepositCard thriftDepositCard) {
DepositCard depositCard = new DepositCard();
depositCard.setId(thriftDepositCard.getId());
depositCard.setAccountBalance(thriftDepositCard.getAccountBalance());
depositCard.setAccountFlow(thriftDepositCard.getAccountFlow());
depositCard.setIsVip(thriftDepositCard.isIsVip());
ThriftCustomer thriftCustomer = thriftDepositCard.getCustomer();
if (thriftCustomer != null) {
String customerIDNumber = thriftCustomer.getIDNumber();
depositCard.setCustomerId(customerIDNumber);
}
ThriftBranch thriftBranch = thriftDepositCard.getBranch();
if (thriftBranch != null) {
Long branchId = thriftBranch.getId();
depositCard.setBranchId(branchId);
}
depositCard.setOpeningTime(thriftDepositCard.getOpeningTime());
return depositCard;
}
複製程式碼
服務端(deposit-server)
在服務端模組引入:
- spring-cloud-starter-thrift-server:
thrift
服務端的starter
程式。 - calculator-iface:中間契約模組,這裡作為服務端骨架(
Skeleton
)程式。
pom.xml
<parent>
<groupId>com.icekredit.rpc.thrift.examples</groupId>
<artifactId>deposit</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>deposit-server</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- Thrift相關依賴 -->
<dependency>
<groupId>com.icekredit.rpc.thrift</groupId>
<artifactId>spring-cloud-starter-thrift-server</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.icekredit.rpc.thrift.examples</groupId>
<artifactId>deposit-iface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- SpringBoot依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 資料庫相關依賴 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.5</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<!-- Swagger依賴 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
複製程式碼
在application.yml
中配置thrift
服務端的執行引數、資料來源連線池引數和Mybatis
相關屬性:
application.yml
server:
port: 8080
endpoints:
actuator:
sensitive: false
enabled: true
management:
security:
enabled: false
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/deposit?useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root
thrift:
server:
service-id: deposit-server-rpc
service-model: hsHa
port: 25000
worker-queue-capacity: 1000
hs-ha:
min-worker-threads: 5
max-worker-threads: 20
keep-alived-time: 3
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.icekredit.rpc.thrift.examples.http.entities
logging:
level:
root: INFO
com:
icekredit:
rpc:
thrift:
examples:
mapper: DEBUG
複製程式碼
服務端程式啟動入口類,設定 Swagger API
所在的包路徑名稱。
Application.java
@SpringBootApplication
@EnableSwagger2
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public Docket createRestfulApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.icekredit.rpc.thrift.examples.service.http.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Deposit Server")
.description("Deposit Server")
.version("1.0")
.build();
}
}
複製程式碼
編寫服務端的Thrift
的實現,以ThriftDepositCardService
為例,由實現類ThriftDepositCardServiceImpl
實現ThriftDepositCardService.Iface
介面的方法:
ThriftDepositCardServiceImpl.java
@ThriftService(name = "thriftDepositCardService")
public class ThriftDepositCardServiceImpl implements ThriftDepositCardService.Iface {
private final BranchMapper branchMapper;
private final DepositCardMapper depositCardMapper;
private final CustomerMapper customerMapper;
private final DepositHistoryMapper depositHistoryMapper;
private final WithdrawHistoryMapper withdrawHistoryMapper;
@Autowired
public ThriftDepositCardServiceImpl(BranchMapper branchMapper, DepositCardMapper depositCardMapper, CustomerMapper customerMapper, DepositHistoryMapper depositHistoryMapper, WithdrawHistoryMapper withdrawHistoryMapper) {
this.branchMapper = branchMapper;
this.depositCardMapper = depositCardMapper;
this.customerMapper = customerMapper;
this.depositHistoryMapper = depositHistoryMapper;
this.withdrawHistoryMapper = withdrawHistoryMapper;
}
@Override
public Set<ThriftDepositCard> queryAllDepositCards(String customerId) throws TException {
List<DepositCard> depositCardList = depositCardMapper.queryAllDepositCards(customerId);
// 查詢客戶持有的銀行卡
return depositCardList.stream().map(depositCard -> {
ThriftDepositCard thriftDepositCard = depositCard.toThrift();
Long branchId = depositCard.getBranchId();
if (Objects.nonNull(branchId) && branchId > 0L) {
Branch branch = branchMapper.findById(branchId);
ThriftBranch thriftBranch = branch.toThrift();
ThriftBank thriftBank = new ThriftBank();
thriftBank.setId(branch.getBankId());
thriftBranch.setBank(thriftBank);
thriftDepositCard.setBranch(thriftBranch);
}
Customer customer = customerMapper.findById(customerId);
ThriftCustomer thriftCustomer = customer.toThrift();
thriftDepositCard.setCustomer(thriftCustomer);
return thriftDepositCard;
}).collect(Collectors.toSet());
}
@Override
@Transactional
public void addNewDepositCard(String customerId, ThriftDepositCard depositCard) throws TException {
DepositCard newDepositCard = DepositCard.fromThrift(depositCard);
// 新增銀行卡資訊
depositCardMapper.save(newDepositCard);
}
@Override
@Transactional
public ThriftDepositStatus depositMoney(String depositCardId, double money) throws TException {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
try {
DepositHistory depositHistory = new DepositHistory();
depositHistory.setSubmittedTime(sf.format(new Date()));
depositCardMapper.incrementMoney(depositCardId, money);
depositHistory.setFinishedTime(sf.format(new Date()));
depositHistory.setSerialNumber(UUID.randomUUID().toString().replace("-", ""));
depositHistory.setTransactionAmount(money);
depositHistory.setDepositCardId(depositCardId);
depositHistory.setStatus(1);
// 新增存款歷史記錄
depositHistoryMapper.save(depositHistory);
return ThriftDepositStatus.FINISHED;
} catch (Exception e) {
e.printStackTrace();
return ThriftDepositStatus.FAILED;
}
}
@Override
@Transactional
public ThriftWithdrawStatus withdrawMoney(String depositCardId, double money) throws TException {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
try {
WithdrawHistory withdrawHistory = new WithdrawHistory();
withdrawHistory.setSubmittedTime(sf.format(new Date()));
depositCardMapper.decrementMoney(depositCardId, money);
withdrawHistory.setFinishedTime(sf.format(new Date()));
withdrawHistory.setSerialNumber(UUID.randomUUID().toString().replace("-", ""));
withdrawHistory.setTransactionAmount(money);
withdrawHistory.setDepositCardId(depositCardId);
withdrawHistory.setStatus(1);
// 新增取款歷史記錄
withdrawHistoryMapper.save(withdrawHistory);
return ThriftWithdrawStatus.FINISHED;
} catch (Exception e) {
e.printStackTrace();
return ThriftWithdrawStatus.FAILED;
}
}
@Override
public List<ThriftDeposit> queryDepositHistorys(String depositCardId) throws TException {
List<DepositHistory> depositHistory = depositHistoryMapper.queryDepositHistoryList(depositCardId);
// 查詢存款歷史紀錄
return depositHistory.stream().map(DepositHistory::toThrift).collect(Collectors.toList());
}
@Override
public List<ThriftWithdraw> queryWithdrawHistorys(String depositCardId) throws TException {
List<WithdrawHistory> withdrawHistory = withdrawHistoryMapper.queryWithdrawHistoryList(depositCardId);
// 查詢取款歷史紀錄
return withdrawHistory.stream().map(WithdrawHistory::toThrift).collect(Collectors.toList());
}
}
複製程式碼
Mybatis
持久層,還是以DepositCardMapper
為例:
DepositCardMapper.java
@Repository
@Mapper
public interface DepositCardMapper {
int save(DepositCard record);
List<DepositCard> queryAllDepositCards(@Param("customerId") String customerId);
void decrementMoney(@Param("depositCardId") String depositCardId, @Param("money") Double money);
void incrementMoney(@Param("depositCardId") String depositCardId, @Param("money") Double money);
Long countRowsByCustomerId(@Param("customerId") String customerId);
}
複製程式碼
DepositCardMapper.xml
<insert id="save" parameterType="com.icekredit.rpc.thrift.examples.http.entities.DepositCard">
INSERT INTO deposit_card (id, is_vip, opening_time,
account_balance, account_flow, branch_id,
customer_id)
VALUES (#{id,jdbcType=VARCHAR}, #{isVip,jdbcType=BIT}, #{openingTime,jdbcType=VARCHAR},
#{accountBalance,jdbcType=DOUBLE}, #{accountFlow,jdbcType=DOUBLE}, #{branchId,jdbcType=BIGINT},
#{customerId,jdbcType=VARCHAR})
</insert>
<select id="queryAllDepositCards" resultMap="BaseResultMap" parameterType="java.lang.String">
SELECT
<include refid="Base_Column_List"/>
FROM deposit_card
WHERE customer_id = #{customerId}
</select>
<select id="countRowsByCustomerId" resultType="java.lang.Long" parameterType="java.lang.String">
SELECT COUNT(id)
FROM deposit_card
WHERE customer_id = #{customerId}
</select>
<update id="decrementMoney">
UPDATE deposit_card
<set>
<if test="money != null">
account_balance = account_balance - #{money},
</if>
</set>
WHERE id = #{depositCardId}
</update>
<update id="incrementMoney">
UPDATE deposit_card
<set>
<if test="money != null">
account_balance = account_balance + #{money},
</if>
</set>
WHERE id = #{depositCardId}
</update>
複製程式碼
客戶端(deposit-client)
同樣,在客戶端模組引入:
- spring-cloud-starter-thrift-client:
thrift
客戶端的starter
程式。 - deposit-iface:中間契約模組,這裡作為客戶端樁(
Stub
)程式。
pom.xml
<parent>
<groupId>com.icekredit.rpc.thrift.examples</groupId>
<artifactId>deposit</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>deposit-client</artifactId>
<dependencies>
<!-- Thrift相關依賴 -->
<dependency>
<groupId>com.icekredit.rpc.thrift</groupId>
<artifactId>spring-cloud-starter-thrift-client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.icekredit.rpc.thrift.examples</groupId>
<artifactId>deposit-iface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- SpringBoot依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud Consul服務註冊與發現 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- Spring Cloud宣告式Restful客戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<!-- Swagger依賴 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
複製程式碼
在application.yml
中配置thrift
的客戶端的的執行引數和 Consul
的服務註冊與發現的引數:
application.yml
server:
port: 8080
endpoints:
actuator:
sensitive: false
enabled: true
management:
security:
enabled: false
spring:
cloud:
consul:
host: 192.168.91.128
port: 8500
discovery:
register: false
register-health-check: true
health-check-interval: 30s
retry:
max-attempts: 3
max-interval: 2000
thrift:
client:
package-to-scan: com.icekredit.rpc.thrift.examples.thrift.client
service-model: hsHa
pool:
retry-times: 3
pool-max-total-per-key: 200
pool-min-idle-per-key: 10
pool-max-idle-per-key: 40
pool-max-wait: 10000
connect-timeout: 5000
複製程式碼
客戶端程式啟動入口類,設定 Swagger API
所在的包路徑名稱,同時允許自身作為註冊程式註冊到註冊中心。
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
@EnableSwagger2
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public Docket createRestfulApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.icekredit.rpc.thrift.examples"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Deposit Client")
.description("Deposit Client")
.version("1.0")
.build();
}
}
複製程式碼
在客戶端使用@ThriftClient
註解標識服務端的thrift
服務代理介面,代理服務ID
為deposit-server-rpc
,代理的目標類是ThriftDepositCardService
。
DepositCardThriftClient.java
@ThriftClient(serviceId = "deposit-server-rpc", refer = ThriftDepositCardService.class)
public interface DepositCardThriftClient extends ThriftClientAware<ThriftDepositCardService.Client> {
}
複製程式碼
BankThriftClient.java
@ThriftClient(serviceId = "deposit-server-rpc", refer = ThriftBankService.class)
public interface BankThriftClient extends ThriftClientAware<ThriftBankService.Client> {
}
複製程式碼
在客戶端控制器中通過ThriftReferer
注入需要使用的服務代理介面,通過 thriftClient.client()
即可獲取Thrift
客戶端樁物件,然後實現遠端服務的呼叫。
DepositCardRpcController.java
@RestController
@RequestMapping("/rpc/deposit")
public class DepositCardRpcController {
@ThriftReferer
private DepositCardThriftClient thriftClient;
@GetMapping("/queryAllDepositCards")
public List<DepositCard> queryAllDepositCards(@RequestParam("customerId") String customerId)
throws Exception {
return thriftClient.client().queryAllDepositCards(customerId)
.stream().map(DepositCard::fromThrift)
.collect(Collectors.toList());
}
@PostMapping("/addNewDepositCard")
public void addNewDepositCard(DepositCard depositCard) throws Exception {
thriftClient.client().addNewDepositCard(depositCard.getCustomerId(), depositCard.toThrift());
}
@GetMapping("/depositMoney")
public ThriftDepositStatus depositMoney(@RequestParam("depositCardId") String depositCardId,
@RequestParam("money") double money) throws Exception {
return thriftClient.client().depositMoney(depositCardId, money);
}
@GetMapping("/withdrawMoney")
public ThriftWithdrawStatus withdrawMoney(@RequestParam("depositCardId") String depositCardId,
@RequestParam("money") double money) throws Exception {
return thriftClient.client().withdrawMoney(depositCardId, money);
}
@GetMapping("/queryDepositHistory")
public List<DepositHistory> queryDepositHistory(@RequestParam("depositCardId") String depositCardId)
throws Exception {
return thriftClient.client().queryDepositHistorys(depositCardId)
.stream().map(DepositHistory::fromThrift)
.collect(Collectors.toList());
}
@GetMapping("/queryWithdrawHistory")
public List<WithdrawHistory> queryWithdrawHistory(@RequestParam("depositCardId") String depositCardId)
throws Exception {
return thriftClient.client().queryWithdrawHistorys(depositCardId)
.stream().map(WithdrawHistory::fromThrift)
.collect(Collectors.toList());
}
}
複製程式碼
BankRpcController.java
@RestController
@RequestMapping("/rpc/bank")
public class BankRpcController {
@ThriftReferer
private BankThriftClient thriftClient;
@PostMapping("/addNewBank")
public void addNewBank(Bank bank) throws Exception {
thriftClient.client().registerNewBank(bank.toThrift());
}
@GetMapping("/getBankById")
public Bank getBankById(@RequestParam("bankId") Long bankId) throws Exception {
return Bank.fromThrift(thriftClient.client().getBankById(bankId));
}
@GetMapping("/queryAllBranchesByRegion")
public Map<Region, List<Branch>> queryAllBranchesByRegion(@RequestParam("bankId") Long bankId) throws Exception {
Map<ThriftRegion, List<ThriftBranch>> thriftRegionListMap = thriftClient.client()
.queryAllBranchesByRegion(bankId);
Map<Region, List<Branch>> regionListMap = new HashMap<>();
for (Map.Entry<ThriftRegion, List<ThriftBranch>> entry : thriftRegionListMap.entrySet()) {
ThriftRegion thriftRegion = entry.getKey();
Region region = Region.findByValue(thriftRegion.getValue());
List<ThriftBranch> thriftBranches = entry.getValue();
List<Branch> branchList = thriftBranches.stream().map(Branch::fromThrift).collect(Collectors.toList());
regionListMap.put(region, branchList);
}
return regionListMap;
}
}
複製程式碼
因為服務代理客戶端介面使用@ThriftClient
標識,通過(服務ID + 客戶端樁 + 版本號)唯一標識, 即使同時注入多個服務代理客戶端介面,@ThriftReferer
也可忽略註解屬性的配置。
總結
有一點是肯定的,那就是在已有技術框架(比如說:Spring
+ Mybatis/JPA
)內,為了提高服務的效能和吞吐量,而引入諸如Thrift
的RPC
框架,程式設計難度和複雜度是會大大提高的。好比一把雙刃劍,技術選型時還需要多方面權衡利弊。
歡迎關注技術公眾號: 零壹技術棧
本帳號將持續分享後端技術乾貨,包括虛擬機器基礎,多執行緒程式設計,高效能框架,非同步、快取和訊息中介軟體,分散式和微服務,架構學習和進階等學習資料和文章。