这里写目录标题
- 多模块项目的搭建
- 父项目的构建
- 子模块的创建
- 父子模块的意义
- 将注册服务引入到父子模块中
- 创建子模块用于发现服务和调用
- 供调用的服务接口
- 创建调用子模块
- 测试
- 一些小问题
在前文中我们实现了微服务的注册参考此文:
Spring Cloud Alibaba中Nacos的安装(Windows平台)以及服务的发现
现在我们需要创建另一个项目来发现服务以及调用注册的服务
多模块项目的搭建
为了方便之后的其他组件的引入,我这里就不再创建新的工程
了,而是把之前的注册服务
和接下来的nacos发现服务
都放到同一个工程
里。
也就是从之前的
转为以下这样
父项目的构建
得到的目录结构如图:
然后将src目录
删除,因为父模块不需要运行
,得到以下的目录结构
子模块的创建
然后我们再新建子模块
,右键根目录
,选择new -> module
这里的new module
创建的照样是一个maven工程
,不过此时它存在一个父模块,也就是我们上面的father_project
创建以后的目录这样的
父子模块的意义
大家可能会问了,父子模块的意义
是什么?为什么不能再创建一个项目
?而是使用父子模块
?
在 IntelliJ IDEA
中,父子模块的概念与 Maven 或 Gradle
等构建工具中的模块结构
概念相关联。
父子模块的意义:
-
模块化管理:父子模块的设计
有助于将项目分解为更小、更易管理的模块单元
(听起来像微服务划分的方式)。这种模块化管理使得项目更易于开发和维护
,有助于团队协作和复用。 -
依赖管理:父子模块可以有
依赖关系
,子模块可以依赖于父模块,同时子模块也可以互相依赖。 -
共享配置:
父模块中定义的配置
可以被子模块继承和覆盖
,比如版本管理、插件配置
等。 -
独立构建:子模块可以
独立构建、测试和运行
,同时也可以
依赖于其他子模块,最终打包成整个项目。
将注册服务引入到父子模块中
按照上述的方式,将之前的注册项目
引入到父子模块结构
的项目中,得到如下的项目
这里父项目的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>org.example</groupId><artifactId>SpringCloudAlibabaDemo</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><!-- 子模块的信息--><modules><module>nacos-project-registrant</module></modules><properties><!-- 项目的源代码的Java版本--><maven.compiler.source>11</maven.compiler.source><!-- 项目编译生成的字节码的目标Java版本--><maven.compiler.target>11</maven.compiler.target><!-- 项目的源代码文件的字符编码--><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!-- spring boot的版本--><spring-boot.version>2.7.4</spring-boot.version><!-- spring cloud alibaba的版本--><spring-cloud-alibab.version>2021.0.5.0</spring-cloud-alibab.version><!-- nacos-discovery的版本--><spring-nacos.version>2021.0.5.0</spring-nacos.version><!-- spring cloud的版本--><spring-cloud.version>2021.0.5</spring-cloud.version></properties><!-- 需要集中管理的依赖 子模块可以通过父模块引入而不需要自己导入--><dependencyManagement><dependencies><!-- Nacos服务注册和发现的集成--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>${spring-nacos.version}</version><type>pom</type><scope>import</scope></dependency><!-- 引入spring boot --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency><!-- 引入spring cloud alibaba --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibab.version}</version><type>pom</type><scope>import</scope></dependency><!-- 部分spring cloud功能使用时候需要引入这个--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><!-- 项目的构建配置,包括编译、打包、测试、部署等方面--><build><plugins><!-- spring-boot中用于支持maven打包的插件--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
子项目的目录结构与之前的相似
这里子模块的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><packaging>war</packaging><parent><groupId>org.example</groupId><artifactId>SpringCloudAlibabaDemo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>nacos-project-registrant</artifactId><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><!-- 由于父模块中已经引入了,所以这里不需要配置版本,项目会自动以父模块为准--><dependencies>
<!-- spring boot的引入--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Nacos服务注册和发现的集成--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies><!-- 项目的构建配置,包括编译、打包、测试、部署等方面--><build><resources><!-- 构建项目过程中被复制到输出目录中,以便它们可以在应用程序运行时访问--><resource><directory>src/main/java</directory><includes><!-- 项目内mybatis的dao配置文件--><include>**/*.xml</include></includes></resource><resource><directory>src/main/resources</directory><includes><!-- 资源文件--><include>**/*.*</include></includes></resource></resources><plugins><!-- spring-boot中用于支持maven打包的插件--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins><!-- 打包出来的名称 一般是项目的缩写外加版本号 --><finalName>npr</finalName></build></project>
我们再验证一下是否引入成功,启动注册服务
如果nacos
中对应服务存在,则表示成功
如果运行失败,可能是nacos没启动
导致的
创建子模块用于发现服务和调用
接下来我们再创建一个子模块用于发现
注册的服务,以及调用该服务的接口
供调用的服务接口
这里我们先在注册服务
中创建一些接口,供订阅者调用
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class NacosTest {@GetMapping("/echo/{string}")public String echo(@PathVariable String string) {return "成功调用注册服务的接口,代码为:" + string;}@GetMapping("/test")public String test() {return "调用服务的测试";}
}
在启动类上添加@EnableDiscoveryClient
注解,启用Nacos客户端的发现
创建调用子模块
按照上面的方式创建一个名为nacos-discoverry-call
子模块,并将其改为spring boot
项目,如下图所示
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><packaging>war</packaging><parent><groupId>org.example</groupId><artifactId>SpringCloudAlibabaDemo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>nacos-discoverry-call</artifactId><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><!-- 由于父模块中已经引入了,所以这里不需要配置版本,项目会自动以父模块为准--><dependencies><!-- spring boot的引入--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Nacos服务注册和发现的集成--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- openfeign提供服务的远程调用--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- open-feign在默认情况下依赖于负载均衡 新版本中已经不再强制依赖ribbon 而是推荐loadbalancer--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency></dependencies><!-- 项目的构建配置,包括编译、打包、测试、部署等方面--><build><resources><!-- 构建项目过程中被复制到输出目录中,以便它们可以在应用程序运行时访问--><resource><directory>src/main/java</directory><includes><!-- 项目内mybatis的dao配置文件--><include>**/*.xml</include></includes></resource><resource><directory>src/main/resources</directory><includes><!-- 资源文件--><include>**/*.*</include></includes></resource></resources><plugins><!-- spring-boot中用于支持maven打包的插件--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins><!-- 打包出来的名称 一般是项目的缩写外加版本号 --><finalName>ndc</finalName></build></project>
application.yml
文件除了application.name以及port
其他无变化:
server:port: 9001tomcat:uri-encoding: UTF-8spring:application:name: nacos-callcloud:nacos:discovery:server-addr: 192.168.2.102:8848
# 控制应用程序在启动时对配置中心的连接行为 如果没有连接到客户端则会立即启动失败fail-fast: true
启动类CallApplication
中需要添加以下两个注解,启用服务的发现和调用
:
调用类相关的就以下两个
FeignInterface
调用的接口,定义了某个服务
调用的接口:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//feign接口提供服务的调用 name为所调用服务的名称
@FeignClient(name="nacos-register")
public interface FeignInterface {@GetMapping("/echo/{str}")String echo(@PathVariable("str") String str);
}
NacosTest
为测试的控制器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;@RestController
public class NacosTest {private final static String SERVICE_ADDR = "http://192.168.2.102:9000";//Fegin接口提供的调用方式@AutowiredFeignInterface feignInterface;//直接使用Rest风格模板来实现调用 不推荐private RestTemplate template = new RestTemplate();@GetMapping("/echo/{string}")public String echo(@PathVariable String string) {//直接使用Rest风格模板来实现调用return template.getForObject(SERVICE_ADDR + "/echo/" + string , String.class);}@GetMapping("/test")public String test() {//直接使用Rest风格模板来实现调用return template.getForObject(SERVICE_ADDR+"/test" , String.class);}@GetMapping("/iecho/{string}")public String iecho(@PathVariable String string) {//Fegin接口提供的调用方式return feignInterface.echo(string);}}
测试
启动两个子模块,进入Nacos
控制台
这里可以发现两个已经注册的服务,说明没问题,然后我们调用一下,检查是否调用服务(nacos-call)
能否调用到注册服务(nacos-register)
中的接口
地址栏输入http://localhost:9001/iecho/125
调用注册服务中的echo接口
有以下显示即为成功
此时点开订阅者列表
可看到,nacos-call
服务
还可以输入http://localhost:9001/test
测试/test
接口
一些小问题
订阅者有时候不显示应用名称而是显示为unknow
自己给环境设置一下即可
ProjectNameConfig
代码为:
import com.alibaba.nacos.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;//用于设置订阅者一栏中的应用名称
@Configuration
public class ProjectNameConfig implements EnvironmentAware {@Value("${spring.application.name}")private String applicationName;@Overridepublic void setEnvironment(Environment environment) {if(StringUtils.isBlank(System.getProperty("project.name"))){System.setProperty("project.name",applicationName);}}
}