今天在学习别人做的一份工程项目的时候发现了一块新大陆,虽然很小,但作为入侵者的我觉得还是有必要从应用层面
对它进行记录,至于从源码原理
层面,那也得等定居久了,有了深入了解才来写嘛!
对了,忘了说了,这块新大陆就是dubbo filter
。
做过web开发的朋友都知道,在java EE
中都有过滤器这种东西,作用就是用来对请求前做些权限校验,同时过滤器也是有链式调用的,你可以声明多个Filter
,然后指定调用顺序即可!
我就废话不多说了,直接上代码。
一、工程目录结构
目录解释
- 1、这是一个Spring Boot应用程序,采用gradle进行构建,传统dubbo都采用maven进行配置,由于最近在学习 gradle,所以就使用gradle进行构建,差别不大!
- 2、
api
是服务定义接口,consumer
消费者,provider
服务提供者,filter
过滤器类,至于xml
文件,文件名已经告诉你它的作用啦!
二、上代码
DemoService.java
package com.example.DubboFilterTest.api;
public interface DemoService {
String sayHello(String name);
}
复制代码
Consumer.java
package com.example.DubboFilterTest.consumer;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.example.DubboFilterTest.api.DemoService;
public class Consumer {
public static void main(String[] args) {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext(new String[] { "dubbo-demo-consumer.xml" });
context.start();
DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy
while (true) {
try {
Thread.sleep(1000);
String hello = demoService.sayHello("world"); // call remote method
System.out.println(hello); // get result
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
}
复制代码
IpFilter.java
package com.example.DubboFilterTest.filter;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
public class IpFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
System.err.println("在这里做一些权限校验....");
return invoker.invoke(invocation);
}
}
复制代码
DemoServiceImpl.java
package com.example.DubboFilterTest.provider;
import com.alibaba.dubbo.rpc.RpcContext;
import com.example.DubboFilterTest.api.DemoService;
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) {
System.err.println(RpcContext.getContext().getRemoteHost() + "早上好!");
return "Hello " + RpcContext.getContext().getRemoteHost();
}
}
复制代码
Provider.java
package com.example.DubboFilterTest.provider;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Provider {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext(new String[] { "dubbo-demo-provider.xml" });
context.start();
System.in.read(); // press any key to exit
}
}
复制代码
com.alibaba.dubbo.rpc.Filter
IpFilter=com.example.DubboFilterTest.filter.IpFilter
复制代码
注意com.alibaba.dubbo.rpc.Filter
这个文件的位置要放在META-INF/dubbo
目录下,否则找不到
dubbo-demo-consumer
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="DubboFilterTest"/>
<dubbo:registry address="multicast://224.5.6.7:1234"/>
<dubbo:reference id="demoService" check="false" interface="com.example.DubboFilterTest.api.DemoService"/>
</beans>
复制代码
dubbo-demo-provider
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="DubboFilterTest"/>
<!-- 注意这里要配置filter属性,否则过滤器不生效 -->
<dubbo:provider filter="IpFilter"></dubbo:provider>
<!-- 注册中心就不采用zookeeper了,大家就不需要自己本地搭建zookeeper了,想要搭建zookeeper环境,也可以查阅我以往文章 -->
<dubbo:registry address="multicast://224.5.6.7:1234"/>
<dubbo:protocol name="dubbo" port="20880"/>
<bean id="demoService" class="com.example.DubboFilterTest.provider.DemoServiceImpl"/>
<dubbo:service interface="com.example.DubboFilterTest.api.DemoService" ref="demoService"/>
</beans>
复制代码
build.gradle
buildscript {
ext {
springBootVersion = '2.0.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')//配置Spring Boot依赖
compile(group: 'com.alibaba', name: 'dubbo', version: '2.5.3'){
exclude(module: 'spring')//排除dubbo中默认的Spring依赖(版本太低)
}
//配置dubbo依赖
runtime('org.springframework.boot:spring-boot-devtools')//配置热更新工具
testCompile('org.springframework.boot:spring-boot-starter-test')//测试工具
}
复制代码
运行程序:
先运行provider.java,再运行comsumer.java即可,如果需要启动SpringBoot应用,可以运行DubboFilterTestApplication.java
遇到的问题:
1、运行DubboFilterTestApplication.java
报以下错误:
说是没有该方法,经过亲自到依赖包中查看源码,发现确实没有该方法,考虑是引入dubbo包出错
解决方法:
在引入dubbo依赖时排除自带的spring模块,加入exclude(module: 'spring')//排除dubbo中默认的Spring依赖(版本太低)
2、运行完一次cunsumer
之后就抛以下异常:
原因:
这里不能写为null
解决方法:
之前说过,过滤器是链式调用的,调用完过滤器之后一定要将链条传递下去,因为dubbo
本身还有其它自己的filter
。
谢谢阅读,祝你生活愉快,学习进步,事业步步高升,迎娶白富美,走上人生巅峰!