加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

springboot-21-dubbo扩展点Filter和@activate

(2017-05-13 15:06:05)
分类: 微服务
接上文http://blog.sina.com.cn/s/blog_7d1968e20102ww6x.html

对于java web应用来说,spring的filter可以拦截web接口调用,但对于dubbo接口,spring的filter就不起作用了。
设想有这样一种场景,comsumer调用了provider的接口方法,comsumer中的异常类型是MyException(checked类型),而provider抛出的是RuntimeException(unchecked类型),所以我们需要在consumer调用provider的实现类方法之前将其拦截,然后调用方法,捕获RuntimeException并将其封装成MyException,然后返回给consumer,此时就需要dubbo的扩展点

一.首先增加dubbo-starter项目下关于filter配置
@Configuration
@ConditionalOnClass({Exporter.class, Invoker.class})
@PropertySource(value = "classpath:/application.properties")
public class DubboConfiguration {

    @Value("${dubbo.application.name}")
    private String applicationName;

    @Value("${spring.redis.host}")
    private String logger;

    @Value("${dubbo.registr.protocol}")
    private String protocol;

    @Value("${dubbo.registry.address}")
    private String registryAddress;

    @Value("${dubbo.protocol.name}")
    private String protocolName;

    @Value("${dubbo.protocol.port}")
    private int protocolPort;

    @Value("${dubbo.provider.timeout}")
    private int timeout;

    @Value("${dubbo.provider.retries}")
    private int retries;

    @Value("${dubbo.provider.delay}")
    private int delay;

    @Value("${dubbo.provider.filter}")
    private String providerFilter;


   
    @Bean
    public static AnnotationBean annotationBean(@Value("${dubbo.annotation.package}") String packageName) {
        AnnotationBean annotationBean = new AnnotationBean();
        annotationBean.setPackage(packageName);
        return annotationBean;
    }

   
    @Bean
    public ApplicationConfig applicationConfig() {
        // 当前应用配置
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName(this.applicationName);
        return applicationConfig;
    }

   
    @Bean
    public RegistryConfig registryConfig() {
        // 连接注册中心配置
        RegistryConfig registry = new RegistryConfig();
        registry.setProtocol(protocol);
        registry.setAddress(registryAddress);
        return registry;
    }

   
    @Bean
    public ProtocolConfig protocolConfig() {
        // 服务提供者协议配置
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName(protocolName);
        protocolConfig.setPort(protocolPort);
        protocolConfig.setThreads(200);
        System.out.println("默认protocolConfig:" + protocolConfig.hashCode());
        return protocolConfig;
    }

   
    @Bean(name="defaultProvider")
    public ProviderConfig providerConfig(ApplicationConfig applicationConfig, RegistryConfig registryConfig, ProtocolConfig protocolConfig) {
        ProviderConfig providerConfig = new ProviderConfig();
        providerConfig.setTimeout(timeout);
        providerConfig.setRetries(retries);
        providerConfig.setDelay(delay);
        providerConfig.setFilter(providerFilter);
        providerConfig.setApplication(applicationConfig);
        providerConfig.setRegistry(registryConfig);
        providerConfig.setProtocol(protocolConfig);
        return providerConfig;
    }

    public String getApplicationName() {
        return applicationName;
    }

    public void setApplicationName(String applicationName) {
        this.applicationName = applicationName;
    }

    public String getLogger() {
        return logger;
    }

    public void setLogger(String logger) {
        this.logger = logger;
    }

    public String getProtocol() {
        return protocol;
    }

    public void setProtocol(String protocol) {
        this.protocol = protocol;
    }

    public String getRegistryAddress() {
        return registryAddress;
    }

    public void setRegistryAddress(String registryAddress) {
        this.registryAddress = registryAddress;
    }

    public String getProtocolName() {
        return protocolName;
    }

    public void setProtocolName(String protocolName) {
        this.protocolName = protocolName;
    }

    public int getProtocolPort() {
        return protocolPort;
    }

