Fork me on GitHub

微服务服务提供者在Eureka中注册

目录

服务提供者

被其他微服务调用的微服务

首先我们用首先打开http://start.spring.io,如下图所示,

微服务服务提供者在Eureka中注册

创建报名,项目名

microservice-provider

最后点击下方的“Generate Project”按钮, 将会生成 zip包。

microservice-provider.zip

然后解压,导入idea中。

然后开始编写代码

编写服务提供者

创建一个Maven项目,依赖如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.cicoding</groupId>
<artifactId>microservice-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>microservice-provider</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<!-- springboot admin jar -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!--排除默认的tomcat-jdbc-->
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.cloud</groupId>-->
<!--<artifactId>spring-cloud-starter-openfeign</artifactId>-->
<!--</dependency>-->
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

创建实体类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.example.model;

public class UserDomain {

private Integer userId;

private String userName;

private String password;

private String phone;

public Integer getUserId() {
return userId;
}

public void setUserId(Integer userId) {
this.userId = userId;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}
}

创建DAO:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.example.dao;

import com.example.model.UserDomain;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface UserDao {

int insert(UserDomain record);

void deleteUserById(@Param("userId") Integer userId);

void updateUser(UserDomain userDomain);

List<UserDomain> selectUsers();

UserDomain findById(Integer id);
}

创建mapper的xml映射文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.dao.UserDao" >
<sql id="BASE_TABLE">
t_user
</sql>

<sql id="BASE_COLUMN">
userId,userName,password,phone
</sql>

<insert id="insert" parameterType="com.example.model.UserDomain">
INSERT INTO
<include refid="BASE_TABLE"/>
<trim prefix="(" suffix=")" suffixOverrides=",">
userName,password,
<if test="phone != null">
phone,
</if>
</trim>
<trim prefix="VALUES(" suffix=")" suffixOverrides=",">
#{userName, jdbcType=VARCHAR},#{password, jdbcType=VARCHAR},
<if test="phone != null">
#{phone, jdbcType=VARCHAR},
</if>
</trim>
</insert>

<delete id="deleteUserById">
DELETE FROM
<include refid="BASE_TABLE"/>
WHERE
userId = #{userId, jdbcType=INTEGER}
</delete>
<!-- 更新用户信息,为空的字段不进行置空 -->
<update id="updateUser" parameterType="com.example.model.UserDomain">
UPDATE
<include refid="BASE_TABLE"/>
<set>
<if test="userName != null">
userName = #{userName, jdbcType=VARCHAR},
</if>
<if test="password != null">
password = #{password, jdbcType=VARCHAR},
</if>
<if test="phone != null">
phone = #{phone, jdbcType=VARCHAR},
</if>
</set>
<where>
userId = #{userId, jdbcType=INTEGER}
</where>
</update>

<select id="selectUsers" resultType="com.example.model.UserDomain">
SELECT
<include refid="BASE_COLUMN"/>
FROM
<include refid="BASE_TABLE"/>
</select>

<select id="findById" resultType="com.example.model.UserDomain">
SELECT
<include refid="BASE_COLUMN"/>
FROM
<include refid="BASE_TABLE"/>
where userId = #{id}
</select>


</mapper>

创建controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.example.controller;

import com.example.model.UserDomain;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
private UserService userService;

@PostMapping("")
public ResponseEntity addUser(@RequestParam(value = "userName", required = true) String userName, @RequestParam(value = "password", required = true)
String password, @RequestParam(value = "phone", required = false) String phone){
UserDomain userDomain = new UserDomain();
userDomain.setUserName(userName);
userDomain.setPassword(password);
userDomain.setPhone(phone);
userService.insert(userDomain);
return ResponseEntity.ok("添加成功");
}

@DeleteMapping("")
public ResponseEntity deleteUser(@RequestParam(value = "userId", required = true) Integer userId){

userService.deleteUserById(userId);
return ResponseEntity.ok("删除成功");
}

@PutMapping("")
public ResponseEntity updateUser(@RequestParam(value = "userId", required = true) Integer userId, @RequestParam(value = "userName", required = false) String userName,
@RequestParam(value = "password", required = false) String password, @RequestParam(value = "phone", required = false) String phone ){
UserDomain userDomain = new UserDomain();
userDomain.setUserId(userId);
userDomain.setUserName(userName);
userDomain.setPassword(password);
userDomain.setPhone(phone);
userService.updateUser(userDomain);
return ResponseEntity.ok("更新成功");
}

