Java web项目创建笔记27 之《整合dubbo》

dubbo是一个rpc框架,提供了远程方法调用的功能
需要3个角色:注册中心、服务提供方、服务消费方
注册中心用:nacos
服务提供方名称:dubbo-provider-demo
服务消费方名称:dubbo-consumer-demo
dubbo使用spring装配有两种配置方法,注解驱动和spring xml文件配置,这里使用xml文件

1、pom文件添加依赖

<dubbo.version>2.6.9</dubbo.version>
<dubbo.spring.version>1.0.11</dubbo.spring.version>
<dubbo.registry.nacos.version>2.6.7</dubbo.registry.nacos.version>
<!-- dubbo依赖 -->
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>dubbo</artifactId>
	<version>${dubbo.version}</version>
</dependency>
<!-- dubbo使用spring装配方式 -->
<dependency>
	<groupId>com.alibaba.spring</groupId>
	<artifactId>spring-context-support</artifactId>
	<version>${dubbo.spring.version}</version>
</dependency>
<!-- dubbo nacos registry依赖 -->
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>dubbo-registry-nacos</artifactId>
	<version>${dubbo.registry.nacos.version}</version>
</dependency>

2、在webapp2_module1模块
1)添加包com.study.module1.dubbo.resource
2)在该包下,添加服务接口,DemoService.java

package com.study.module1.dubbo.resource;

public interface DemoService {
	
	String echo(String msg);
}

3)添加包com.study.module1.dubbo.resource.impl
4)在该包下,添加服务接口实现类,DemoServiceImpl.java

package com.study.module1.dubbo.resource.impl;

import com.alibaba.dubbo.rpc.RpcContext;
import com.study.module1.dubbo.resource.DemoService;

public class DemoServiceImpl implements DemoService {

	@Override
	public String echo(String msg) {
		RpcContext rpcContext = RpcContext.getContext();
		// 获取当前服务配置信息
		String application = RpcContext.getContext().getUrl().getParameter("application");
		return String.format("Service [name :%s , port : %d] %s say : Hello,%s", 
				application, 
				rpcContext.getLocalPort(),
				rpcContext.getMethodName(), msg);
	}

}

3、webapp2_web模块src/main/resources
1)添加服务提供方配置文件,spring-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://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://dubbo.apache.org/schema/dubbo
           http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="dubbo-provider-demo"/>

    <!-- 使用 Nacos 注册中心 -->
    <dubbo:registry address="nacos://172.0.0.1:8848"/>
    <!-- 如果要使用自己创建的命名空间可以使用下面配置 -->
    <!-- <dubbo:registry address="nacos://127.0.0.1:8848?namespace=5cbb70a5-xxx-xxx-xxx-d43479ae0932" /> -->

    <!-- 用dubbo协议在随机端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="-1"/>

    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.study.module1.dubbo.resource.DemoService" ref="demoService" version="1.0.0"/>

    <!-- 和本地bean一样实现服务 -->
    <bean id="demoService" class="com.study.module1.dubbo.resource.impl.DemoServiceImpl"/>
</beans>

2)添加服务消费方配置文件,spring-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://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://dubbo.apache.org/schema/dubbo
           http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="dubbo-consumer-demo"/>

    <!-- 使用 Nacos 注册中心 -->
    <dubbo:registry address="nacos://127.0.0.1:8848"/>
    <!-- 如果要使用自己创建的命名空间可以使用下面配置 -->
    <!-- <dubbo:registry address="nacos://127.0.0.1:8848?namespace=5cbb70a5-xxx-xxx-xxx-d43479ae0932" /> -->

    <!-- 引用服务接口 -->
    <dubbo:reference id="dubboConsumer" interface="com.study.module1.dubbo.resource.DemoService" version="1.0.0"/>

</beans>

3)applicationContext.xml添加文件引用

<import resource="classpath:/spring-dubbo-provider.xml"/>
<import resource="classpath:/spring-dubbo-consumer.xml"/>

注:实际只能配置使用一个,要么服务方要么消费方

4、在src/test/java下添加测试类,DubboTest.java

package webapp;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import com.study.base.util.ApplicationContextHolder;
import com.study.module1.dubbo.resource.DemoService;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "classpath:applicationContext.xml", "classpath:spring-mvc.xml" })
@ActiveProfiles("dev")
public class DubboTest {

