销售端作用:
用于与第三方交互的门户网关,这里进行安全控制,流量统计等,整合内部资源,对外提供相应的接口,完成产品的销售管理
功能:
- 产品查询
- 申购、赎回
- 对账
接口文档:
- 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