irpas技术客

SpringBoot,SpringCloud整合Eureka过程详解_shuai_juan_eureka springboot

网络 2018

在讲这个之前我们需要了解微服务的优点:

? ? ? ? 传统的单体架构是以整个系统为单位进行部署的, 而微服务则是以每个独立组件(比如用户服务、商品服务)为单位进行部署的。

用一张经典的图来表现,就是下面这个样子:

上图想表达的意思就是现实中每个服务的吞吐量是不一样的,常用的服务需要部署更多的服务器,不常用的服务则不需要那么多服务器,而这种灵活的部署只有微服务架构才能实现。(Docker容器的诞生,为微服务架构提供了有效的容器)

? ? ? ? 步入正题:从上图来看,我们需要将每个服务给细分开,所有首先这里肯定需要一个父项目,然后删掉父项目的src,在父项目里面建多个子项目。

第一步:新建一个maven工程,将其作为父项目,命名为springcloud

注意事项:

1. 新建好的pom.xml中首先要更改项目打包方式为pom

<!--打包方式--> <packaging>pom</packaging>

pom项目里面不执行任何代码,只是为了聚合工程或者传递依赖用的。

pom? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 父类型都为pom类型????????jar(默认)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?内部调用或者是作服务使用war? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 需要部署的项目

?2. pom.xml里面导入<dependencyManagement>

<dependencyManagement>标签的作用是提供管理依赖版本号的方式,在它里面声明所依赖的jar包的版本号等信息。这样,它的所有子项目再次引入该依赖的时候不需要显式的列出版本号,方便后续版本升级只需要更改父项目版本,而不需要每个子项目都去更改一遍。

<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <junit.version>4.12</junit.version> <lombok.version>1.18.22</lombok.version> <log4j.version>1.2.17</log4j.version> </properties> <dependencyManagement> <!--注意:Springboot和Springcloud是有版本对应关系--> <dependencies> <!--springcloud依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR12</version> <type>pom</type> <scope>import</scope> </dependency> <!--springboot依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.3.7.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--连接数据库--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.26</version> </dependency> <!--数据源--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.8</version> </dependency> <!--mybatis启动器--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> <!--日志测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.7</version> </dependency> </dependencies> </dependencyManagement>

上面有一个需要注意的地方就是Springboot和springcloud版本有对应关系,

?这里我使用的SpringCloud版本是最新的:Hoxton.SR12,Springboot版本刚开始也是使用的最新版本2.6.0,但是后面整合Eureka时候出现了错误,所以改成了上面XML中的2.3.7.RELEASE,具体什么原因下面会讲。

第二步:在父项目springcloud下新建maven子项目,命名为springcloud-api,用来写实体类服务

注意事项:

1. pom.xml中导入lombok依赖

<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>

2. 新建一个java实体类

import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.io.Serializable; /** * @author: Administrator * @date: 2021/12/16 11:43 */ //实体类:Dept,映射:mysql数据库中的表db01对应这个实体类 @Data @NoArgsConstructor @Accessors(chain = true) //链式写法 public class Dept implements Serializable { private Long deptno; //主键 private String dname; private String db_source; public Dept(String dname) { this.dname = dname; } }

这个java实体类对应的数据库字段

第三步: 构建注册中心,命名为springcloud-eureka-7001

1. pom.xml导入所需依赖

<dependencies> <!--<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> <version>1.4.7.RELEASE</version> </dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!-- 这里一定要注意,如果报ConfigurationBeanFactoryMetadata错误,是因为 spring boot 2.4之后删掉了ConfigurationBeanFactoryMetadata 将spring boot版本降级为2.3.9.RELEASE即可解决. --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies>

?2. 编写主启动类

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; //启动之后访问:localhost:7001 @SpringBootApplication @EnableEurekaServer //服务端的启动类,可以接受别人注册进来 public class EurekaServer_7001 { public static void main(String[] args) { SpringApplication.run(EurekaServer_7001.class,args); } }

图中增加了一个@EnableEurekaServer注解,这个注解所标明的类代表它可以接受服务提供者注册进来。而服务提供者的的主启动类中则是添加@EnableEurekaClient这个注解,作用是在服务启动之后注册到Eureka中。

主启动类在启动之后,有些人可以会报这个错误:org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata

原因是版本兼容问题,在spring boot 2.4之后删掉了ConfigurationBeanFactoryMetadata

将spring boot版本降级为2.3.9.RELEASE即可解决。

运行成功之后浏览器访问网址:localhost:7001即可成功进入下面页面。

?图中红色方框内的东西是服务实例。服务提供者注册进去之前是没有的。

第四步:新建服务提供者项目,命名为springcloud-provider-dept-8001

注意事项:

1. pom.xml导入所需依赖

<dependencies> <!--拿到自己写的实体类--> <dependency> <groupId>com.haige</groupId> <artifactId>springcloud-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!--test--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <!--热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!--eureka依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <!--完善监控信息--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>

?在以前的旧版本的Eureka依赖是spring-cloud-starter-eureka-server,现在改成了最新版spring-cloud-starter-netflix-eureka-server,我的Eureka依赖默认的版本是2.2.9.RELEASE。这里注意下载这个依赖可能需要一段时间。