    public void setProtocolPort(int protocolPort) {
        this.protocolPort = protocolPort;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public int getRetries() {
        return retries;
    }

    public void setRetries(int retries) {
        this.retries = retries;
    }

    public int getDelay() {
        return delay;
    }

    public void setDelay(int delay) {
        this.delay = delay;
    }

    public String getProviderFilter() {
        return providerFilter;
    }

    public void setProviderFilter(String providerFilter) {
        this.providerFilter = providerFilter;
    }
}

二. dubbo-provider项目下
1.使用filter和active创建dubbo扩展点的MyExceptionFilter

@Activate(group = Constants.PROVIDER, value = "exceptionfilter")
public class MyExceptionFilter implements Filter{
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        Result result = invoker.invoke(invocation);
        if(result.hasException() && GenericService.class != invoker.getInterface()) {
            Throwable throwable = result.getException();
            if(throwable.getClass().equals(RuntimeException.class)) {
                RuntimeException exception = (RuntimeException) throwable;
                return new MyExceptionResult(exception);
            }
        }
        return result;
    }

    private static class MyExceptionResult implements Result{
        private MyException e;

        MyExceptionResult(RuntimeException r) {
            this.e = new MyException(r.getMessage() + "-------Filter");
        }

        @Override
        public Object getValue() {
            return null;
        }

        @Override
        public Throwable getException() {
            return e;
        }

        @Override
        public boolean hasException() {
            return true;
        }

        @Override
        public Object recreate() throws Throwable {
            return null;
        }

        @Override
        public Object getResult() {
            return null;
        }

        @Override
        public Map<String, String> getAttachments() {
            return null;
        }

        @Override
        public String getAttachment(String s) {
            return null;
        }

        @Override
        public String getAttachment(String s, String s1) {
            return null;
        }
    }
}

关键:Activate注解中的value指向下文com.alibaba.dubbo.rpc.Filter中的exceptionfilter

2.创建com.alibaba.dubbo.rpc.Filter

在resources下创建META-INF/dubbo/com.alibaba.dubbo.rpc.Filter,内容为:exceptionfilter=com.scn7th.filter.MyExceptionFilter

3.在appication.properties中增加dubbo.provider.filter=exceptionfilter


dubbo.application.name=provider
dubbo.application.logger=slf4j

dubbo.annotation.package=com.scn7th.provider

dubbo.protocol.name=dubbo
dubbo.protocol.port=20881
dubbo.protocol.accessLog=true

dubbo.provider.timeout=3000

dubbo.provider.retries=1
dubbo.provider.delay=-1
dubbo.provider.filter=exceptionfilter

dubbo.registr.protocol=zookeeper

dubbo.registry.address=127.0.0.1:2181
dubbo.registry.register=true
dubbo.registry.subscribe=true

dubbo.

spring.redis.host=

4.抛给consumer的MyException

public class MyException extends Exception{
    public MyException(String message) {
        super(message);
    }
}

5.dubbo接口及其实现类

public interface IDubboDemoService {
    String sayHello(String name) throws MyException;
    String sayYourAge(int age) throws MyException;
}

@Component
@Service(version="1.0.0")
public class DubboDemoServiceImpl implements IDubboDemoService {

    @Override
    public String sayHello(String name) throws MyException {
        if(name.equals("Tom")) {
            throw new RuntimeException("The Name is Tom! He is not a good man!");
        }
        return "hello " + name;
    }

    @Override
    public String sayYourAge(int age) throws MyException{
        return null;
    }

}

三、dubbo-consumer项目
1.dubbo服务调用

@Service
public class MyService {
    @Reference(version = "1.0.0")
    private IDubboDemoService dubboDemoService;

    public String hello(String name) throws MyException {
        String result = dubboDemoService.sayHello(name);
        return result;
    }
}

2.controller接收异常

@RestController
@RequestMapping("/")
public class MyController {
    @Autowired
    private MyService myService;

    @RequestMapping("/user/name/{name}")
    public String test(@PathVariable String name) {
        try {
            String result = myService.hello(name);
            return result;
        }catch (MyException e) {
            return e.getMessage();
        }
    }
}

测试:
在浏览器中输入http://localhost:8088/user/name/Tom

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有