码云工程代码的连接:https://gitee.com/xuanyuanzy/spring-cloud2020
首先需要有一个最总的父工程,创建如下图:
配置字符集,如下图:
开启注解支持,如下图:
设置java编译版本为8,如下图:
删除父工程中多余的目录和文件,如下图:
所有的代码都在我的码云仓库里面,仓库地址:https://gitee.com/xuanyuanzy/spring-cloud2020.git
dependencies,dependency,dependencyManagement这三个maven的pom文件标签都是用来进行包管理的。
势力范围由dependencyManagement>dependencies>dependency依次减弱,并且每个标签都是上一个标签的下级。
dependencyManagement和dependencies区别:
1.如果没有dependencyManagement标签,只有一个dependencies标签的话,那么子模块中会默认继承父模块中的所有的依赖,如果子模块中有和父模块中相同的依赖,则会使用子模块中已经写的依赖。
2.如果写了dependencyManagement标签,那么子模块中就不会继承父模块的dependencyManagement标签中的dependencies标签中的全部依赖了,而是只有当子模块中的dependencies标签中的依赖没有写version版本号的时候,这个时候才会继承父模块的对应的这一个依赖。
3.dependencyManagement这个标签是用来父类管理的,一般是最顶层的父工程中才能看到这个标签。
4.dependencyManagement标签里面的依赖是不会被下载到父模块中的,如下图:
它只是进行一个规范,进行一种version版本号的锁定,你子模块是可以使用我的规范的,如果你依赖不写version版本号,那么你就会默认使用我的父模块里的规范,也就是会使用父模块里面的版本号。
之前的项目里面,使用maven命令打包的时候,如果想要跳过单元测试,一般都是使用命令的形式,如: mvn clean install -Dmaven.test.skip=true但是其实我们可以只通过一个按钮就来实现这个功能,如下图:
统一各种依赖的版本号,如下图:
使用properties标签里面统一的版本号,如下图:
构建步骤:
1.cloud-provider-payment8001微服务提供者支付Module模块
2.热部署Devtools
3.cloud-consumer-order80微服务消费者订单Module模块
4.工程重构
怎样建立一个微服务模块呢?
1.建module
2.写pom
3.写YML
4.主启动类
5.业务类
在父工程cloud2020的下面新建一个cloud-provider-payment8001子模块,如下图:
注意:上图子模块的pom.xml模块中,为什么只有一个artifactId标签呢?正常情况下不都是应该是gav坐标都要有的吗?因为我们的子模块是继承的cloud2020父工程,因此groupId包名和version版本号默认是继承于父类,因此不用写。
成功创建子模块之后,在父工程的pom.xml文件中会多出一个modules标签,用来记录所有的子模块,如下图:
首先父工程里面引入的spring-boot-dependencies依赖就相当于是把SpringBoot这个框架引入了进来,然后你去点击spring-boot-dependencies依赖,可以发现里面有所有的关于springboot的依赖,如果我们在子模块中想要使用这些依赖只需要引入ga就行了,不用写version版本号,具体演示如下图:
如下图:
配置子模块的yml文件,如下图:
如下图:
首先建一个表如下图:
接着写实体类,如下图:
写dao层的动态代理接口,如下图:
然后写动态代理接口所对应的映射文件,如下图:
先写接口,如下图:
然后写一个service层的实现类,如下图:
那如果我们想要发送post请求,该怎么办呢?可以使用一个工具:postman,如下图:
什么是热部署?简单的一句话就是说,每次我们的代码改动之后,idea可以自动的重启运行,而不用我们每次都要停止运行然后再开启运行,因为这样太浪费时间了。
没有热部署,那么我们改动代码之后,程序就不能自动运行,如下图:
如下图:
这里没有直接在支付模块的pom文件中引入spring-boot-maven-plugin插件,而是在它的父工程中引入的这个插件,如下图:
需要在四个地方进行打钩,如下图:
进入Registry的快捷键是:ctrl+shift+alt+/,如下图:
然后勾选两个选项,如下图:
热部署测试成功,先把控制台的输出信息删除,然后重新在程序中加上了一段代码int age=10/2之后,按一下组合键ctrl+s之后,大概6秒之后,程序就重新运行了,如下图:
消费者订单模块order微服务中应该有哪些东西呢?controller层,service层,dao层,是都需要有吗?答案是不是的,我们只需要有一个controller控制器层就行了,order微服务的controller控制器层会调用payment微服务的controller控制器层,然后payment微服务的controller控制器层再去调用它的service层dao层。解释如下:
消费者订单的模块是微服务order,支付模块微服务是payment,比方说我们在淘宝京东上面买东西,那么我们相当于是客户端消费者,我们在订单这个微服务上调用payment支付这个微服务,支付微服务模块需要进行service层dao层调用淘宝京东的数据库等信息,但是订单微服务模块只需要有一个controller层调用支付微服务模块就行了,具体的活order模块是不做的,它会调用payment模块,让payment模块干活,因为你想一下也知道,我们作为消费者,只管下单就行了,我们肯定是没办法访问淘宝京东的数据库的。
那现在问题来了,如果order模块中的controller控制器想要调用payment模块中的service层的东西,因为controller层和service层是在两个工程里面,那么这个时候该怎样实现不同的微服务之间的相互调用呢?请看下图:
使用restTemplate访问restful接口非常的简单粗暴无脑。
(url,requestMap,ResponseBean.class)这三个参数分别代表REST请求地址,请求参数,HTTP响应转换被转换成的对象类型。
什么是HTTP响应转换被转换成的对象类型,就是说,order模块微服务访问了payment模块微服务的那个控制器方法返回的对象类型。
如果是order微服务调用payment微服务的请求是插入请求,那么在order微服务中需要用到方法restTemplate.postForObject(url,实体参数对象,控制器方法返回的类.class),去调用payment微服务控制器,如下图:
如果是order微服务调用payment微服务的请求是查询请求,那么order消费者微服务需要用到方法restTemplate.getForObject(url,控制器方法返回的类.class),去调用提供者payment微服务,如下图:
首先是在order消费者服务中调用payment提供者服务里面的查询数据库的控制器方法,如下图:
order微服务中的控制器方法如下图:
payment提供者微服务对应的控制器方法如下图:
浏览器测试接口,如下图:
其次是order微服务调用payment微服务中的插入方法,如下图:
payment提供者服务对应的控制器中的方法,如下图:
order消费者服务对应的控制器中的方法,如下图:
浏览器中测试order微服务能否成功调用payment微服务,如下图:
通常使用restTemplate的时候会把restTemplate类使用配置类加入到IOC容器中,如下图:
新版本的idea的Run DashBoard其实就是Service,如下图:
我们上面已经写了两个微服务,一个是payment提供者微服务,另外一个是order消费者微服务,我们可以发现这两个微服务中有一些东西是完全一样的,比如说是两个微服务中的实体类就完全一样,如下图:
但是这样的话就会显得比较冗余了,所以我们可不可以把这些东西全部都提取出来放到一个地方呢?这个提取的思想就叫做工程重构。工程重构其实就是新建一个工程,然后这个工程里面存储的是一些其他工程共用的东西,比方说是实体类了,然后把这个工程打包发布到我们maven的本地仓库中去,其它的工程如果想引用里面的实体类可以直接引入工程的依赖,这样就可以了,具体操作如下图:
因为这个重构的工程不用对外访问,因此它不用暴露接口,所以也就不用写YML配置文件去定义端口号了。
把order微服务和payment微服务中的实体类复制到cloud-api-commons工程中,如下图:
如下图:
1.把order微服务和payment微服务中的实体类全部删除,如下图:
2.引入重构工程的maven依赖,如下图:
重新测试消费者服务能否成功调用提供者服务出现相应的结果,最后发现测试是成功的。