现在我们按照他的一个架构图,注册中心已经配置好,现在只要把Provider搭建出来就可以,在Provider中需要告诉Provider
的事情,第一件事情,我需要告诉它,我的注册中心在哪,这点你说应不应告诉,你不告诉他就能找到,就在虚拟机中找到注册中心,
那他也太厉害了,这个东西也太神奇了,人工智能他就不要发展了,这是第一个,告诉注册中心在哪,第二个,你得告诉它用什么协议,
他不是支持三个吗,你得告诉它用哪个,然后第三件事情,要告诉注册中心,他要告诉注册中心,我的哪一个接口需要进行发布,
是哪一个功能需要发布,发布哪个类,主要是做这三件事情,那我现在做之前,Dubbo中的Provider搭建,在搭建之前,我们需要分析
一些事情,我们现在还没有去搭建过呢,在dubbo这块,我们是一定需要去建一个接口的,注意看,这是咱们的大前提,咱们的总体思想,
一般调用接口,会有功能吗,没有,是不是还要建一个实现类啊,这个实现类一般情况下,我们用完Dubbo之后,那种感觉像什么呢,就是
把Service业务中的代码,这是实现类,Impl,把这里面替了,现在在做的时候,为什么前面需要强调一下,就是这两个东西不能建到一个
项目中,接口和实现类必须分开建,Dubbo是不是要被consumer调用的,我们现在需要有个项目,我想要调用它的时候,比如在我的接口中
有个方法,A方法,我怎么提供dubbo提供A对象啊,你在编译的时候,比如在当前项目中,没有B这样的一个接口,我能写Provider B小b吗,
你想想在当前项目没有B接口或类,你能写出这句话吗,是不能啊,你为了让他编译通过,编译通过,我是不是要保证当前项目有B接口或类,
所以我就需要让当前项目去依赖他,那依赖他的话,如果接口跟实现类都在同一个项目中,那我在当前项目还能不能看到实现类,可以,
那是RPC了吗,所以就不是RPC了,那就和普通的项目调用有什么区别了,所以我们在创建的时候,一定要把接口和实现类拆分两个项目,
让实现类实现这个接口,让consumer消费者也去依赖接口,具体接口对应的实现类怎么实现的,在我的consumer中,是根本不知道的,
能明白这点吗,所以必须得分开建,不分开建是绝对不行的,所以我们在做的时候,新建一个,other,选择一个maven project,
dubbo-service就是一个jar,就是一个接口,里面也不用导任何包,就写类就行,右键新建一个接口
<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>com.learn</groupId>
<artifactId>dubbo-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</project>
package com.learn.service;
/**
* 反正我们就提供一个方法,
* 返回值是一个字符串
* 也不用连数据库
* 就声明我们有哪些接口
* @author Leon.Sun
*
*/
public interface DemoService {
/**
* 我们单独建一个最简单的
* String类型的
* 假设传入一个String类型的name
* 这都认识吧
* 接口就创建完了
*/
String demo(String name);
}
重点是怎么创建实现类项目,这个项目就是我们在原理图中看见的Provider,Provider在代码中的体现,就是接口实现类的项目,
Provider在代码中的实现,其实就是这个接口的实现类项目,右键新建一个项目,Maven Project,dubbo-service-impl,这里看清除,
dubbo实现的这块,不用建成war,就一个jar就行,他底层用了一个第三方的框架,叫netty框架,这是一个网络框架,能够把我们的东西
发布,如果有人学过安卓的话,你就会用到他,netty框架,网络框架,netty框架一定要用的,网卡框架你不用netty,你用谁啊,
我们现在这个packaging叫做jar就行,就是jar,他不用写控制器,我们写这个实现类的时候,就像我们以前写项目的时候,以前写项目,
就dubbo的provider,就像我们以前service的实现类,顶多以后我们会在里面加个mapper,那我们现在写完之后,我为了保证有这个接口,
加一个依赖
<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>com.learn</groupId>
<artifactId>dubbo-service-impl</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.learn</groupId>
<artifactId>dubbo-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
package com.learn.service.impl;
import com.learn.service.DemoService;
/**
* 在这里我要让他去实现DemoService
* 添加未实现方法
* 这里就没有@Servcie
* 这里不用写
* dubbo给我们提供了一个注解
* 这个注解和我们以前的注解名字是一样
* 也叫@Service
* 但是这个注解对2.5.3兼容性特别好
* 在我们Spring4.1.6的时候
* 如果你还用@Service
* 导包的时候是dubbo的
* dubbo的一个@Service
* 他和Spring的AOP有冲突
* 一定要注意哦
* 这块本质是能用注解的
* 但是由于现在和Spring4.1.6有冲突
* 所以我们就不能够用注解
* 不用注解我们就用原始配置文件
* 现在我们这里什么也不能写
* 我这里少点东西
* 我现在想用dubbo这个框架
* 做框架第一步是干什么
* 导入jar包
* 我们去导jar包
*
* @Service在provider里不要用
* 一用就和我们的service就冲突了
* 一定要注意
* 那怎么用呢
* 得写配置文件,
* 配置文件怎么写配置文件
* 依赖于Spring容器
* 就像SpringMVC依赖于Spring容器的
* 我们写Spring配置文件的时候
* Dubbo依赖于谁呢
* 依赖于Spring容器
* 那我们写dubbo配置文件的时候
* 所以我们在做的时候
* 在我们的resource里面新建一个xml
* 随便起个名
* applicationContext-dubbo.xml
* @author Leon.Sun
*
*/
public class DemoServiceImpl implements DemoService {
/**
* 调方法的时候就会传这个字符串
* 写代码这块就这么写就行了
*/
@Override
public String demo(String name) {
return "传递过来的name:" + name;
}
}
<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>com.learn</groupId>
<artifactId>dubbo-service-impl</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.learn</groupId>
<artifactId>dubbo-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<!-- 这里会有spring-2.5.6这是多少年前的,所以我们要想一个办法 -->
<!-- 不要用它,我们知道导入Spring的时候 -->
<!-- 我昨天说过一个事情,因为Spring从2到3是大跨版本的 -->
<!-- 2就一个jar包,里面包括了所有的功能 -->
<!-- aop,beans,context,core核心,是不是全在一个jar包里面 -->
<!-- 从3开始拆分很多了,所以根本就不是一个东西了,如果是一个东西,我们完全可以像昨天一样 -->
<!-- 在这里面我们要告诉maven,有个叫exclusions不包含,不包含什么呢 -->
<!-- 他只能依赖一个spring,不可能依赖两 -->
<!-- 我们就用一个exlusion就把它拿掉了 -->
<exclusions>
<!-- exclusion里面是什么呢,是坐标 -->
<!-- 2.5.6的artifactId就是spring -->
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- springmvc我们用的是4.1.6 -->
<!-- 粘贴进去,你会发现覆盖不掉 -->
<!-- 4.1.6进来了,spring-2.5.6还在 -->
<!-- 其实你要注意,如果真的只是版本的迭代 -->
<!-- 但是2和3变化太大了,那这该怎么办呢 -->
<!-- 看这个单词netty-3.2.5是不是我刚才说的网络框架 -->
<!-- 那我现在在这里面删掉,右键是删不掉的 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- 你们要明白这个包是干什么的
访问zookeeper客户端的jar包,
-->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
</dependencies>
</project>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 写配置文件要导入schema,那这个schema怎么办呢 -->
<!-- 我特意没有去找spring的schema -->
<!-- xmlns:dubbo我们看到dubbo命令空间 -->
<!-- xmlns:context还是有的 -->
<!-- 依赖于spring容器,但是有自己的东西 -->
<!-- 根据schema特性,我们可以加命名空间 -->
<!-- 加了命令空间后,就是扩展功能 -->
<!-- 那就是dubbo,那在写命名空间的时候没有 -->
<!-- 给当前Provider自定义个名字 -->
<!-- 除了注册中心以外还要有一个application -->
<!-- 给当前的provider起个名字,这个名字有什么用呢,我们这个都是要被监控中心所管理的
他需要知道是哪一个provider,所以随便取个名,我们就取dubbo-service
除了这个以外再往下
-->
<dubbo:application name="dubbo-service"/>
<!-- 首先我要告诉他的注册中心在哪 -->
<!-- 配置注册中心 -->
<!-- 在注册中心这块有个address
然后还有一个protocol协议,端口2181,协议什么协议,dubbo协议是不是刚讲过的
做完这个就差不多了,就差最后一件事情,还需要配一个,protocol
protocol="zookeeper"这个属性其实起的不好,name="zookeeper"如果是这样就好了
什么意思,这个东西配置的是注册中心,localhost:2181这个是zookeeper的地址
-->
<dubbo:registry address="localhost:2181" protocol="zookeeper"></dubbo:registry>
<!-- 配置端口 -->
<!-- 这又是个什么东西呢
然后有个name等于什么什么,然后port等于什么什么,
配置这个的时候,这个标签是什么意思,看我们的原理,一定要明白这个标签的意思
看清楚有个第四步,第四步干什么,我去注册中心往下拿,拿到provider的地址之后,
真实的调用一下,那我调用的话通过互联网,一个电脑访问另一个电脑,一定要走端口啊,
20880配置的意思表示我的provider再使用当前计算机的端口20880
那2181是什么东西,是zookeeper的端口,20880是provider在那台计算机上发布
在哪台计算机上运行,就用哪个端口,必须20880吗,不是,你随便写,随便写,只要不写1024之前的
不写哪些经常被占用的,随便写,你这写成什么,以后我这台consumser在调用我这台计算机的时候,
就走哪个端口,明白啥意思吗,就是这样的一个意思,name就是从注册中心dubbo:registry这
获取到我的地址 address="localhost:2181",这是个固定值,把信息注册到
注册中心,所有的consumer获取到我的信息,然后通过20888来访问我的计算机,name="registry"
这个字符串是获取到上面的,到此还差一个了,我们的provider一起来需要干什么,是不是要想注册中心注册啊
注册什么啊,注册自己提供了什么功能,你说你什么 也没有配置,Dubbo就知道DemoServiceImpl这个
东西需要被注册的吗,是不是不能知道,所以我在这里面做的时候,要向注册中心中注册功能
name="dubbo"这个是dubbo协议,
-->
<dubbo:protocol name="dubbo" port="20888"></dubbo:protocol>
<!-- 注册功能 -->
<!-- 要注册一个接口
哪个接口,这个是接口,注册只是去注册接口,不是注册实现类,接口呢,com.learn.service.DemoService这儿
那他怎么知道是调哪个实现类呢,不要着急,还没有写完,还有一个ref呢,一旦ref后面要配个什么东西,bean的id
-->
<dubbo:service interface="com.learn.service.DemoService" ref="demoServiceImpl"></dubbo:service>
<!-- 这里才是咱们要的实现类
你不能向注册中心注册实现类啊,你得注册接口,那我们把实现类拿过来,实现类呢,在这儿com.learn.service.impl.DemoServiceImpl
然后把这个demoServiceImpl往ref里面放,现在我们所有的配置都完事了,就这5个标签,如果后面频繁的写接口和实现类,
dubbo:service和bean这个是频繁写的,多写几份,一个接口写一个,一个接口写两个标签,这里我还必须再强调一下,
就是这几个标签,只要是这几个东西,配置完之后就不用换了,所以这个东西根本就不用配,知道是什么意思就行了
-->
<bean id="demoServiceImpl" class="com.learn.service.impl.DemoServiceImpl"></bean>
<!-- 其实还有一个dubbo:annotation
什么啊,注解是吧,package="com.learn.service.impl",其实我特别喜欢用这个,
用完他之后,我只需要在com.learn.service.impl.DemoServiceImpl上加上@Service
导入的是dubbo的就完事了,import com.alibaba.dubbo.config.annotation.Service;
不用配置上面dubbo:service和bean这两个标签了,但是就是和声明式AOP有冲突,他们都是采用双向代理
都对DemoServiceImpl这块产生代理,两个人就冲突了,所以没办法,就不能用注解了,这不可能不用声明式事务
宁可我们做的麻烦点,也不能不用声明式事务,给他删掉,现在配置功能就全部写完了
-->
<!-- <dubbo:annotation package="com.learn.service.impl" /> -->
</beans>
package com.learn.test;
import java.io.IOException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.alibaba.dubbo.container.Main;
/**
* 我只要把Spring启起来,
* dubbo就起来了
* 配置文件起来就行了
*
* @author Leon.Sun
*
*/
public class Test {
public static void main(String[] args) throws Exception {
/**
* 怎么加载Spring配置文件
* new ClassPathXmlApplicationContext()
* 这个项目是真实的dubbo服务
* 我的配置文件叫applicationContext-dubbo.xml
* 这么写完成之后
* 要让容器启动
* 没有start方法
* 方法在ClassPathXmlApplicationContext
* ApplicationContext接口中没提供
* ClassPathXmlApplicationContext实现类中提供了
* 一定要用实现类接收
*/
// ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext-dubbo.xml");
/**
* 此时就把Spring容器启起来了
* 这是手动启动Spring容器
* dubbo就写在这里了
* 其实本质我们在写start的时候
* 是在做0start的过程
* 1的register过程不需要我们做
* 它是自动做的
* 这点我需要强调一下
* 1这个register如果你的WIFI有共享精灵
* 有什么这些东西
* 可能会导致1register无效而且不报错
* 可能不是一定的
* 把WIFI共享精灵一关就好使了
* 开开就注册不上
* 这块需要注意一下
* 现在有了这样的一个功能之后
* 我们只要邮件run as
* 你会发现一个特别有意思的事情
* 我们在提供者中配置的时候
* dubbo:protocol name="dubbo"
* 这里name是写的dubbo
* dubbo:registry address="localhost:2181" protocol="zookeeper"
* 这里的协议是zookeeper
* 表示的这里是一个zookeeper地址
* 这是一个zookeeper
* 走到运行原理是怎么走的
* Registry是我们的注册中心
* 是我们的第四步
* 我们在做第四步的时候
* 根据provider的地址真实的调用provider的功能
* 我们dubbo中支持的协议包括几个呢
* Dubbo,RMI,Hessian
* 就是我们的consumer调用provider的时候
* 其实是遵守上面的协议的
* 那是哪个协议
* 是dubbo协议
* dubbo:protocol name="dubbo" port="20888"
* 这个port是我的provider在哪台电脑上占用哪个端口
* 就是我的consumer去调用我的时候
* 中间通过的协议是dubbo协议
* 然后访问我的是20880端口
* dubbo:registry address="localhost:2181" protocol="zookeeper"
* 上面表示注册中心的地址
* 注册中心使用的是zookeeper
* 下面往下解决这个事情
* NoClassDefFoundError: org/I0Itec/zkclient/exception/ZkNoNodeException
* 指定是少jar包
* 少了谁啊
* 少个zkclient
* 这个东西是什么呢
* client是客户端
* zk应该是哪个单词的缩写
* zk是zookeeper
* 我们现在要做件什么事情
* 是在容器启动的时候
* 向注册中心注册自己的信息
* 那此时我的zookeeper是一个服务
* provider相当于是zookeeper的一个客户端
* 想想是不是
* 我是不是要通过provider去访问Registry
* 看能不能想明白这个事情
* 相当于你去注册
* 所以在我这个容器中
* 要必须具备访问zookeeper的能力
* 这个能力就是zkclient
* https://mvnrepository.com/artifact/com.101tec/zkclient
* 我们导入0.10就行了
* 拿过来放入我们的pom.xml中
* 此时就具备了往注册中心注册的功能
* 那现在完事了
* 那现在又带来了下一个问题
* 怎么一下子就关了
*
*/
// ac.start();
/**
* 说明我们现在的配置都对了
* 你给我关了
* 那consumer还能调用吗
* 程序关了它是绝对调不到的
* 所以我们要想一个办法
* 阻止关闭
*
*/
// System.out.println("启动成功");
/**
* 最简单的是这个
* 这个什么意思
* 我只要不在控制台输入东西
* 他就会一直跑
* 但是只要我随便写一个东西一回车
* 接收到这一行就直接过去了
* 能看明白啥意思吗
* 那这种方式是一种
* 这么写不太好啊
* 官方给我们提供一种
* 一种非常好的一种方式
*
*/
// System.in.read();
/**
* 官方推荐的
* 叫Main类的main()方法
* 这个不是调自己
* Main类是自己提供的一个类
* main方法是启动容器的一个办法
* Dubbo service server started!
* 但是至少解决刚才没了这个问题
* 是不是还在亮着呢
* 现在还少一个事情
* 少一个什么事情
* 他这方法你往里进也没什么用
* 加载默认的扩展名称loader.getDefaultExtensionName()
* Runtime.getRuntime()运行时的环境
* 我们的dubbo的一个运行环境类
* 下面container.start()这什么意思
* 容器启动
* 这个容器在哪呢
* 这其实就是一个List<Container>
* list里面有containers.add(loader.getExtension(args[i]))
* 你看是中国人写的
* 其实想告诉一件事情
* 如果你这么写好像没有指定配置文件
* 那这个时候就对配置文件有个强制要求
* 要求配置文件必须放在/META-INF/spring/*.xml
* 就是你的路径必须是这样的
* 否则你的配置文件无法被加载到
* 注意这个META-INF不是下面的META-INF
* 这是什么项目
* 这是jar项目
* 在resource下右键新建文件夹folder
* 文件夹META-INF
* 然后在META-INF下建一个文件夹spring
* 然后applicationContext-dubbo.xml放在spring文件夹下就完事了
* 启动的效果还是那样
* 你启动之后没报错没效果
* 如果你配置文件放外面怎么也没效果
* 其实就是这点不太好
* 这就是我们现在做的所有事情
* 此时所有provider的东西都讲完了
* 那现在有了这个以后,我们总感觉有点别扭,怎么别扭,我不知道是真启成功了
* 还是假启动成功了
* 你会发现配置文件放外面
* 放在外面也是started
* 放在里面也是started
* 所以我们要有一种办法
*/
Main.main(args);
}
}
一个项目中,Consumer依赖这个项目时,就会知道实现类具体实现,这就是为什么要去新建一个接口dubbo-service了,然后干什么,
再去新建一个Maven Project,这个project的作用是干什么,里面其实就是写接口的实现类,我们起个项目名吧,因为下面我们需要
知道是在哪里写,实现类叫dubbo-service-impl,然后下面我们需要做的事情是,在dubbo-service-impl中配置pom.xml,主要配
几个东西,我们回顾一下,首先把dubbo给引进来,引dubbo还需要注意一个事情是,去掉老版本的spring,这是第一件事情,spring
被去掉以后我们还得干什么,是不是得引个新的spring,当我们容器启动的时候,要向注册中心注册,怎么办,还得有个zkclient
访问zookeeper,这三个是最重要的,最后还得依赖一下接口,zkclient是向注册中心注册的,spring新版本,dubbo版本,以及
依赖的接口,这四件事情,包含四件事情,第一件事情依赖接口,第二件事情依赖dubbo,去掉老版本的spring,第三件事情依赖
新版本的spring,第四件事情依赖zookeeper客户端工具zkclient,第四步是新建一个配置文件,叫application-dubbo,不叫
这个名字也行,我们用的Main.main()方法这个,他找只要是xml就行,不看名,假设我们新建这样的一个.xml,并配置,配置了
5个标签,再强调一遍这5个标签的作用,第一件事情我们一会要建立一个管理工具,这个管理工具是专门看我们的服务是否
发布成功没,跟说到的Monitor一点关系也没有,跟这个一点关系也没有的,我要用一个额外的工具,就是看服务发布成功没,
那里面怎么区分是哪一个provider呢,就根据这个名字<dubbo:application name="dubbo-service"/>,然后下面这个地址
是什么地址,<dubbo:registry address="localhost:2181" protocol="zookeeper"></dubbo:registry>,注册中心
的地址,zookeeper这个表示哪个注册中心,<dubbo:protocol name="dubbo" port="20888"></dubbo:protocol>,dubbo这个
表示协议名,20888这个表示consumer调用provider时的端口号,我们需要知道的事情,第一步,我们再写一遍,ubbo:application
他的作用是给provider起个名字,在monitor或者管理工具中区别是哪个provider,dubbo:registry注册中心,这个表示配置
注册中心,配置注册中心,第一个address什么意思,注册中心的ip和端口,还有个protocol,就是使用哪种注册中心,
dubbo:protocol这个什么意思,就是配置协议,name是使用什么协议,还有个port,这个是consumer invoke第四步调用provider时
的端口号,一定要注意,我配的是20888端口,就占用哪个端口,我们会把这个项目放在服务器上,也就占用服务器的20888端口,
到这完事之后,你就配置完了,完成之后,配置完之后要新建实现类,并实现接口和方法,然后我们看一下dubbo:service,这里
是干什么的,注册接口还是实现类,是接口,注册接口,<dubbo:service interface="com.learn.service.DemoService"
ref="demoServiceImpl">,这是我们注册接口,ref引用接口实现类,bean的id值,完事了,然后最后一步,第六步,启动容器,
不就是这个意思,启动容器分为两种,第一种方式是通过Spring方式启动,第二种方式使用dubbo启动的方式启动,我们只是
说一下这种方式,其实我是不用他的,那在这种方式的时候,这样做的话要保证我们的配置文件,什么配置文件,
applicationContext-dubbo放哪,如果这么写的话,放在哪都可以,位置没有要求,下面这个有要求,要求
applicationContext-dubbo.xml必须放入类路径下/META-INF/spring/*.xml,你随便去官方找一个,都是这么写的,
咱们推荐使用这种方式,而且后面我们在学其他技术的时候,就不是推荐了,就是强制必须