当前位置: 代码迷 >> 综合 >> Spring boot理财系统4 Jsonrpc
  详细解决方案

Spring boot理财系统4 Jsonrpc

热度:3   发布时间:2023-12-15 01:28:48.0

销售端作用:

用于与第三方交互的门户网关,这里进行安全控制,流量统计等,整合内部资源,对外提供相应的接口,完成产品的销售管理

功能:

  • 产品查询
  • 申购、赎回
  • 对账

接口文档:

  • swagger
  • swagger编写
  • 已有代码生成接口文档

主要步骤

  • 在api模块中定义产品相关的rpc请求服务和请求对象
  • 在manager中的rpc包下实现api模块中的服务类
  • 在manager中的configuration包下实现RpcConfiguration将rpc相关配置交给spring管理

常见错误:
在配置类中对应的配置内容未添加@Bean

application.yml中url的配置末尾要加/,Json

@JsonRpcService("rpc/products") //这里不能以/开始 例如 /products这是错误的(这里可以通过自己封装来配置)

序列化和反序列化问题

Cannot determine embedded database driver class for database type NONE

产品查询功能

使用jsonrpc实现系统内部之间的交互

使用jsonrpc4j框架来实现jsonrpc

引入依赖

产品相关rpc封装成一个类

package com.qwl.api.domain;import org.springframework.data.domain.Pageable;
import java.math.BigDecimal;
import java.util.List;/*** 产品相关rpc请求对象*/
public class ProductRpcReq {private List<String> idList;private BigDecimal minRewardRate;private BigDecimal maxRewardRate;private List<String> statusList;private Pageable pageable;//get set toString
}

产品相关rpc服务

import com.googlecode.jsonrpc4j.JsonRpcService;
import com.qwl.api.domain.ProductRpcReq;
import com.qwl.entity.Product;
import org.springframework.data.domain.Page;@JsonRpcService("rpc/products")
public interface ProductRpc {//查询多个产品Page<Product> query(ProductRpcReq req);//查询单个产品Product findOne(String id);}

rpc管理端

在管理端添加依赖

    compile project(":api")

rpc服务实现类

package com.qwl.manager.rpc;import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImpl;
import com.qwl.api.ProductRpc;
import com.qwl.api.domain.ProductRpcReq;
import com.qwl.entity.Product;
import com.qwl.manager.service.ProductService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;@AutoJsonRpcServiceImpl
@Service
public class ProductRpcImpl implements ProductRpc {private static Logger LOG = LoggerFactory.getLogger(ProductRpcReq.class);@Autowiredprivate ProductService productService;@Overridepublic Page<Product> query(ProductRpcReq req) {LOG.info("查询多个产品,请求{}",req);Page<Product> result = productService.query(req.getIdList(),req.getMinRewardRate(),req.getMaxRewardRate(),req.getStatusList(),req.getPageable());LOG.info("查询多个产品,结果{}",result);return result;}@Overridepublic Product findOne(String id) {LOG.info("查询产品详情,请求{}",id);Product result = productService.findOne(id);LOG.info("查询产品详情,结果{}",result);return result;}
}

rpc相关配置

 

rpc客户端

添加依赖并新建启动类

package com.qwl.seller.Service;import com.qwl.api.ProductRpc;
import com.qwl.api.domain.ProductRpcReq;
import com.qwl.entity.Product;
import com.qwl.entity.enums.ProductStatus;
import com.qwl.seller.configuration.RpcConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;@Service
public class ProductRpcService {@Autowiredprivate ProductRpc productRpc;private static Logger LOG = LoggerFactory.getLogger(RpcConfiguration.class);//查询全部产品public List<Product> findAll(){ProductRpcReq req = new ProductRpcReq();List<String> status = new ArrayList<>();status.add(ProductStatus.IN_SELL.name());Pageable pageable = new PageRequest(0,1000,Sort.Direction.DESC,"rewardRate");req.setStatusList(status);LOG.info("rpc查询全部产品,请求{}",req);LOG.info("rpc查询全部产品,请求:{}",req);Page<Product> result = productRpc.query(req);LOG.info("rpc查询全部产品,结果:{}",result);return result.getContent();}@PostConstructpublic void test(){findAll();}//查询单个产品public Product findOne(String id){LOG.info("rpc查询单个产品,请求:{}",id);Product result = productRpc.findOne(id);LOG.info("rpc查询单个产品,结果:{}",result);return result;}@PostConstructpublic void init(){findOne("001");}
}

package com.qwl.seller.configuration;import com.googlecode.jsonrpc4j.spring.AutoJsonRpcClientProxyCreator;
import com.qwl.api.ProductRpc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;import java.net.MalformedURLException;
import java.net.URL;@Configuration
@ComponentScan(basePackageClasses = {ProductRpc.class})
public class RpcConfiguration {private static Logger LOG = LoggerFactory.getLogger(RpcConfiguration.class);@Beanpublic AutoJsonRpcClientProxyCreator rpcClientProxyCreator(@Value("${rpc.manager.url}") String url){AutoJsonRpcClientProxyCreator creator = new AutoJsonRpcClientProxyCreator();try {creator.setBaseUrl(new URL(url));} catch (MalformedURLException e) {LOG.error("创建rpc服务地址错误",e);}creator.setScanPackage(ProductRpc.class.getPackage().getName());return creator;}
}

修改ProductRpcReq 

修改实现类

 

删除上面的

运行管理端和客户端

原理

先扫描带有@JsonRpcService注解的接口,创建一个代理对象对应的路径就是主地址加上项目配置的地址,实际调用的时候会通过ObjectMapper将参数信息装换为JSON字符串,通过http的形式传递到服务端。

先在application.yml中添加debug级别日志配置

logging:level:com.googlecode.jsonrpc4j: debug

在ProductRpcService中初始化一个加载即运行方法

@PostConstruct
public void init(){findOne("T001");
}

得出结果如下

根据我们配置的信息去扫描RPC的服务接口,然后去创建代理,执行的时候就是把我们的操作信息转化成json字符串的格式传递到服务端,然后服务端使用json字符串的形式返回来

客户端唯一的入口就是RpcConfiguration里面创建的代理类的创建对象AutoJsonRpcClientProxyCreator

客户端的实现

