SpringBoot-Eureka 服务注册与发现-环境搭建


一、创建 Maven 父工程,springcloud2022

1. 导入 POM 依赖


pom



	UTF-8
	1.8
	1.8
	4.12
	1.2.17
	1.16.18
	5.1.47
	1.1.16
	1.3.0




	
		
		
			org.springframework.boot
			spring-boot-dependencies
			2.2.2.RELEASE
			pom
			import
		
		
		
			org.springframework.cloud
			spring-cloud-dependencies
			Hoxton.SR1
			pom
			import
		
		
		
			com.alibaba.cloud
			spring-cloud-alibaba-dependencies
			2.1.0.RELEASE
			pom
			import
		

		
			mysql
			mysql-connector-java
			${mysql.version}
		
		
			com.alibaba
			druid
			${druid.version}
		
		
			org.mybatis.spring.boot
			mybatis-spring-boot-starter
			${mybatis.spring.boot.version}
		
		
			junit
			junit
			${junit.version}
		
		
			log4j
			log4j
			${log4j.version}
		
		
			org.projectlombok
			lombok
			${lombok.version}
			true
		
	



	
		
			org.springframework.boot
			spring-boot-maven-plugin
			
				true
				true
			
		
	

2. 在 Maven 管理界面,跳过单元测试,执行 mvn:install 命令

二、创建子模块,服务提供者,cloud-provider-payment8001

1. 添加 POM 依赖


	
		org.springframework.boot
		spring-boot-starter-web
	
	
		org.springframework.boot
		spring-boot-starter-actuator
	
	
		org.mybatis.spring.boot
		mybatis-spring-boot-starter
	
	
		com.alibaba
		druid-spring-boot-starter
		1.1.10
	
	
		mysql
		mysql-connector-java
	
	
		org.springframework.boot
		spring-boot-starter-jdbc
	
	
		org.springframework.boot
		spring-boot-devtools
		runtime
		true
	
	
		org.projectlombok
		lombok
		true
	
	
		org.springframework.boot
		spring-boot-starter-test
		test
	

2. 编写 yml,启动类(省略)

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service	# 注册服务名
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloud2022?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: mh359687
mybatis:
  mapperLocations: classpath:/mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities

3. sql 建库建表

CREATE DATABASE  IF NOT EXISTS cloud2022 DEFAULT CHARACTER SET utf8 ;

USE cloud2022;

DROP TABLE IF EXISTS payment ;

CREATE TABLE payment (
  id BIGINT (20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  SERIAL VARCHAR (300) DEFAULT NULL,
  PRIMARY KEY (id)
) ENGINE = INNODB AUTO_INCREMENT = 33 DEFAULT CHARSET = utf8 ;

INSERT INTO payment (id, SERIAL) VALUES(31, '尚硅谷001'),(32, 'atguigu002') ;

4. 编写 entities

Payment

package com.atguigu.springcloud.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
    private Long id;
    private String serial;
}

JSON 封装类 CommonResult

package com.atguigu.springcloud.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult  implements Serializable{

    private Integer code;
    private String message;
    private T data;

    public CommonResult(Integer code,String message){
        this(code,message,null);//如果这行报错,请安装lombok插件
    }
}

5. 编写 Dao

PaymentDao 接口

package com.atguigu.springcloud.dao;

import com.atguigu.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;

@Component
@Mapper // mybatis提供的,等价:@MapperScan("com.atguigu.springcloud.dao")
public interface PaymentDao {
    public int create(Payment payment);
    public Payment getPaymentById(@Param("id") Long id);
}

Mybatis 映射文件

