spring boot2整合dubbox全注解
Posted shaozm
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring boot2整合dubbox全注解相关的知识,希望对你有一定的参考价值。
前题
dubbox是dubbo的一个升级版,简单说就是本来dubbo是阿里开发的,现在阿里不维护了,当当网拿过去继续开发。本来阿里的dubbo维护到2.6版本,而再高版本的都是当当网维护的就叫成dubbox了。
dubbo的机制是这样的,首先有一个数据中心zookeeper,这里zookeeper的搭建可以参考 zookeeper集群搭建 这篇博客,数据中心的职能只有一个,就是数据的存储。
如图,提供者将自己的服务信息注册到zookeeper中,消费者从zookeeper中取得提供者的服务信息,包括提供者的ip,端口,服务类名参数,这样就可以直接请求提供者所在的服务器,完成调用。
一、dubbox maven导包
1、编译安装
因为dubbox没有编译发布,所以不能够通过maven拉取远程jar包,需要自己编译安装到自己的本地Maven仓库中。从 dubbox github地址 下载项目,在项目根目录下运行
mvn install -Dmaven.test.skip=true 或者在powershell中运行 mvn clean install package ‘-Dmaven.test.skip=true‘
2、项目构建
创建一个maven项目,项目下创建三个module,如图 (这个dubbox是我自己的项目命名,不是官方的dubbox)
这里需要注意,因为是模块项目,所以在dubboapi等module中的pom的parent是dubbox,但是我们的springboot也需要用spring-boot-starter-parent控制版本,所以spring-boot-starter-parent需要定义在dubbox的pom中,继承下去,但是我在dubbox中控制子模块的jar包版本,这会导致一个问题,就是我在dubbox中的版本控制把spring-boot-starter-parent中的版本给冲突掉了。具体情况下面会说。
dubbox的pom
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>xin.shaozeming</groupId> <artifactId>dubbox</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>dubboxserver</module> <module>dubboxclient</module> <module>dubboxapi</module> </modules> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.BUILD-SNAPSHOT</version> </parent> <dependencyManagement> <dependencies> <!-- dubbo --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.8.4</version> </dependency> <!--zookeeper --> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <exclusions> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> <version>0.1</version> </dependency> <dependency> <groupId>net.dubboclub</groupId> <artifactId>netty4</artifactId> <version>0.0.6</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.9</version> <exclusions> <exclusion> <groupId>io.netty</groupId> <artifactId>netty</artifactId> </exclusion> </exclusions> </dependency> <!--rest api--> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxrs</artifactId> <version>3.0.7.Final</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> <version>3.0.7.Final</version> </dependency> <!-- 如果要使用json序列化 --> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jackson-provider</artifactId> <version>3.0.7.Final</version> </dependency> <!-- 如果要使用xml序列化 --> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxb-provider</artifactId> <version>3.0.7.Final</version> </dependency> <!--kryo序列化--> <dependency> <groupId>com.esotericsoftware.kryo</groupId> <artifactId>kryo</artifactId> <version>2.24.0</version> </dependency> <dependency> <groupId>de.javakaffee</groupId> <artifactId>kryo-serializers</artifactId> <version>0.26</version> </dependency> <!-- 如果要使用tomcat server --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-logging-juli</artifactId> <version>8.0.11</version> </dependency> <!-- 如果要使用netty server --> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-netty</artifactId> <version>3.0.7.Final</version> <exclusions> <exclusion> <groupId>io.netty</groupId> <artifactId>netty</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </dependencyManagement> <!--<!– Package as an executable jar –>--> <build> <finalName>dubbox</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <!-- Add Spring repositories --> <!-- (you don‘t need this if you are using a .RELEASE version) --> <repositories> <repository> <id>spring-snapshots</id> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <url>https://repo.spring.io/milestone</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-snapshots</id> <url>https://repo.spring.io/snapshot</url> </pluginRepository> <pluginRepository> <id>spring-milestones</id> <url>https://repo.spring.io/milestone</url> </pluginRepository> </pluginRepositories> </project>
dubboxapi的pom
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>dubbox</artifactId> <groupId>xin.shaozeming</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>dubbox.api</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> <scope>test</scope> </dependency> <!--zookeeper --> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> </dependency> <dependency> <groupId>net.dubboclub</groupId> <artifactId>netty4</artifactId> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-logging-juli</artifactId> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-netty</artifactId> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxrs</artifactId> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> </dependency> <!--<!– dubbo –>--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> </dependency> <!-- 如果要使用json序列化 --> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jackson-provider</artifactId> </dependency> <!-- 如果要使用xml序列化 --> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxb-provider</artifactId> </dependency> <dependency> <groupId>com.esotericsoftware.kryo</groupId> <artifactId>kryo</artifactId> </dependency> <dependency> <groupId>de.javakaffee</groupId> <artifactId>kryo-serializers</artifactId> </dependency> </dependencies> </project>
dubboxserver和dubboxclient的pom
<dependencies> <dependency> <groupId>xin.shaozeming</groupId> <artifactId>dubbox.api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
仔细看dubbox和dubboxapi中的jar包,dubboxapi中有 tomcat-embed-core 和 validation-api两个jar包,而dubbox的dependencyManagem中并没有控制版本,这是因为这两个包的版本是spring boot parent里面版本控制继承的tomcat-embed-core springboot2默认的是版本是9,如果这里改成8版本。会出现这样的错
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean. at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:155) ~[spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:540) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT] at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT] at xin.shaozeming.dubboxclient.ClientStart.main(ClientStart.java:17) [classes/:?] Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean. at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:204) ~[spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:178) ~[spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:152) ~[spring-boot-2.1.0.BUILD-20181030.064057-619.jar:2.1.0.BUILD-SNAPSHOT] ... 8 more
这里说这个是希望读者对这个问题注意一下,实际上这里没办法用tomcat,因为如果把这个包改成9版本的,dubbox里面启动tomcat使用的api又有问题了,不过这里服务器可以用netty,这个服务器是消费者和提供者之间通讯的服务器,tomcat和netty的性能没什么差距。所以以上关于tomcat服务器的jar包都可以删掉了,当然不删也没影响。
三、代码实现
provider提供者方面
先看看xml的实现
<dubbo:application name="provider"/> <dubbo:registry address="zookeeper://47.105.202.148:2181"/>
<dubbo:annotation package="xin.shaozeming.dubboxserver.api" />
<dubbo:protocol name="rest" port="8888" threads="500" contextpath="services" server="netty" accepts="500"/>
<dubbo:service interface="xin.shaozeming.dubboxapi.service.UserService" ref="userService" protocol="rest"/>
javaconfig的实现
/**
* @author: 邵泽铭
* @date: 2018/12/21
* @description:
**/
@Configuration
public class config {
private static final String APPLICATION_NAME = "provider";
private static final String REGISTRY_ADDRESS = "zookeeper://47.105.202.148:2181";
private static final String ANNOTATION_PACKAGE = "xin.shaozeming.dubboxserver.api";
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName(APPLICATION_NAME);
return applicationConfig;
}
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress(REGISTRY_ADDRESS);
return registryConfig;
}
@Bean
public ProtocolConfig protocolConfig(){
ProtocolConfig protocolConfig=new ProtocolConfig();
protocolConfig.setName("rest");
protocolConfig.setPort(8887);
protocolConfig.setSerialization("kryo");
protocolConfig.setOptimizer(SerializationOptimizerImpl.class.getName());
// protocolConfig.setHost("192.168.0.244");
protocolConfig.setServer("netty");
protocolConfig.setThreads(500);
protocolConfig.setAccepts(500);
protocolConfig.setExtension(
"com.alibaba.dubbo.rpc.protocol.rest.support.LoggingFilter"
);
return protocolConfig;
}
@Bean
public AnnotationBean annotationBean() {
AnnotationBean annotationBean = new AnnotationBean();
annotationBean.setPackage(ANNOTATION_PACKAGE);
return annotationBean;
}
}
以下是提供者的接口注解,这里这个service不是spring的service,是dubbox里提供的注解
@Service(interfaceClass = UserService.class) public class UserServiceProvider implements UserService { @Override public User getUser() { User user=new User(); user.setUserName("szm"); user.setPassword("123456"); return user; } }
而rest的注解是需要配置在 UserService 上的,因为 rest的注解不仅仅是提供者接收请求的时候需要,消费者发起请求的时候也需要,之前就是因为这个问题,加上消费者端上没开日志,找了好久的bug。
UserService接口我是定义在dubboxapi里面的
package xin.shaozeming.dubboxapi.service; import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType; import xin.shaozeming.dubboxapi.po.User; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; /** * * Created with IntelliJ IDEA. * * User: 邵泽铭 * * Date: 2018/12/21 * * Time: 9:50 * * Description: * */ @Path("user") public interface UserService { @GET @Path("getUser") @Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML}) @Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8}) public User getUser(); }
到这里提供者就配置好了,再看消费者端
xml版本
<dubbo:application name="consumer" /> <dubbo:registry address="zookeeper://47.105.202.148:2181" check="false" /> <!--uncomment this if you want to test dubbo‘s monitor--> <!--<dubbo:monitor protocol="registry"/>--> <dubbo:reference id="userService" interface="xin.shaozeming.dubboxapi.service.UserService" />
javaconfig
@Configuration public class config { private static final String APPLICATION_NAME = "consumer"; private static final String REGISTRY_ADDRESS = "zookeeper://47.105.202.148:2181"; private static final String ANNOTATION_PACKAGE = "xin.shaozeming.dubboxclient.controller"; @Bean public ApplicationConfig applicationConfig() { ApplicationConfig applicationConfig = new ApplicationConfig(); applicationConfig.setName(APPLICATION_NAME); return applicationConfig; } @Bean public RegistryConfig registryConfig() { RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setAddress(REGISTRY_ADDRESS); return registryConfig; } @Bean public AnnotationBean annotationBean() { AnnotationBean annotationBean = new AnnotationBean(); annotationBean.setPackage(ANNOTATION_PACKAGE); return annotationBean; } }
@RestController public class UserController { @Reference(interfaceClass=UserService.class) private UserService userService; @GetMapping("/user") public User getUser(){ return userService.getUser(); } }
到此消费者端就也配置好了
关于duubox的日志,不知道为什么log4j配置了也实现不了,不过后来翻了翻代码,发现可以通过系统属性选择日志实现,start类里面加入以下代码,spring boot整合log4j2可以看这篇文章 sprintboot2整合log4j2
System.setProperty("dubbo.application.logger","slf4j");
还有一个问题,就是对于provider提供者来说,只需要一个netty服务器端口提供服务就可以了,而用springboot启动的时候,springboot会启动一个web,加上netty就是两个服务器,这显然没什么必要,所以可以将spring boot设置成不以web启动方式启动
/** * @author: 邵泽铭 * @date: 2018/12/21 * @description: **/ @SpringBootApplication //@ImportResource("classpath:dubbo-provider.xml") public class ServerStart { public static void main(String[] args) throws Exception{ System.setProperty("org.springframework.boot.logging.LoggingSystem","org.springframework.boot.logging.log4j2.Log4J2LoggingSystem"); System.setProperty("dubbo.application.logger","slf4j"); new SpringApplicationBuilder(ServerStart.class) .web(WebApplicationType.NONE) .run(args); } }
一切准备完成之后,启动运行
大功告成!!!
demo项目github地址 https://github.com/1160809039/springboot2-dubbox
以上是关于spring boot2整合dubbox全注解的主要内容,如果未能解决你的问题,请参考以下文章
spring boot2 整合Mybatis (特别完整!)