  • 扫描我们的包路径下面添加了JsonRpcService这个注解的接口
  • 创建一个代理对象,对应的路径就是基础地址+注解里面配置的地址
  • 通过objectMapper将参数信息转换成Json字符串
  • 通过http的形式传递到服务端

服务端的实现

服务端的唯一 入口AutoJsonRpcServiceImplExporter,实现了BeanFactoryPostProcessor这个接口,会自动调用postProcessBeanFactory方法,这是spring的实现原理

简化封装

在seller和manager模块中都有JsonRpcConfiguration,在我的代码中这两处都被注释了,因为后面进行简化封装,但是为了让读者能感受到变化我就没删掉

将两个模块中的JsonRpcConfiguration写在util(或者开一个jsonRpc的模块)的configuration/JsonRpcConfiguration中

private static Logger LOG = LoggerFactory.getLogger(JsonRpcConfiguration.class);@Beanpublic AutoJsonRpcServiceImplExporter rpcServiceImplExporter(){return new AutoJsonRpcServiceImplExporter();}@Bean@ConditionalOnProperty(value = {"rpc.client.url","rpc.client.basePackage"}) //当配置文件中有这两个属性时才需要导出客户端public AutoJsonRpcClientProxyCreator rpcClientProxyCreator(@Value("${rpc.client.url}") String url,@Value("${rpc.client.basePackage}") String basePackage){AutoJsonRpcClientProxyCreator clientProxyCreator = new AutoJsonRpcClientProxyCreator();try {//配置基础urlclientProxyCreator.setBaseUrl(new URL(url));} catch (MalformedURLException e) {LOG.error("创建rpc服务地址错误");}//让它扫描api下rpc服务的包clientProxyCreator.setScanPackage(basePackage);return clientProxyCreator;}
  • 然后把两个模块中的JsonRpcConfiguration删除

  • util的build.gradle

  • dependencies {compile libs.jsonrpc
    }

    api模块中加上对util模块的依赖

  • 在seller的application.yml中加上

  • rpc:client:url: http://localhost:8081/manager/ #结尾记得加上/,否则会报错basePackage: com.qwl.api

    在resources/META-INF/spring.factories下

  • org.springframework.boot.autoconfigure.EnableAutoConfiguration =com.qwl.util.configuration.JsonRpcConfiguration

     

 

  相关解决方案