@GetMapping("")
public ResponseEntity getUsers(){
return ResponseEntity.ok(userService.selectUsers());
}

@GetMapping("/{id}")
public UserDomain findById(@PathVariable Integer id) {
return this.userService.findById(id);
}

}
  • 其中, @GetMapping,是Spring 4.3提供的新注解。它是一个组合注解,等价于@RequestMapping(method = RequestMethod.GET),用于简化开发。同理还有@PostMapping@PutMapping@DeleteMapping@PatchMapping等。

编写启动类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class ProviderApplication {

public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}

}

@SpringBootApplication是一个组合注解,它整合了@Configuration@EnableAutoConfiguration@ComponentScan注解,并开启了Spring Boot程序的组件扫描和自动配置功能。在开发Spring Boot程序的过程中,常常会组合使用@Configuration@EnableAutoConfiguration@ComponentScan等注解,所以Spring Boot提供了@SpringBootApplication,来简化开发。

编写配置文件application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
eureka:
client:
service-url:
defaultZone: http://${eureka.instance.hostname}:8888/eureka/
instance:
hostname: localhost
logging:
level:
com:
example: debug
root: info
web: trace
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: '*'
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.model
server:
port: 8080
spring:
application:
name: microservice-provider
boot:
admin:
client:
url: http://localhost:8788
datasource:
auto-commit: true
default-auto-commit: true
driver-class-name: com.mysql.cj.jdbc.Driver
initial-size: 5
max-idle: 10
max-wait: 10000
maximum-pool-size: 100
min-idle: 5
minEvictableIdleTimeMillis: 300000
password: root
test-on-borrow: false
test-while-idle: true
time-between-eviction-runs-millis: 18800
url: jdbc:mysql://localhost:3309/mytest?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&allowPublicKeyRetrieval=true&serverTimezone=UTC&autoReconnect=true
username: root
validation-query: SELECT 1

传统Web应用开发中,常使用properties格式文件作为配置文件。Spring Boot以及Spring Cloud支持使用properties或者yml格式的文件作为配置文件。
yml文件格式是YAML(Yet Another Markup Language)编写的文件格式,YAML和properties格式的文件可互相转换,例如本节中的application.yml,就等价于如下的properties文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
server.port=8080

eureka.instance.hostname=localhost

#### 数据库连接池属性
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.url=jdbc:mysql://10.254.193.154:3306/mytest?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&allowPublicKeyRetrieval=true
spring.datasource.url=jdbc:mysql://localhost:3309/mytest?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&allowPublicKeyRetrieval=true&serverTimezone=UTC&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=root
#自动提
spring.datasource.default-auto-commit=true
#指定updates是否自动提交
spring.datasource.auto-commit=true
spring.datasource.maximum-pool-size=100
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
spring.datasource.validation-query=SELECT 1
spring.datasource.test-on-borrow=false
spring.datasource.test-while-idle=true
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.time-between-eviction-runs-millis=18800
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000

# mybatis对应的映射文件路径
mybatis.mapper-locations=classpath:mapper/*.xml
# mybatis对应的实体类
mybatis.type-aliases-package=com.example.model

#logging.config = classpath:logback.xml
logging.level.root=info
logging.level.com.example= debug

# 指定注册到eureka server上的服务名称
spring.application.name=microservice-provider


spring.boot.admin.client.url=http://localhost:8788


# 开放所有监控端点
management.endpoints.web.exposure.include=*
# 是否展示健康检查详情
management.endpoint.health.show-details = always

# 指定eureka server通信地址,注意/eureka/小尾巴不能少
#eureka.client.service-url.defaultZone=http://10.254.193.30:9001/eureka/,http://10.254.193.31:9002/eureka/,http://10.254.193.32:9003/eureka/
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:8888/eureka/

# 是否注册IP到eureka server,如不指定或设为false,那就会注册主机名到eureka server
#eureka.instance.prefer-ip-address=true
#eureka.instance.ip-address=10.254.193.120
#eureka.instance.prefer-ip-address=false
#eureka.instance.hostname=10.254.193.129
logging.level.web=trace

从中不难看出,YAML比properties结构清晰;可读性、可维护性也更强,并且语法非常简洁。因此,本书使用YAML格式作为配置文件。但,yml有严格的缩进,并且key与value之间使用: 分隔,冒号后的空格不能少,请大家注意

测试

启动eureka,然后启动我们的microservices-provider,在eureka中可以看到注册上去了

image-20191226091541936

至此,我们完成了服务提供者注册到eureka!

相关文章