Dubbo:整合 Spring boot


#Dubbo#


示例

项目结构

.
├── build.gradle
├── settings.gradle
├── contract
│   ├── src
│       └── main
│           └── java
│               └── demo
│                   └── contract
│                       └── DemoService.java
├── provider
│   ├── src
│       └── main
│           ├── java
│           │   └── demo
│           │       └── provider
│           │           ├── DemoServiceImpl.java
│           │           └── ProviderMain.java
│           └── resources
│               ├── dubbo-provider.xml
│               └── log4j.properties
└── spring-boot-web
    └── src
        └── main
            ├── java
            │   └── demo
            │       └── web
            │           ├── DemoController.java
            │           └── WebApplication.java
            └── resources
                ├── dubbo-consumer.xml
                └── log4j.properties

build.gradle

build.gradle 内容:

group 'com.example'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8


buildscript {

    ext {
        springBootVersion = '2.1.4.RELEASE'
        aliyunMavenUrl = 'https://maven.aliyun.com/repository/public/'
    }

    repositories {
      maven { url "${aliyunMavenUrl}" }
      mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

ext {
    dubboVersion = '2.7.1'
    zookeeperVersion = '3.4.10'
    lombokVersion = '1.18.0'
    junitVersion = '4.12'
}


allprojects {
    apply plugin: 'java'

    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'

    repositories {
        maven { url "${aliyunMavenUrl}" }
        mavenCentral()
    }

    configurations {
        all*.exclude group:'ch.qos.logback', module: 'logback-classic' // 去掉 logback,保留 log4j
    }

    dependencies {
        compile "org.projectlombok:lombok:${lombokVersion}"
    }

}

// 配置子项目 contract
project(":contract") {

    dependencies {

        testCompile "junit:junit:$junitVersion"

    }
}

// 配置子项目 provider
project(":provider") {

    dependencies {
      compile project(":contract")
      compile "org.springframework.boot:spring-boot-starter:${springBootVersion}"
      compile "org.apache.dubbo:dubbo:${dubboVersion}"
      compile "org.apache.dubbo:dubbo-dependencies-zookeeper:${dubboVersion}"

      testCompile "junit:junit:${junitVersion}"
    }

}


// 配置子项目 web
project(":spring-boot-web") {

    dependencies {
        compile project(":contract")
        compile "org.springframework.boot:spring-boot-starter-web:${springBootVersion}"
        compile ("org.apache.dubbo:dubbo:${dubboVersion}")
        compile "org.apache.dubbo:dubbo-dependencies-zookeeper:${dubboVersion}"

        testCompile "junit:junit:${junitVersion}"
    }

}

log4j.properties

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] %X{IP} - %m%n

dubbo.properties

dubbo.application.qos.port=33333

contract 模块

DemoService 接口:

package demo.contract;

public interface DemoService {

    String sayHello(String name);

}

provider 模块

DemoServiceImpl 类:

package demo.provider;

import demo.contract.DemoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class DemoServiceImpl implements DemoService {

    public String sayHello(String name) {
        log.info("请求数据: {}", name);
        return "Hello, " + name;
    }

}

ProviderMain 类:

package demo.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

@SpringBootApplication
@ImportResource(locations={"classpath:dubbo-provider.xml"})
public class ProviderMain {

    public static void main(String[] args) throws IOException {
        SpringApplication.run(ProviderMain.class, args);
        System.in.read();
    }

}

为什么要加System.in.read();,不加的话,程序很快停止运行。

还有无让程序长久运行的其他方法 ?

方法1:增加若干Controller,让程序即提供HTTP服务,也提供Dubbo服务。注意,两个服务的端口是不一样的。

方法2:使用 dubbo 官方提供的 spring boot starter,https://github.com/apache/incubator-dubbo-spring-boot-project 。

dubbo-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"
       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="hello-world-app"></dubbo:application>

    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <dubbo:protocol name="dubbo" port="20880"/>

    <dubbo:service interface="demo.contract.DemoService" class="demo.provider.DemoServiceImpl"/>

</beans>

spring-boot-web 模块

DemoController 类:

package demo.web;

import demo.contract.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    @Autowired
    private DemoService demoService;

    @RequestMapping("/hello")
    public String hello(@RequestParam(value="name", defaultValue="World") String name) {
        return demoService.sayHello(name);
    }

}

WebApplication 类:

package demo.web;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
@ImportResource(locations={"classpath:dubbo-consumer.xml"})
public class WebApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebApplication.class, args);
    }

}

dubbo-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="consumer-of-helloworld-app"/>
    <dubbo:consumer timeout="5000" />

    <dubbo:registry address="zookeeper://127.0.0.1:2181" check="false"/>
    <dubbo:reference id="demoService" interface="demo.contract.DemoService" check="false"/>

</beans>

测试

启动 zookeeper:

$ zkServer.sh start

运行 provider 模块中的 ProviderMain 类,然后运行 web 模块中的 WebApplication 类。

打开浏览器访问 http://127.0.0.1:8080/hello,会看到Hello, World


( 本文完 )