spring-boot-starter-actuator的作用是完善监控信息:图中链接只有加了这个插件才不会报404

2. 编写application.yml

server: port: 8001 #mybatis配置 mybatis: #别名 type-aliases-package: com.haige.springcloud.pojo mapper-locations: classpath:mybatis/mapper/*.xml config-location: classpath:mybatis/mybatis-config.xml #spring配置 spring: application: name: springcloud-provider-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver #mysql8以上要在表名后面加上时区 url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=UTF-8&useSSL=false username: root password: 10086 #eureka配置 eureka: client: service-url: defaultZone: http://localhost:7001/eureka/ instance: instance-id: springcloud-provider-dept8001 #修改Eureka上的默认描述信息

application.yml配置文件里面规范了暴露的端口号为8001,同时也声明了Eureka的访问地址及端口号。由于我使用的mysql是8以上的,所以需要在url后面添加时区。

服务提供者代码框架图:

?下面是mybatis的核心配置文件:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <!-- 设置是否启动缓存 --> <setting name="cacheEnabled" value="true"/> <!-- 设置是否启用懒加载 --> <setting name="lazyLoadingEnabled" value="true"/> </settings> </configuration>

下面是mapper的配置文件:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.haige.springcloud.dao.DeptDao"> <insert id="addDept" parameterType="Dept"> insert into dept (dname,db_source) values (#{dname},DATABASE()) </insert> <select id="queryById" resultType="Dept" parameterType="Long"> select * from dept where deptno=#{deptno} </select> <select id="queryAll" resultType="Dept"> select * from dept </select> </mapper>

配置文件写好之后就是写三层架构了:

service层:

import com.haige.springcloud.pojo.Dept; import java.util.List; public interface DeptService { public boolean addDept(Dept dept); public Dept queryById(Long deptno); public List<Dept> queryAll(); } import com.haige.springcloud.dao.DeptDao; import com.haige.springcloud.pojo.Dept; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class DeptServiceImpl implements DeptService { @Autowired private DeptDao deptDao; @Override public boolean addDept(Dept dept) { return deptDao.addDept(dept); } @Override public Dept queryById(Long deptno) { return deptDao.queryById(deptno); } @Override public List<Dept> queryAll() { return deptDao.queryAll(); } }

dao层:

import com.haige.springcloud.pojo.Dept; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; import java.util.List; @Mapper @Repository public interface DeptDao { public boolean addDept(Dept dept); public Dept queryById(Long deptno); public List<Dept> queryAll(); }

controller层:

import com.haige.springcloud.pojo.Dept; import com.haige.springcloud.service.DeptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; //提供Restful服务 @RestController public class DeptController { @Autowired private DeptService deptService; @PostMapping("/dept/add") public boolean addDept(@RequestBody Dept dept){ return deptService.addDept(dept); } @GetMapping("/dept/get/{deptno}") public Dept qyeryById(@PathVariable("deptno") Long deptno){ return deptService.queryById(deptno); } @GetMapping("/dept/list") public List<Dept> qeeryAll(){ return deptService.queryAll(); } }

主启动类:

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; //启动类 @SpringBootApplication @EnableEurekaClient //在服务启动之后自动注册到eureka中 public class DeptProvider_8001 { public static void main(String[] args) { SpringApplication.run(DeptProvider_8001.class,args); } }

第五步:新建服务消费者,命名为springcloud-consumer-dept-80

1. 因为80端口在访问的时候可以缺省,所以使用80端口方便。

2. pom.xml导入所需依赖

<!--实体类+web--> <dependencies> <dependency> <groupId>com.haige</groupId> <artifactId>springcloud-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies>

controller层与浏览器建立联系:

import com.haige.springcloud.pojo.Dept; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.List; @RestController public class DeptConsumerController { //理解:消费者,不应该有service层吗? //RestTemplate....供我们直接调用,注册到Spring中 @Autowired private RestTemplate restTemplate;//提供多种便捷访问远程HTTP服务的方法,简单的restful服务模板 private static final String REST_URLPREFIX = "http://localhost:8001"; @RequestMapping("/consumer/dept/get/{deptno}") public Dept get(@PathVariable("deptno") Long deptno){ return restTemplate.getForObject(REST_URLPREFIX+"/dept/get/"+deptno,Dept.class); } @RequestMapping("/consumer/dept/add") public boolean add(Dept dept){ return restTemplate.postForObject(REST_URLPREFIX+"/dept/add",dept,Boolean.class); } @RequestMapping("/consumer/dept/list") public List<Dept> list(){ return restTemplate.getForObject(REST_URLPREFIX+"/dept/list",List.class); } }

注意上面代码里面出现了RestTemplate这个类,它是依赖里面带出来的。Dubbo是通过@Reference装配直接拿到提供者的Service,而Eureka的HTTP通信只能通过RestTemplate取调用提供者的接口。

将RestTemplate注入到容器中:

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration //相当于Spring中的application.xml public class ConfigBean { //给容器加入RestTemplate这个对象,作用:调用提供者里面的东西 @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } }


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Eureka #springboot