- RpcContext
利用RpcContext實現(xiàn)consumer和provicer參數(shù)傳遞例如:
消費端:
RpcContext.getContext().setAttachment("bizId", "小程序");
//調用dubbo
activityAdminFacade.queryExchangeActivitiesByOption(option);
服務端:
@Override
public PageResult<ExchangeActivityDTO> queryExchangeActivitiesByOption(ActivityQueryOption option) {
String userInfo = RpcContext.getContext().getAttachment("bizId");
}
實際上rpcContext也是用到了dubbo filter 特性。ConsumerContextFilter attachment中參數(shù)會直接帶到invocation對象,傳遞至provider端搓蚪。finaly中RpcContext.getContext().clearAttachments(); 每次調用會直接清除。所以需要我們每次調用dubbo服務接口前都要設置setAttachment丁鹉。
@Activate(group = Constants.CONSUMER, order = -10000)
public class ConsumerContextFilter implements Filter {
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
RpcContext.getContext()
.setInvoker(invoker)
.setInvocation(invocation)
.setLocalAddress(NetUtils.getLocalHost(), 0)
.setRemoteAddress(invoker.getUrl().getHost(),
invoker.getUrl().getPort());
if (invocation instanceof RpcInvocation) {
((RpcInvocation)invocation).setInvoker(invoker);
}
try {
return invoker.invoke(invocation);
} finally {
RpcContext.getContext().clearAttachments();
}
}
}
- 有的時候我們不想每次調用dubbo接口都要去設置RpcContext妒潭。所以需要我們自己去實現(xiàn)定義一個dubbo filter悴能。當然我們也可以直接修改源碼哈哈(不推薦)
2.1 范圍:一個線程上下文內(nèi)
public class BizIdUtils {
private static final ThreadLocal<String> Cache
= new ThreadLocal<String>();
public static String getBizId() {
return Cache.get();
}
public static void setBizId(String bizId) {
Cache.set(bizId);
}
public static void clear() {
Cache.remove();
}
}
package com.test.dubbo;
public class TraceIdFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
String traceId = RpcContext.getContext().getAttachment("BizId");
if ( !StringUtils.isEmpty(BizId) ) {
// *) 從RpcContext里獲取bizId并保存
BizIdUtils.setBizId(bizId);
} else {
// *) 交互前重新設置traceId, 避免信息丟失
RpcContext.getContext().setAttachment("bizId", BizIdUtils.getBizId());
}
// *) 實際的rpc調用
return invoker.invoke(invocation);
}
}
BizIdUtils ThreadLocal就是用來保存當前線程的變量值。所以在一個線程上下文中雳灾,只需要在第一次設置RpcContext.setAttachment即可漠酿。比如web的一次請求。
2.2 范圍:設置整個consumer端
public class MyFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
RpcContext.getContext().setAttachment("bizId", "電商");
Result result = invoker.invoke(invocation);
return result;
}
}
這樣我們consumer端就不需再調用RpcContext了谎亩。
- 如何使filter生效
我們自定義filter話炒嘲,需要在resource下創(chuàng)建 /META-INFO/dubbo/com.alibaba.dubbo.rpc.Filter
文件內(nèi)容為
helloFilter=com.fcbox.mall.item.MyFilter
image.png
helloFilter為自定義的名稱
然后再application.properties中配置
springboot:spring.dubbo.consumer.filter=helloFilter
spring dubbo需要我們自己去實現(xiàn)java配置,這個filter就存放在DubboProperties中consumerConfig中filter中:
@Configuration
@EnableConfigurationProperties(DubboProperties.class)
public class DubboAutoConfiguration {
@Autowired
private DubboProperties dubboProperties;
@Autowired
private Environment environment;
@Bean
public ApplicationConfig requestApplicationConfig() {
ApplicationConfig applicationConfig = dubboProperties.getApplication();
if(applicationConfig == null){
applicationConfig = new ApplicationConfig();
}
return applicationConfig;
}
@Bean
@Primary
public RegistryConfig requestRegistryConfig() {
RegistryConfig registryConfig = dubboProperties.getRegistry();
if(registryConfig == null){
registryConfig = new RegistryConfig();
}
return registryConfig;
}
@Bean
public ProtocolConfig requestProtocolConfig() {
ProtocolConfig protocolConfig = dubboProperties.getProtocol();
if(protocolConfig == null){
protocolConfig = new ProtocolConfig();
}
//獲取啟動參數(shù),優(yōu)先級最高
String host=environment.getProperty("server.address");
if(StringUtils.isNotEmpty(host)){
protocolConfig.setHost(host);
}
return protocolConfig;
}
@Bean
public MonitorConfig requestMonitorConfig() {
MonitorConfig monitorConfig = dubboProperties.getMonitor();
if(monitorConfig == null){
monitorConfig = new MonitorConfig();
}
return monitorConfig;
}
@Bean
public ProviderConfig requestProviderConfig(){
ProviderConfig providerConfig = dubboProperties.getProvider();
if(providerConfig == null){
providerConfig = new ProviderConfig();
}
return providerConfig;
}
@Bean
public ModuleConfig requestModuleConfig(){
ModuleConfig moduleConfig = dubboProperties.getModule();
if(moduleConfig == null){
moduleConfig = new ModuleConfig();
}
return moduleConfig;
}
@Bean
public MethodConfig requestMethodConfig(){
MethodConfig methodConfig = dubboProperties.getMethod();
if(methodConfig == null){
methodConfig = new MethodConfig();
}
return methodConfig;
}
@Bean
public ConsumerConfig requestConsumerConfig(){
ConsumerConfig consumerConfig = dubboProperties.getConsumer();
if(consumerConfig == null){
consumerConfig = new ConsumerConfig();
}
return consumerConfig;
}
}
public class DubboProperties {
private String scan;
private ApplicationConfig application;
private RegistryConfig registry;
private ProtocolConfig protocol;
private MonitorConfig monitor;
private ProviderConfig provider;
private ModuleConfig module;
private MethodConfig method;
private ConsumerConfig consumer;
consumer配置類:com.alibaba.dubbo.config.ConsumerConfig