一、Spring cloud 相关组件停更及替换方案(看图)
image.png二、说明
本文章使用的cloud组件:
- eureka
- ribbon
- openfeign
三、版本说明
spring boot 与 cloud 版本对应关系:
Springboot-cloud版本对应关系.jpeg根据官网推荐,本文使用spring boot 2.2.2 + spring cloud Hoxton.SR1
当前最佳:spring boot 2.3.1.RELEASE + spring cloud Hoxton.SR6
其它:
jdk1.8, maven 3.6.3
四、开始工程
工程介绍:
订单模块——>eureka(高可用)——>(负载均衡)支付模块
修改hosts文件:
添加一行:
127.0.0.1 localhost2
1、工程目录
工程目录.png2、父工程
使用idea创建新工程
使用maven工具创建-选择jdk1.8-修改项目名、groupid
创建父工程.png
修改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.learning.springcloud</groupId>
<artifactId>new-cloud</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Maven</name>
<!-- FIXME change it to the project's website -->
<url>http://maven.apache.org/</url>
<inceptionYear>2001</inceptionYear>
<distributionManagement>
<site>
<id>website</id>
<url>scp://webhost.company.com/www/website</url>
</site>
</distributionManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<locales>en,fr</locales>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<!-- spring boot 2.2.2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring cloud Hoxton.SR1 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
</project>
其中重点:
- <packaging>pom</packaging>父工程必须指定参数为pom
- <dependencyManagement>
...
</dependencyManagement>可以被子项目继承的依赖信息,子项目引入相同依赖时可以不指定版本号,如果指定,则会使用自己的版本
从idea面板右侧的maven工具栏,先clean再install
3、创建子工程eureka-server-7001
右击父工程根目录,新建module,使用maven工具,选择jdk1.8,finish
pom文件添加依赖:
<dependencies>
<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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>2.2.2.RELEASE</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
pom文件其它不用改
创建src/main/resources/application.yml配置文件
内容如下(注意yml文件格式):
server:
port: 7001
eureka:
instance:
hostname: localhost #当前server名
client:
register-with-eureka: false #此client不在eureka中注册,因为是其本身
fetch-registry: false #不要去注册中心获取其他服务的地址
service-url:
defaultZone: http://localhost2:7002/eureka/ #注册到eureka-server-7002
两个eureka相互注册实现高可用,也可使用多个
创建启动类com.learning.springcloud.Server7001Main
package com.learning.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @author xxxx
* @version 1.0
* @create 2020/8/2 4:44 下午
*/
@SpringBootApplication
@EnableEurekaServer
public class Server7001Main {
public static void main(String[] args) {
SpringApplication.run(Server7001Main.class,args);
}
}
4、创建子工程eureka-server-7002
和eureka-server-7001步骤一致
pom文件直接复制7001的
只需对application.yml文件简单修改:
server:
port: 7002
eureka:
instance:
hostname: localhost2 #当前server名
client:
register-with-eureka: false #此client不在eureka中注册,因为是其本身
fetch-registry: false #不要去注册中心获取其他服务的地址
service-url:
defaultZone: http://localhost:7001/eureka/ #注册到eureka-server-7002
主启动类改个名就可以了
启动两个子工程,通过浏览器访问http:localhost:7001,看到如下页面及成功配置高可用server eureka.png5、创建子工程commons-api
此工程是多个子工程用到的公用代码,将作为依赖引入其它子项目
pom文件引依赖:
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
创建类com.learning.springcloud.entities.Payment
package com.learning.springcloud.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author xxxx
* @version 1.0
* @create 2020/8/2 5:21 下午
*/
@Data //自动生成get、set方法
@AllArgsConstructor //自动生成全参构造器
@NoArgsConstructor //自动生成无参构造器
public class Payment {
private Long id;
private String serial;
}
创建类com.learning.springcloud.entities.CommonResult
package com.learning.springcloud.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author xxxx
* @version 1.0
* @create 2020/8/2 5:21 下午
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
private Integer code;
private String message;
private T data;
}
clean项目、install项目
创建子工程payment-8001
pom文件加依赖
<dependencies>
<dependency>
<groupId>org.learning.springcloud</groupId>
<artifactId>commons-api</artifactId>
<version>1.0-SNAPSHOT</version>
</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>2.2.2.RELEASE</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
</dependencies>
创建src/main/resources/application.yml配置文件
server:
port: 8001
spring:
application:
name: cloud-payment #本微服务名称
datasource: #jdbs连接参数
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/db2020?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 12345687
eureka:
client:
register-with-eureka: true #要注册到服务中心
fetch-registry: true #可以从服务中心获取其它服务信息
service-url: http://localhost:7001/eureka,http://localhost2:7002/eureka #向两个服务中心进行注册
instance:
instance-id: payment8001 #微服务的具体实例别名
prefer-ip-address: true
mybatis:
mapper-locations: classpath:mapper/*.xml #mybatis配置mapper地址
type-aliases-package: com.learning.springcloud.entities #对应的实体类包
启动类com.learning.springcloud.Payment8001Main
package com.learning.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @author xxxx
* @version 1.0
* @create 2020/8/2 5:41 下午
*/
@SpringBootApplication
@EnableEurekaClient
public class Payment8001Main {
public static void main(String[] args) {
SpringApplication.run(Payment8001Main.class,args);
}
}
创建接口com.learning.springcloud.dao.PaymentDao
package com.learning.springcloud.dao;
import com.learning.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @author xxxx
* @version 1.0
* @create 2020/8/2 5:42 下午
*/
@Mapper //重要注解
public interface PaymentDao {
Payment getPaymentById(@Param("id") Long id);
int create(Payment payment);
}
创建src/main/resources/mapper/PaymentMapper.xml
<?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.learning.springcloud.dao.PaymentDao">
<insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
insert into payment(serial) values (#{serial});
</insert>
<resultMap id="baseResultMap" type="com.learning.springcloud.entities.Payment">
<id column="id" property="id" jdbcType="BIGINT"/>
<id column="serial" property="serial" jdbcType="VARCHAR"/>
</resultMap>
<select id="getPaymentById" parameterType="Long" resultMap="baseResultMap">
select * from payment where id=#{id};
</select>
</mapper>
namespace属性别忘记
创建接口com.learning.springcloud.service.PaymentService及实现类com.learning.springcloud.service.impl.PaymentServiceImpl
package com.learning.springcloud.service;
import com.learning.springcloud.entities.Payment;
/**
* @author xxxx
* @version 1.0
* @create 2020/8/2 6:14 下午
*/
public interface PaymentService {
Payment getPaymentById(Long id);
int create(Payment payment);
}
package com.learning.springcloud.service.impl;
import com.learning.springcloud.dao.PaymentDao;
import com.learning.springcloud.entities.Payment;
import com.learning.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @author xxxx
* @version 1.0
* @create 2020/8/2 6:15 下午
*/
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentDao paymentDao;
@Override
public Payment getPaymentById(Long id) {
return paymentDao.getPaymentById(id);
}
@Override
public int create(Payment payment) {
return paymentDao.create(payment);
}
}
com.learning.springcloud.controller.PaymentController
package com.learning.springcloud.controller;
import com.learning.springcloud.entities.CommonResult;
import com.learning.springcloud.entities.Payment;
import com.learning.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author xxxx
* @version 1.0
* @create 2020/8/2 6:18 下午
*/
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@Value("${server.port}")
private String serverPort;
@GetMapping(value = "/payment/get/{id}")
CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
Payment result = paymentService.getPaymentById(id);
log.info("******查询结果:{}", result);
if (result != null){
return new CommonResult<Payment>(200, "select success", result);
}else {
return new CommonResult<Payment>(444, "select fail");
}
}
@PostMapping(value = "/payment/create")
CommonResult<Integer> create(@RequestBody Payment payment){
log.info("~~~~~~~~~~~~~XXXXX:{}",payment);
int result = paymentService.create(payment);
log.info("******插入结果:" + result);
if (result > 0){
return new CommonResult<>(200, "create success, server_port:" + serverPort, result);
}else {
return new CommonResult<>(444, "create fail");
}
}
}
子项目payment-8002
基本复制8001
application.yml配置文件有所变化
端口改为8002
instance-id为payment8002
可以启动服务器后再启动两个payment微服务,在浏览器上进行访问验证是否成功http://localhost:8002/payment/get/1
创建子工程order-80
pom文件依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>2.2.2.RELEASE</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.learning.springcloud</groupId>
<artifactId>commons-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
application.yml
server:
port: 80
spring:
application:
name: order-server-80
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka,http://localhost2:7002/eureka
ribbon:
ReadTimeout: 5000
ConnectTimeout: 5000
logging:
level:
com.springcloud.demo.services.PaymentFeignService: debug
com.learning.springcloud.config.FeignConfig
package com.learning.springcloud.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author xxxx
* @version 1.0
* @create 2020/8/3 10:22 上午
*/
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
com.learning.springcloud.service.OrderPaymentService
openfeign通过ribbon实现负载均衡
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import javax.annotation.Resource;
/**
* @author xxxx
* @version 1.0
* @create 2020/8/3 10:09 上午
*/
@Service
@FeignClient(value = "cloud-payment")
public interface OrderPaymentService {
@GetMapping(value = "/payment/get/{id}")
CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
@GetMapping(value = "/payment/create")
CommonResult<Integer> create(@RequestBody Payment payment);
}
com.learning.springcloud.controller.OrderPaymentController
package com.learning.springcloud.controller;
import com.learning.springcloud.entities.CommonResult;
import com.learning.springcloud.entities.Payment;
import com.learning.springcloud.service.OrderPaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author xxxx
* @version 1.0
* @create 2020/8/3 9:55 上午
*/
@RestController
@Slf4j
public class OrderPaymentController {
@Resource
private OrderPaymentService orderPaymentService;
@GetMapping(value = "/order/payment/get/{id}")
CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
return orderPaymentService.getPaymentById(id);
}
@GetMapping(value = "/order/payment/create")
CommonResult<Integer> create(Payment payment){
return orderPaymentService.create(payment);
}
}
一个简单的cloud后端服务已完成,实现类注册中心的高可用和子服务的负载均衡,启动顺序为先启动两个eureka注册中心,再启动其它微服务,然后可以通过浏览器访问验证http://localhost/order/payment/create?id=3&serial=ere
本文章参照尚硅谷周阳老师视频完成,进一步学习可以网上搜索他的视频
网友评论