03.SpringCloud - Spring Cloud Netflix 之 Eureka服务注册中心,Ribbon负载均衡(三)
03.SpringCloud - Spring Cloud Netflix 之 Eureka服务注册中心,Ribbon负载均衡(三)
阅读本文前可先参考
SpringCloud - Spring Cloud根/父项目,开发准备(二)_MinggeQingchun的博客-CSDN博客
我们首先来看下不需要注册服务中心,服务消费者 直接调用 服务提供者
一、服务消费者 直接 访问 服务提供者
1、服务提供者
1、新建一个springboot Module(springcloud-1-noregistry-provider),设置父项目(服务提供者)
2、添加 web,mysql,mybatis依赖,以及处理资源resoureces,java等插件
<!--继承统一的父项目-->
<parent>
<groupId>com.company</groupId>
<artifactId>springcloud-demo</artifactId>
<version>1.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.company</groupId>
<artifactId>springcloud-1-noregistry-provider</artifactId>
<version>1.0.0</version>
<name>springcloud-1-noregistry-provider</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--spring web 起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MySQL的jdbc驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis起步依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
</dependencies>
<build>
<!--处理资源目录-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
<plugins>
<!--mybatis代码自动生成插件-->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<!--配置文件的位置: 在项目的根目录下,和src平级的-->
<configurationFile>GeneratorMapper.xml</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3、application.prperties配置文件中配置访问端口9001,以及 mysql数据库等信息
server.port=9001
#设置mysql数据库连接信息
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=admin123456
4、可使用代码自动生成响应的mapper,model,service等包以及响应类
public class Goods {
private Integer goodId;
private String goodName;
private String goodNameDesc;
private BigDecimal goodPrice;
private String goodImgUrl;
private Integer goodStore;
private Date startTime;
private Date endTime;
public Integer getGoodId() {
return goodId;
}
public void setGoodId(Integer goodId) {
this.goodId = goodId;
}
public String getGoodName() {
return goodName;
}
public void setGoodName(String goodName) {
this.goodName = goodName;
}
public String getGoodNameDesc() {
return goodNameDesc;
}
public void setGoodNameDesc(String goodNameDesc) {
this.goodNameDesc = goodNameDesc;
}
public BigDecimal getGoodPrice() {
return goodPrice;
}
public void setGoodPrice(BigDecimal goodPrice) {
this.goodPrice = goodPrice;
}
public Integer getGoodStore() {
return goodStore;
}
public void setGoodStore(Integer goodStore) {
this.goodStore = goodStore;
}
public String getGoodImgUrl() {
return goodImgUrl;
}
public void setGoodImgUrl(String goodImgUrl) {
this.goodImgUrl = goodImgUrl;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
@Override
public String toString() {
return "Goods{" +
"goodId=" + goodId +
", goodName='" + goodName + '\'' +
", goodNameDesc='" + goodNameDesc + '\'' +
", goodPrice=" + goodPrice +
", goodStore='" + goodStore + '\'' +
", goodImgUrl='" + goodImgUrl + '\'' +
", startTime=" + startTime +
", endTime=" + endTime +
'}';
}
}
@Mapper
public interface GoodsMapper {
List<Goods> selectAllGoods();
}
@Service
public class GoodsServiceImpl implements GoodsService {
@Autowired
private GoodsMapper goodsMapper;
public List<Goods> getAllGoods() {
return goodsMapper.selectAllGoods();
}
public Goods getGoodsById(Integer goodsId) {
return goodsMapper.selectByPrimaryKey(goodsId);
}
public int decrByStore(Integer goodsId, Integer buyNum) {
return goodsMapper.updateByStore(goodsId, buyNum);
}
}
<?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.company.mapper.GoodsMapper">
<resultMap id="BaseResultMap" type="com.company.model.Goods">
<id column="good_id" jdbcType="INTEGER" property="goodId"/>
<result column="good_name" jdbcType="VARCHAR" property="goodName"/>
<result column="good_name_desc" jdbcType="VARCHAR" property="goodNameDesc"/>
<result column="good_price" jdbcType="DECIMAL" property="goodPrice"/>
<result column="good_img_url" jdbcType="VARCHAR" property="goodImgUrl"/>
<result column="good_store" jdbcType="INTEGER" property="goodStore"/>
<result column="start_time" jdbcType="TIMESTAMP" property="startTime"/>
<result column="end_time" jdbcType="TIMESTAMP" property="endTime"/>
</resultMap>
<sql id="Base_Column_List">
good_id, good_name, good_name_desc, good_price, good_store,good_img_url, start_time, end_time
</sql>
<select id="selectAllGoods" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from goods
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from goods
where good_id = #{goodId,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete
from goods
where good_id = #{goodId,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.company.model.Goods">
insert into goods (good_id, good_name, good_price,good_store)
values (#{goodId,jdbcType=INTEGER}, #{goodName,jdbcType=VARCHAR}, #{goodPrice,jdbcType=DECIMAL},
#{goodStore,jdbcType=INTEGER})
</insert>
<insert id="insertSelective" parameterType="com.company.model.Goods">
insert into goods
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="goodId != null">
good_id,
</if>
<if test="goodName != null">
good_name,
</if>
<if test="goodPrice != null">
good_price,
</if>
<if test="goodStore != null">
good_store,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="goodId != null">
#{goodId,jdbcType=INTEGER},
</if>
<if test="goodName != null">
#{goodName,jdbcType=VARCHAR},
</if>
<if test="goodPrice != null">
#{goodPrice,jdbcType=DECIMAL},
</if>
<if test="goodStore != null">
#{goodStore,jdbcType=INTEGER},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.company.model.Goods">
update goods
<set>
<if test="goodName != null">
good_name = #{goodName,jdbcType=VARCHAR},
</if>
<if test="goodPrice != null">
good_price = #{goodPrice,jdbcType=DECIMAL},
</if>
<if test="goodStore != null">
good_store = #{goodStore,jdbcType=INTEGER},
</if>
</set>
where good_id = #{goodsId,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.company.model.Goods">
update goods
set good_name = #{goodName,jdbcType=VARCHAR},
good_price = #{goodPrice,jdbcType=DECIMAL},
good_store = #{goodStore,jdbcType=INTEGER}
where good_id = #{goodsId,jdbcType=INTEGER}
</update>
<update id="updateByStore">
update goods
set good_store = good_store - #{buyNum,jdbcType=INTEGER}
where good_id = #{goodsId,jdbcType=INTEGER}
</update>
</mapper>
5、创建服务提供者访问方法,基于RESTFUL风格
@RestController
public class GoodsController {
@Autowired
private GoodsService goodsService;
@GetMapping(value = "/service/goodList")
public List<Goods> goodList(){
List<Goods> goodsList = goodsService.getAllGoods();
System.out.println("查询商品列表成功:");
for (Goods good:goodsList) {
System.out.println("查询商品:"+ good);
}
return goodsList;
}
}
6、启动springboot启动类,访问应用,测试能否正常运行
http://localhost:9001/service/goodList
2、服务消费者
1、新建一个springboot Module(springcloud-1-noregistry-consumer),设置父项目 (服务消费者)
2、添加 web依赖
<!--继承统一的父项目-->
<parent>
<groupId>com.company</groupId>
<artifactId>springcloud-demo</artifactId>
<version>1.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.company</groupId>
<artifactId>springcloud-1-noregistry-consumer</artifactId>
<version>1.0.0</version>
<name>springcloud-1-noregistry-consumer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--spring web 起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3、application.prperties配置文件中配置访问端口8081
4、创建一个RestConfig配置类,创建RestTemplate
RestTemplate
Spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式
@Configuration
public class RestConfig {
@Bean
public RestTemplate restTemplate () {
return new RestTemplate();
}
}
5、创建服务消费者访问方法,基于RESTFUL风格
@RestController
public class GoodsController {
private final String GOODS_SERVICE_URL = "http://localhost:9001/service/goodList";
@Autowired
private RestTemplate restTemplate;
@GetMapping(value = "/springcloud/goodList")
public @ResponseBody Object getGoodList(){
//调用远程的一个controller(Restful风格调用)
ResponseEntity<Object> responseEntity = restTemplate.getForEntity(GOODS_SERVICE_URL, Object.class);
return responseEntity.getBody();
}
}
6、启动springboot启动类,访问应用,测试能否正常运行 http://localhost:8081/springcloud/goodList
二、Eureka 服务注册中心
通过手动指定每个服务来实现调用,相当低效,当服务接口增多,手动指定接口地址变得难以维护
Spring Cloud(特指 Spring Cloud Netflix) 提供了多种服务注册与发现的实现方式,如:Eureka、Consul、Zookeeper
Spring Cloud(特指 Spring Cloud Netflix)支持得最好的是 Eureka,其次是 Consul,再次是 Zookeeper;当然后续还会说到 Spring Cloud Alibaba的 Nacos
服务注册
服务注册:将服务所在主机、端口、版本号、通信协议等信息登记到注册中心上
服务发现
服务发现:服务消费者向注册中心请求已经登记的服务列表,然后得到某个服务的主机、端口、版本号、通信协议等信息,从而实现对具体服务的调用;
Eureka
Eureka 是 Netflix 公司开发的一款开源的服务注册与发现组件
Spring Cloud 将 Eureka 与 Netflix 中的其他开源服务组件(例如 Ribbon、Feign 以及 Hystrix 等)一起整合进 Spring Cloud Netflix 模块中,整合后的组件全称为 Spring Cloud Netflix Eureka。
Eureka 是 Spring Cloud Netflix 模块的子模块,它是 Spring Cloud 对 Netflix Eureka 的二次封装,主要负责 Spring Cloud 的服务注册与发现功能。
Spring Cloud 使用 Spring Boot 思想为 Eureka 增加了自动化配置,开发人员只需要引入相关依赖和注解,就能将 Spring Boot 构建的微服务轻松地与 Eureka 进行整合。
1、Spring Cloud Netflix 架构图
Service Provider: 暴露服务的服务提供方
Service Consumer:调用远程服务的服务消费方。
EureKa Server: 服务注册中心和服务发现中心
2、Eureka 两大组件
Eureka 采用 CS(Client/Server,客户端/服务器) 架构,它包括以下两大组件:
Eureka Server:Eureka 服务注册中心,主要用于提供服务注册功能。当微服务启动时,会将自己的服务注册到 Eureka Server。Eureka Server 维护了一个可用服务列表,存储了所有注册到 Eureka Server 的可用服务的信息,这些可用服务可以在 Eureka Server 的管理界面中直观看到。
Eureka Client:Eureka 客户端,通常指的是微服务系统中各个微服务,主要用于和 Eureka Server 进行交互。在微服务应用启动后,Eureka Client 会向 Eureka Server 发送心跳(默认周期为 30 秒)。若 Eureka Server 在多个心跳周期内没有接收到某个 Eureka Client 的心跳,Eureka Server 将它从可用服务列表中移除(默认 90 秒)。
注:"心跳"指的是一段定时发送的自定义信息,让对方知道自己"存活",以确保连接的有效性。大部分 CS 架构的应用程序都采用了心跳机制,服务端和客户端都可以发心跳。通常情况下是客户端向服务器端发送心跳包,服务端用于判断客户端是否在线。
1、Eureka注册服务端
1、新建一个springboot Module(springcloud-3-service-eureka),设置父项目(服务注册中心)
2、添加 web,eureka-server 依赖
添加 eureka server 的依赖!!!spring-cloud-starter-netflix-eureka-server
<!--Spring Cloud 的 eureka-server 起步依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--继承统一的父项目-->
<parent>
<groupId>com.company</groupId>
<artifactId>springcloud-demo</artifactId>
<version>1.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.company</groupId>
<artifactId>springcloud-3-service-eureka</artifactId>
<version>1.0.0</version>
<name>springcloud-3-service-eureka</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--spring web 起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Spring Cloud 的 eureka-server 起步依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3、application.prperties配置文件中配置访问端口8761,以及配置 Eureka服务注册中心信息
#内嵌Tomcat端口
server.port=8761
#设置该服务注册中心的hostname
eureka.instance.hostname=localhost
#由于目前创建的应用是一个服务注册中心,而不是普通应用;默认情况下,这个应用会向注册中心(它自己)注册自己,设置FALSE表示禁止自己向自己注册的默认行为
eureka.client.register-with-eureka=false
#表示不去从服务端检索其他服务信息,因为自己就是服务端,服务注册中心本身职责就是维护服务实例,不需要去检索其他服务
eureka.client.fetch-registry=false
#指定服务注册中心的位置 eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
4、在 Spring Boot 的入口类上添加一个**@EnableEurekaServer** 注解,开启 Eureka 注册中心服务端
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer //开启Eureka服务端
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
5、启动 SpringBoot 程序,main 方法运行,浏览器输入访问
http://localhost:8761/
Eureka控制面板界面如下
Eureka控制面板界面详细参数可参考 https://blog.csdn.net/MinggeQingchun/article/details/125261048
2、Eureka注册服务提供者
1、新建一个springboot Module(springcloud-3-service-eureka-provider),设置父项目(服务提供者)
2、添加 web,mysql,mybatis,springcloud的common公共服务,springboot自动热部署,spring-cloud-starter-netflix-eureka-client等 依赖,以及处理资源resoureces,java等插件
eureka 客户端的依赖!!!spring-cloud-starter-netflix-eureka-client
<!--spring-cloud-starter-netflix-eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--继承统一的父项目-->
<parent>
<groupId>com.company</groupId>
<artifactId>springcloud-demo</artifactId>
<version>1.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.company</groupId>
<artifactId>springcloud-3-service-eureka-provider</artifactId>
<version>1.0.0</version>
<name>springcloud-3-service-eureka-provider</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--spring web 起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MySQL的jdbc驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis起步依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!--依赖统一的springcloud-service-commons项目-->
<dependency>
<groupId>com.company</groupId>
<artifactId>springcloud-2-service-common</artifactId>
<version>1.0.0</version>
</dependency>
<!-- springboot 开发自动热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!--spring-cloud-starter-netflix-eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<build>
<!--处理资源目录-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<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>
</build>
3、application.prperties配置文件中配置访问端口9001,mysql数据库,以及 服务名称 和 eureka注册中心 等信息
server.port=9001
#设置应用名称,对应Eureka控制台下 DS Replicas 的 Application
spring.application.name=springcloud-3-service-eureka-provider
#设置mysql数据库连接信息
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=admin123456
#每间隔5s,向Eureka服务注册中心发送一次心跳,证明服务是否依然"存活"
eureka.instance.lease-renewal-interval-in-seconds=5
#告诉服务端,如果10s之内没有发送心跳,就代表故障,将本服务踢出
eureka.instance.lease-expiration-duration-in-seconds=10
#告诉服务端,服务实例以IP作为链接,不是取机器名
eureka.instance.prefer-ip-address=false
#注册服务实例名称
eureka.instance.instance-id=springcloud-3-service-eureka-provider
#注册中心的链接地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
注:
这里需要配置一下应用名称,对应Eureka控制台下 DS Replicas 的 Application
#设置应用名称,对应Eureka控制台下 DS Replicas 的 Application
spring.application.name=springcloud-3-service-eureka-provider
如果没设置
设置了应用名称
4、在 Spring Boot 的启动类中,添加**@EnableEurekaClient**注解,表明是一个 eureka 客户端,让服务提供者可以连接 eureka 注册中心
@EnableEurekaClient //开启 Eureka client服务
@SpringBootApplication
public class Eureka3ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(Eureka3ProviderApplication.class, args);
}
}
5、可使用代码自动生成响应的mapper,model,service等包以及响应类(可放在公共服务Module common中)
public class Goods {
private Integer goodId;
private String goodName;
private String goodNameDesc;
private BigDecimal goodPrice;
private String goodImgUrl;
private Integer goodStore;
private Date startTime;
private Date endTime;
public Integer getGoodId() {
return goodId;
}
public void setGoodId(Integer goodId) {
this.goodId = goodId;
}
public String getGoodName() {
return goodName;
}
public void setGoodName(String goodName) {
this.goodName = goodName;
}
public String getGoodNameDesc() {
return goodNameDesc;
}
public void setGoodNameDesc(String goodNameDesc) {
this.goodNameDesc = goodNameDesc;
}
public BigDecimal getGoodPrice() {
return goodPrice;
}
public void setGoodPrice(BigDecimal goodPrice) {
this.goodPrice = goodPrice;
}
public Integer getGoodStore() {
return goodStore;
}
public void setGoodStore(Integer goodStore) {
this.goodStore = goodStore;
}
public String getGoodImgUrl() {
return goodImgUrl;
}
public void setGoodImgUrl(String goodImgUrl) {
this.goodImgUrl = goodImgUrl;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
@Override
public String toString() {
return "Goods{" +
"goodId=" + goodId +
", goodName='" + goodName + '\'' +
", goodNameDesc='" + goodNameDesc + '\'' +
", goodPrice=" + goodPrice +
", goodStore='" + goodStore + '\'' +
", goodImgUrl='" + goodImgUrl + '\'' +
", startTime=" + startTime +
", endTime=" + endTime +
'}';
}
}
@Mapper
public interface GoodsMapper {
List<Goods> selectAllGoods();
}
@Service
public class GoodsServiceImpl implements GoodsService {
@Autowired
private GoodsMapper goodsMapper;
public List<Goods> getAllGoods() {
return goodsMapper.selectAllGoods();
}
public Goods getGoodsById(Integer goodsId) {
return goodsMapper.selectByPrimaryKey(goodsId);
}
public int decrByStore(Integer goodsId, Integer buyNum) {
return goodsMapper.updateByStore(goodsId, buyNum);
}
}
<?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.company.mapper.GoodsMapper">
<resultMap id="BaseResultMap" type="com.company.model.Goods">
<id column="good_id" jdbcType="INTEGER" property="goodId"/>
<result column="good_name" jdbcType="VARCHAR" property="goodName"/>
<result column="good_name_desc" jdbcType="VARCHAR" property="goodNameDesc"/>
<result column="good_price" jdbcType="DECIMAL" property="goodPrice"/>
<result column="good_img_url" jdbcType="VARCHAR" property="goodImgUrl"/>
<result column="good_store" jdbcType="INTEGER" property="goodStore"/>
<result column="start_time" jdbcType="TIMESTAMP" property="startTime"/>
<result column="end_time" jdbcType="TIMESTAMP" property="endTime"/>
</resultMap>
<sql id="Base_Column_List">
good_id, good_name, good_name_desc, good_price, good_store,good_img_url, start_time, end_time
</sql>
<select id="selectAllGoods" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from goods
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from goods
where good_id = #{goodId,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete
from goods
where good_id = #{goodId,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.company.model.Goods">
insert into goods (good_id, good_name, good_price,good_store)
values (#{goodId,jdbcType=INTEGER}, #{goodName,jdbcType=VARCHAR}, #{goodPrice,jdbcType=DECIMAL},
#{goodStore,jdbcType=INTEGER})
</insert>
<insert id="insertSelective" parameterType="com.company.model.Goods">
insert into goods
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="goodId != null">
good_id,
</if>
<if test="goodName != null">
good_name,
</if>
<if test="goodPrice != null">
good_price,
</if>
<if test="goodStore != null">
good_store,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="goodId != null">
#{goodId,jdbcType=INTEGER},
</if>
<if test="goodName != null">
#{goodName,jdbcType=VARCHAR},
</if>
<if test="goodPrice != null">
#{goodPrice,jdbcType=DECIMAL},
</if>
<if test="goodStore != null">
#{goodStore,jdbcType=INTEGER},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.company.model.Goods">
update goods
<set>
<if test="goodName != null">
good_name = #{goodName,jdbcType=VARCHAR},
</if>
<if test="goodPrice != null">
good_price = #{goodPrice,jdbcType=DECIMAL},
</if>
<if test="goodStore != null">
good_store = #{goodStore,jdbcType=INTEGER},
</if>
</set>
where good_id = #{goodsId,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.company.model.Goods">
update goods
set good_name = #{goodName,jdbcType=VARCHAR},
good_price = #{goodPrice,jdbcType=DECIMAL},
good_store = #{goodStore,jdbcType=INTEGER}
where good_id = #{goodsId,jdbcType=INTEGER}
</update>
<update id="updateByStore">
update goods
set good_store = good_store - #{buyNum,jdbcType=INTEGER}
where good_id = #{goodsId,jdbcType=INTEGER}
</update>
</mapper>
6、创建服务提供者访问方法,基于RESTFUL风格
@RestController
public class GoodsController {
@Autowired
private GoodsService goodsService;
@GetMapping(value = "/eureka/service/goodList")
public List<Goods> goodList(){
List<Goods> goodsList = goodsService.getAllGoods();
System.out.println("查询商品列表成功:");
for (Goods good:goodsList) {
System.out.println("查询商品:"+ good);
}
return goodsList;
}
}
7、启动springboot启动类,访问应用,再去查看 Eureka 控制中心控制台服务 http://localhost:9001/eureka/service/goodList
http://localhost:8761/
3、Eureka注册服务消费者
1、新建一个springboot Module(springcloud-3-service-eureka-consumer),设置父项目 (服务消费者)
2、添加 web依赖,springcloud的common公共服务,springboot自动热部署,spring-cloud-starter-netflix-eureka-client 客户端支持
eureka 客户端的依赖!!!spring-cloud-starter-netflix-eureka-client
<!--spring-cloud-starter-netflix-eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--继承统一的父项目-->
<parent>
<groupId>com.company</groupId>
<artifactId>springcloud-demo</artifactId>
<version>1.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.company</groupId>
<artifactId>springcloud-3-service-eureka-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-3-service-eureka-consumer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--spring web 起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--依赖统一的springcloud-service-commons项目-->
<dependency>
<groupId>com.company</groupId>
<artifactId>springcloud-2-service-common</artifactId>
<version>1.0.0</version>
</dependency>
<!-- springboot 开发自动热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!--spring-cloud-starter-netflix-eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3、application.prperties配置文件中配置访问端口8081
server.port=8081
#设置应用名称,对应Eureka控制台下 DS Replicas 的 Application
spring.application.name=springcloud-3-service-eureka-consumer
#每间隔5s,向Eureka服务注册中心发送一次心跳,证明服务是否依然"存活"
eureka.instance.lease-renewal-interval-in-seconds=30
#告诉服务端,如果10s之内没有发送心跳,就代表故障,将本服务踢出
eureka.instance.lease-expiration-duration-in-seconds=60
#告诉服务端,服务实例以IP作为链接,不是取机器名
eureka.instance.prefer-ip-address=false
#注册服务实例名称
eureka.instance.instance-id=springcloud-3-service-eureka-consumer
#注册中心的链接地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
4、Springboot启动类上添加**@EnableEurekaClient** 注解,表明是一个 eureka 客户端,让服务消费者可以使用 eureka 注册中心
@EnableEurekaClient //开启 Eureka client服务
@SpringBootApplication
public class Eureka3ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(Eureka3ConsumerApplication.class, args);
}
}
5、创建一个RestConfig配置类,创建RestTemplate;使用Ribbon调用(服务的发现由 eureka 客户端实现,而服务的消费由 Ribbon 实现)
注:
服务的发现由 eureka 客户端实现,而服务的消费由 Ribbon 实现,因此服务的调用需要 eureka 客户端和 Ribbon,两者配合起来才能实现;
Eureka 客户端是一个 Java 客户端,用来连接 Eureka 服务端,与服务端进行交互、负载均衡,服务的故障切换等;
Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡器,当使用 Ribbon 对服务进行访问的时候,它会扩展 Eureka 客户端的服务发现功能,实现从Eureka 注册中心中获取服务端列表,并通过 Eureka 客户端来确定服务端是否己经启动。
Ribbon 在 Eureka 客户端服务发现的基础上,实现了对服务实例的选择策略,从而实现对服务的负载均衡消费。
@Configuration
public class RestConfig {
//使用Ribbon实现负载均衡的调用
@LoadBalanced
@Bean
public RestTemplate restTemplate () {
return new RestTemplate();
}
}
6、创建服务消费者访问方法,基于RESTFUL风格
@RestController
public class GoodsController {
private final String GOODS_SERVICE_URL = "http://localhost:9001/service/goodList";
private final String GOODS_SERVICE_EUREKA_URL = "http://springcloud-3-service-eureka-provider/eureka/service/goodList";
@Autowired
private RestTemplate restTemplate;
@GetMapping(value = "/springcloud/eureka/goodList")
public @ResponseBody Object getGoodList(){
//调用远程的一个controller(Restful风格调用)
ResponseEntity<Object> responseEntity = restTemplate.getForEntity(GOODS_SERVICE_EUREKA_URL, Object.class);
return responseEntity.getBody();
}
}
7、启动springboot启动类,访问应用,测试能否正常运行 http://localhost:8081/springcloud/eureka/goodList
这时再去访问 Eureka 控制台,就会发现一个服务提供者,和一个服务消费者
来源:https://blog.csdn.net/MinggeQingchun/article/details/125274095