	@Test
	public void test() throws Exception {
		DemoService demo = ApplicationContextHolder.getBean("dubboConsumer", DemoService.class);
		String result = demo.echo("我是谁");
		System.out.println(result);
        System.out.println("111111111111111111111111");
		Thread.sleep(60 * 1000);
	}
}

5、测试方法
1)起一个服务,配置为服务提供方,放到tomcat中启动
2)本地项目配置为服务消费方,运行测试方法
日志打印出:Service [name :dubbo-provider-demo , port : 20880] echo say : Hello,我是谁
查看nacos控制台,都注册上了:

6、遇到的问题
1)pom文件中
<!-- dubbo nacos registry依赖 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo-registry-nacos</artifactId>
        <version>${dubbo.registry.nacos.version}</version>
</dependency>
版本不能用2.6.9,因为会报错,原因是这个版本没有自动依赖nacos-client包。。。

扫描二维码关注公众号,回复: 12899190 查看本文章
java.lang.IllegalStateException: Failed to load ApplicationContext
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
	at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189)
	at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131)
	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: java.lang.IllegalStateException: Failed to load extension class(interface: interface com.alibaba.dubbo.registry.RegistryFactory, class line: com.alibaba.dubbo.registry.nacos.NacosRegistryFactory) in jar:file:/C:/Users/User/.m2/repository/com/alibaba/dubbo-registry-nacos/2.6.9/dubbo-registry-nacos-2.6.9.jar!/META-INF/dubbo/com.alibaba.dubbo.registry.RegistryFactory, cause: com/alibaba/nacos/api/exception/NacosException
	at com.alibaba.dubbo.common.extension.ExtensionLoader.loadResource(ExtensionLoader.java:634)
	at com.alibaba.dubbo.common.extension.ExtensionLoader.loadDirectory(ExtensionLoader.java:604)
	at com.alibaba.dubbo.common.extension.ExtensionLoader.loadExtensionClasses(ExtensionLoader.java:586)
	at com.alibaba.dubbo.common.extension.ExtensionLoader.getExtensionClasses(ExtensionLoader.java:561)
	at com.alibaba.dubbo.common.extension.ExtensionLoader.getExtensionClass(ExtensionLoader.java:549)
	at com.alibaba.dubbo.common.extension.ExtensionLoader.hasExtension(ExtensionLoader.java:333)
	at com.alibaba.dubbo.config.AbstractInterfaceConfig.loadRegistries(AbstractInterfaceConfig.java:185)
	at com.alibaba.dubbo.config.ServiceConfig.doExportUrls(ServiceConfig.java:358)
	at com.alibaba.dubbo.config.ServiceConfig.doExport(ServiceConfig.java:319)
	at com.alibaba.dubbo.config.ServiceConfig.export(ServiceConfig.java:217)
	at com.alibaba.dubbo.config.spring.ServiceBean.export(ServiceBean.java:266)
	at com.alibaba.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:106)
	at com.alibaba.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:53)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:347)
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:883)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)
	at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:130)
	at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:61)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:281)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:249)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
	... 26 more
Caused by: java.lang.NoClassDefFoundError: com/alibaba/nacos/api/exception/NacosException
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at com.alibaba.dubbo.common.extension.ExtensionLoader.loadResource(ExtensionLoader.java:631)
	... 51 more
Caused by: java.lang.ClassNotFoundException: com.alibaba.nacos.api.exception.NacosException
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 54 more

2)在实际使用中服务提供方和服务消费方是两个不同的项目
那么服务消费方如何获取这个服务接口类,DemoService.class?引入对方的jar包?
3)nacos控制台-服务管理,下面分为服务列表和订阅者列表,这个订阅者列表是干什么的呢?

这个订阅者列表不是指消费者列表,而是指主动向Nacos Server发起事件监听的订阅者,比如健康检查、服务变更等事件监听的订阅者,具体可查看NacosDiscoveryEndpoint.nacosDiscovery()方法中是通过EventDispatcher去获取订阅者列表和发布事件。新版本才加了这么个订阅者列表,老版本可以订阅默认端点查看订阅者列表:http://127.0.0.1:9000/actuator/nacos-discovery

参考资料:
https://nacos.io/zh-cn/docs/use-nacos-with-dubbo.html

注:最新代码上传至https://github.com/csj50/webapp2.git
 

猜你喜欢

转载自blog.csdn.net/csj50/article/details/113704750