<?xml version="1.0" encoding="UTF-8"?>



    
        
        
    

    
            insert into payment(serial) values(#{serial});
    

    

Service 接口及实现类

接口

package com.atguigu.springcloud.service;

import com.atguigu.springcloud.entities.Payment;

public interface PaymentService {
    public int create(Payment payment);
    public Payment getPaymentById(Long id);
}

实现类

package com.atguigu.springcloud.service.impl;

import com.atguigu.springcloud.dao.PaymentDao;
import com.atguigu.springcloud.entities.Payment;
import com.atguigu.springcloud.service.PaymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PaymentServiceImpl implements PaymentService {
    @Autowired
    private PaymentDao paymentDao;

    @Override
    public int create(Payment payment) {
        return paymentDao.create(payment);
    }

    @Override
    public Payment getPaymentById(Long id) {
        return paymentDao.getPaymentById(id);
    }
}

Controller

package com.atguigu.springcloud.controller;


import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import com.atguigu.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

@RestController
@Slf4j
@RequestMapping("/payment")
public class PaymentController {
    @Resource
    private PaymentService paymentService;

    @PostMapping("/create")
    public CommonResult create(@RequestBody Payment payment) {
        int result = paymentService.create(payment);
        log.info("*****插入结果:" + result);
        if (result > 0) {
            return new CommonResult(200, "插入数据成功", result);
        } else {
            return new CommonResult(444, "插入数据失败", null);
        }
    }

    @GetMapping("/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id) {
        Payment payment = paymentService.getPaymentById(id);
        log.info("*****查询结果:" + payment);
        if (payment != null) {
            return new CommonResult<>(200, "查询成功", payment);
        } else {
            return new CommonResult<>(444, "查询失败,没有记录" + id);
        }
    }
}

三、创建子模块,服务消费者,cloud-consumer-order80

1. 编写 POM 文件


	
		org.springframework.boot
		spring-boot-starter-web
	
	
		org.springframework.boot
		spring-boot-starter-actuator
	
	
		org.springframework.boot
		spring-boot-devtools
		runtime
		true
	
	
		org.projectlombok
		lombok
		true
	
	
		org.springframework.boot
		spring-boot-starter-test
		test
	

2. 编写 yml,启动类

yml

server:
  port: 80
spring:
  application:
    name: cloud-consumer-order80

启动类

package com.atguigu.springcloud;

import com.atguigu.myrule.MySelfRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;

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

3. 编写实体类 entities

将cloud-provider-payment8001工程下的entities包下的两个实体类复制过来

4. 编写 RestTemplate 配置类

package com.atguigu.springcloud.config;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootConfiguration
public class ApplicationContextConfig {

    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

5. 创建 Controller

package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@Slf4j
@RequestMapping("/consumer")
public class OrderController {
    public static final String PAYMENT_URL = "http://localhost:8001/payment";

    @Resource
    private RestTemplate restTemplate;

    @PostMapping("/payment/create")
    public CommonResult create(@RequestBody Payment payment){
        // 请求 url,请求体数据,响应数据类型
        return restTemplate.postForObject(PAYMENT_URL + "/create", payment, CommonResult.class);
    }

    @GetMapping("/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id){
        return restTemplate.getForObject(PAYMENT_URL + "/get/" + id, CommonResult.class);
    }
}

6. 进行远程过程调用测试


四、项目重构

1. 新建子模块,cloud-api-commons

将 payment8001 中 entities 复制到 cloud-api-commons

2. 添加 POM 依赖


	
		org.springframework.boot
		spring-boot-devtools
		runtime
		true
	

	
		org.projectlombok
		lombok
		true
	
	
		cn.hutool
		hutool-all
		5.1.0
	

3. 在 Maven 管理界面,跳过单元测试,执行 mvn:install 命令

4. 为 payment,order 工程添加依赖


	
	com.atguigu
	cloud-api-commons
	${project.version}


五、创建子模块,服务注册中心,cloud-eureka-server7001

1. 添加 POM 依赖


	
	
		org.springframework.cloud
		spring-cloud-starter-netflix-eureka-server
	
	
		com.atguigu
		cloud-api-commons
		${project.version}
	
	
		org.springframework.boot
		spring-boot-starter-web
	
	
		org.springframework.boot
		spring-boot-starter-actuator
	
	
		org.springframework.boot
		spring-boot-devtools
		runtime
		true
	
	
		org.projectlombok
		lombok
	
	
		org.springframework.boot
		spring-boot-starter-test
		test
	
	
		junit
		junit
	

2. 编写 yml,启动类

yml

server:
  port: 7001

eureka:
  instance:
    hostname: localhost

  client:
    register-with-eureka: false   # 是否想服务注册中心注册,本身就是无需注册
    fetchRegistry: false          # 是否获取已经注册的服务列表
    service-url:
      defaultZone: http://localhost:7001/eureka

启动类

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer	// 注解开启 EurekaServer 功能
public class EruekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EruekaApplication.class, args);
    }
}

3. 测试

访问:http://localhost:7001/

六、改写服务提供者和消费者

将服务提供者和消费者都注册进 Eureka 中

1. 改写服务提供者

添加 POM 依赖



	org.springframework.cloud
	spring-cloud-starter-netflix-eureka-client

添加 yml 配置

eureka:
  client:
    register-with-eureka: true   # 向服务注册中心注册服务
    fetchRegistry: false         # 获取注册列表信息
    service-url:
      defaultZone: http://localhost:7001/eureka

在 payment 启动类上,添加注解 “@EnableEurekaClient”

2. 消费者改造

消费者进行同样的改造,将 yml 配置中的 fetchRegistry 改为 true,让消费者可以获取注册列表

记得在启动类上添加注解

添加 Ribbon 负载均衡服务调用

在消费者端添加 Ribbon服务

1. 新建 Ribbon 负载均衡策略配置类

注意:这个配置类不能放在启动类所在的包和子包下
原因: 这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化订制的目的了。

package com.atguigu.myrule;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MySelfRule {

    @Bean
    public IRule myRule(){
        return new RandomRule();//定义为随机
    }
}

2. 在主启动类上添加 @RibbonClient 注解

@RibbonClient(name = "CLOUD-PAYMENT-SERVER", configuration = MySelfRule.class)

3. 在消费者 RestTemplate 配置类中加上 @LoadBalanced 注解

package com.atguigu.springcloud.config;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootConfiguration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
  1. 在 Controller 中将请求的 URL,改为服务名
// 更改之前
public static final String PAYMENT_URL = "http://localhost:8001/payment";
// 更改之后
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE/payment";