用于与第三方交互的门户网关,这里进行安全控制,流量统计等,整合内部资源,对外提供相应的接口,完成产品的销售管理
功能:
接口文档:
主要步骤
常见错误:
在配置类中对应的配置内容未添加@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 idList;
private BigDecimal minRewardRate;
private BigDecimal maxRewardRate;
private List 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 query(ProductRpcReq req);
//查询单个产品
Product findOne(String id);
}
在管理端添加依赖
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);
@Autowired
private ProductService productService;
@Override
public Page query(ProductRpcReq req) {
LOG.info("查询多个产品,请求{}",req);
Page result = productService.query(req.getIdList(),req.getMinRewardRate(),
req.getMaxRewardRate(),req.getStatusList(),req.getPageable());
LOG.info("查询多个产品,结果{}",result);
return result;
}
@Override
public Product findOne(String id) {
LOG.info("查询产品详情,请求{}",id);
Product result = productService.findOne(id);
LOG.info("查询产品详情,结果{}",result);
return result;
}
}
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 {
@Autowired
private ProductRpc productRpc;
private static Logger LOG = LoggerFactory.getLogger(RpcConfiguration.class);
//查询全部产品
public List findAll(){
ProductRpcReq req = new ProductRpcReq();
List 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 result = productRpc.query(req);
LOG.info("rpc查询全部产品,结果:{}",result);
return result.getContent();
}
@PostConstruct
public void test(){
findAll();
}
//查询单个产品
public Product findOne(String id){
LOG.info("rpc查询单个产品,请求:{}",id);
Product result = productRpc.findOne(id);
LOG.info("rpc查询单个产品,结果:{}",result);
return result;
}
@PostConstruct
public 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);
@Bean
public 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
客户端的实现
服务端的实现
服务端的唯一 入口AutoJsonRpcServiceImplExporter,实现了BeanFactoryPostProcessor这个接口,会自动调用postProcessBeanFactory方法,这是spring的实现原理
在seller和manager模块中都有JsonRpcConfiguration,在我的代码中这两处都被注释了,因为后面进行简化封装,但是为了让读者能感受到变化我就没删掉
将两个模块中的JsonRpcConfiguration写在util(或者开一个jsonRpc的模块)的configuration/JsonRpcConfiguration中
private static Logger LOG = LoggerFactory.getLogger(JsonRpcConfiguration.class);
@Bean
public 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 {
//配置基础url
clientProxyCreator.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