基于Dubbo的Hessian协议实现远程调用
前言
创建两个项目,一个provider提供dubbo服务,一个client消费服务。
源码地址:https://gitee.com/qianxunclub/java-demo/tree/master/chapter-2
目录结构如下:
$ tree -I target
chapter-2
├── api
│ ├── pom.xml
│ └── src
│ └── main
│ └── java
│ └── com
│ └── qianxunclub
│ └── chapter2
│ └── api
│ └── DemoService.java
├── client
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── qianxunclub
│ │ └── chapter2
│ │ └── client
│ │ └── ClientMain.java
│ └── resource
│ ├── demo-consumer.xml
│ └── log4j.properties
├── pom.xml
└── provider
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── qianxunclub
│ └── chapter2
│ └── provider
│ ├── DemoServiceImpl.java
│ └── ProviderMain.java
└── resource
├── META-INF
│ └── spring
│ └── demo-provider.xml
└── log4j.properties
1、在provider的pom.xml
中引入maven包
<dependency>
<groupId>com.qianxunclub</groupId>
<artifactId>chapter-2-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.26</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
2、在provider中添加配置文件
在provider的resource/META-INF/spring
下建个xml, 例如:demo-provider.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.qianxunclub.chapter2.provider"/>
<!--当前项目在整个分布式架构里面的唯一名称,计算依赖关系的标签-->
<dubbo:application name="demo-provider" owner="lily"/>
<!--dubbo这个服务所要暴露的服务地址所对应的注册中心-->
<dubbo:registry protocol="zookeeper" address="qianxunclub.com:2181"/>
<!--当前服务发布所依赖的协议;WebService、Thrift、Hessian、http-->
<dubbo:protocol name="dubbo" port="20880"/>
<!--增加hessian协议-->
<dubbo:protocol name="hessian" port="8090" server="jetty" />
</beans>
ps:该xml文件默认需要建在resource/META-INF/spring文件夹下。多说无益,上dubbo源码。
从ProviderMain.java中
Main.main(args);
点进去main
方法,查看main
方法中Container
接口的其中之一的实现类SpringContainer
中可以看到默认路径:
public static final String DEFAULT_SPRING_CONFIG = "classpath*:META-INF/spring/*.xml";
也可以自定义路径:
public void start() {
String configPath = ConfigUtils.getProperty("dubbo.spring.config");
if(configPath == null || configPath.length() == 0) {
configPath = "classpath*:META-INF/spring/*.xml";
}
context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"));
context.start();
}
点进去getProperty方法,一路ctrl下去,可以看到ConfigUtils.java中自定义路径的规则:
public static Properties getProperties() {
if(PROPERTIES == null) {
Class var0 = ConfigUtils.class;
synchronized(ConfigUtils.class) {
if(PROPERTIES == null) {
String path = System.getProperty("dubbo.properties.file");
if(path == null || path.length() == 0) {
path = System.getenv("dubbo.properties.file");
if(path == null || path.length() == 0) {
path = "dubbo.properties";
}
}
PROPERTIES = loadProperties(path, false, true);
}
}
}
return PROPERTIES;
}
在resource下创建dubbo.properties文件,内容如下:
#dubbo配置的自定义路径
dubbo.spring.config=classpath*:hello/*.xml
3、在api模块中添加对外抛出的接口
public interface DemoService {
String sayHello(String name);
}
并在provider中添加该接口的实现类:
import com.qianxunclub.chapter2.api.DemoService;
import org.springframework.stereotype.Service;
@Service("demoService")
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
return "hello:"+name;
}
}
在demo-provider.xml
中,添加 对外抛出接口:
<!--服务发布的配置,需要暴露的服务接口-->
<dubbo:service
interface="com.qianxunclub.chapter2.api.DemoService"
ref="demoService" protocol="hessian"/>
4、调用provider中的main方法
import com.alibaba.dubbo.container.Main;
public class ProviderMain {
public static void main(String[] args) {
try {
Main.main(args);
} catch (Exception e){
System.out.println(e);
}
}
}
在provider控制台,会打印:
[DUBBO] Register: hessian://192.168.103.163:8090/com.qianxunclub.chapter2.provider.DemoService?anyhost=true&application=demo-provider&dubbo=2.5.3&interface=com.qianxunclub.chapter2.provider.DemoService&methods=sayHello&owner=lily&pid=6656&server=jetty&side=provider×tamp=1527126914293, dubbo version: 2.5.3, current host: 127.0.0.1
进入zookeeper客户端,查看服务:
5、在client的pom.xml
中引入maven包
<dependency>
<groupId>com.qianxunclub</groupId>
<artifactId>chapter-2-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
6、在client中添加配置文件
在provider的resource/META-INF
下建个xml, 例如:demo-consumer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--当前项目在整个分布式架构里面的唯一名称,计算依赖关系的标签-->
<dubbo:application name="demo-client" owner="mic"/>
<!--dubbo这个服务所要暴露的服务地址所对应的注册中心-->
<dubbo:registry protocol="zookeeper" address="qianxunclub.com:2181"/>
<!--当前服务发布所依赖的协议;webserovice、Thrift、Hessain、http-->
<dubbo:protocol name="dubbo" port="20881"/>
<!--服务发布的配置,需要暴露的服务接口-->
<dubbo:reference
interface="com.qianxunclub.chapter2.api.DemoService"
id="demoService"/>
</beans>
7、调用client中的main方法
import com.qianxunclub.chapter2.api.DemoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ClientMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo-consumer.xml");
DemoService demoService = context.getBean(DemoService.class);
String r = demoService.sayHello("zhangsan");
System.out.println(r);
}
}
报错:
Unsupported protocol hessian in notified url: hessian://192.168.103.163:8090/com.qianxunclub.chapter2.api.DemoService?anyhost=true&application=demo-provider&dubbo=2.5.3&interface=com.qianxunclub.chapter2.api.DemoService&methods=sayHello&owner=lily&pid=11648&server=jetty&side=provider×tamp=1527152915485 from registry qianxunclub.com:2181 to consumer 192.168.103.163, supported protocol: [dubbo, injvm, mock, redis, registry, rmi, thrift]
原来是client端少引了个hessian依赖,加上:
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
再次启动,会看到控制台打印了:hello:zhangsan。
大功告成!