基于SpringCloud+Eureka的微服务项目搭建

基于SpringCloud+Eureka的微服务项目搭建

注:本文重点在于项目搭建和功能实现,异常处理参见另一篇博客:https://blog.csdn.net/qq_61603262/article/details/127299597
鉴于本文中大量技术和框架都已过时或停止更新,一部分在现在(2022年底)功能不足,另一部分因为版本老旧存在诸多兼容问题,故该项目不再进行内容扩充,有关新版的nacos+sentinel模式笔者未来会另开新坑
原创不易,如果本文有用的话,请不要吝啬您手中的点赞和收藏。

0.技术栈一览

SpringCloud(基于SpringBoot)2.7.3

mybatis

Eureka

Ribbon/Feign

Druid

Hystrix

小插件:Lombook、SpringDoc、devtools、configuration-processor

1.环境搭建

1.0准备工作

仓库建立

gitignore采用java标准配置,开源许可和分支模型等根据需要选择。这里笔者选择了master/develop模型。

数据库搭建

下文用到的数据库结构如下:

myemployees.departments

Field Type Null Key Default Extra


department_id int NO PRI (NULL) auto_increment
department_name varchar(3) YES (NULL)
manager_id int YES (NULL)
location_id int YES MUL (NULL)

myemployees.jobs

Field Type Null Key Default Extra


job_id varchar(10) NO PRI (NULL)
job_title varchar(35) YES (NULL)
min_salary int YES (NULL)
max_salary int YES (NULL)

myemployees.locations

Field Type Null Key Default Extra


location_id int NO PRI (NULL) auto_increment
street_address varchar(40) YES (NULL)
postal_code varchar(12) YES (NULL)
city varchar(30) YES (NULL)
state_province varchar(25) YES (NULL)
country_id varchar(2) YES (NULL)

users.user

Field Type Null Key Default Extra


username varchar(20) NO PRI (NULL)
password varchar(20) NO (NULL)
role varchar(6) YES (NULL)
salt varchar(16) YES (NULL)

1.1项目依赖

1.前后端基本环境(SpringBoot相关、SpringWeb等,thymeleaf等)

2.JDBC相关,这里笔者选择MySQL,故引入相关驱动,并选择Druid连接池和Mybatis框架

3.SpringCloud相关,如Eureka的三个依赖、Feign/Ribbon等负载均衡工具、Shiro安全框架

4.其他提升开发体验的小玩意儿,如Lombook、swagger、devtools、configuration-processor等

为了方便版本管理,我们选择把依赖放在父模块的pom中,使用dependencyManagement管理。同时由于父项目只作为项目环境的底座,所以只创建一个maven项目,无需继承springboot

<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>com.zjy</groupId>
    <artifactId>system</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>system</name>
    <url>http://maven.apache.org</url>
 <!--      依赖版本管理,鉴于自动导入的版本依赖出问题更麻烦,索性自己手动控制依赖版本-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>2.7.3</spring.version>
        <mybatis.version>2.2.2</mybatis.version>
        <mysql.version>8.0.30</mysql.version>
        <junit.version>3.8.1</junit.version>
        <eureka.server.version>3.1.4</eureka.server.version>
        <eureka.clinet.version>3.1.4</eureka.clinet.version>
        <eureka.version>1.4.7.RELEASE</eureka.version>
        <feign.version>3.1.4</feign.version>
        <shiro.version>1.9.1</shiro.version>
        <swagger.version>2.0.2.RELEASE</swagger.version>
        <lombok.version>1.18.22</lombok.version>
        <spring-cloud.version>2021.0.4</spring-cloud.version>
    </properties>

<modules>
    <!--      这里之后会写一大堆微服务模块-->
</modules>
    <dependencyManagement>
        <dependencies>
            <!--      spring相关-->
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
                <version>${spring.version}</version>
            </dependency>

            <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->
            <!--      数据库相关-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>


            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
                <version>${spring.version}</version>
            </dependency>


            <!--      Eureka相关-->
            <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-server -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
                <version>${eureka.server.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
                <version>${eureka.clinet.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
                <version>${eureka.version}</version>
            </dependency>
            <!--其他-->
            <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
                <version>${feign.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring-boot-web-starter -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring-boot-web-starter</artifactId>
                <version>${shiro.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.spring4all/swagger-spring-boot-starter -->
            <dependency>
                <groupId>com.spring4all</groupId>
                <artifactId>swagger-spring-boot-starter</artifactId>
                <version>${swagger.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-configuration-processor -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <version>${swagger.version}</version>
            </dependency>



        </dependencies>

    </dependencyManagement>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

1.2分布式架构初步搭建

创建子模块,主要分四类:pojo,provider,consumer,Server(注册中心,本文选取Eureka)

其中pojo只容纳java实体类,除从父模块继承的Lombook之外无需太多配置。我们完成初步配置只是为了检验环境配置正常,配置文件后续还将有所增删。

其余三类模块配置区别主要就在于Eureka模块的不同和各自功能所需(如provider的JDBC相关,consumer的前端模板和框架)

1.2.1provider

启动类用@EnableDiscoveryClient修饰以开启服务发现(事实上,在现版本不写该注解或写@EnableEurekaClient也将自动激活)

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>provider_8000</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>provider_8000</name>
    <description>provider_8000</description>
<parent>
    <groupId>com.zjy</groupId>
    <artifactId>system</artifactId>
    <version>1.0-SNAPSHOT</version>
</parent>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <!--      spring相关-->

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
    </dependencies>



    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.7.RELEASE</version>
                <configuration>
                    <mainClass>com.zjy.provider_8000.Provider8000Application</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

server:
  port: 8000
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:7000/eureka
spring:
  application:
    name: provider8000

这里一定要注意defaultZone关键字书写正确(可以追踪到源代码看一下),链接要写完整(http://),记得加“/eureka”;

1.2.2consumer

启动类用@EnableEurekaClient修饰以激活Eureka客户端

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>final</artifactId>
        <groupId>com.zjy</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.zjy</groupId>
    <artifactId>consumer_9000</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>consumer_9000</name>
    <description>consumer_9000</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <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>

</project>
server:
  port: 9000
spring:
  application:
    name: consumer9000
eureka:
  client:
    enabled: true
    fetch-registry: false
    register-with-eureka: true
    service-url:
     defaultZone: localhost:7000
1.2.3EurekaServer

启动类用@EnableEurekaServer修饰以激活注册中心

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>consumer_9000</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>consumer_9000</name>
    <description>consumer_9000</description>
<parent>
    <groupId>com.zjy</groupId>
    <artifactId>system</artifactId>
    <version>1.0-SNAPSHOT</version>
</parent>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <!-- spring相关-->

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>



    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.7.RELEASE</version>
                <configuration>
                    <mainClass>com.zjy.provider_8000.Provider8000Application</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

server:
  port: 9000
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:7000/eureka
spring:
  application:
    name: EurekaServer9000

1.3环境验证

直接启动注册中心,能够访问到后台页面,证明基本配置正常。

之后启动provider和consumer,能够在注册中心看到两者,证明配置正确。

2.provider的三层架构搭建

三层架构接口写法和mapper.xml写法与ssm无异,只是将xml中的配置迁移到了yaml。故在此不对接口逻辑做太多赘述。

2.1Mapper

package com.zjy.mapper;


import com.zjy.pojo.Department;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
@Repository
public interface DepartmentMapper {
    List<Department> getDepartmentList();
    Department getDepartmentById(Integer departmentId);

    List<Department> getDepartmentByName(String departmentName);
    void insert(Department department);
    void deleteDepartmentById(Integer departmentId);
    void update(Department department);
}
<?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.zjy.mapper.DepartmentMapper">

    <select id="getDepartmentList" resultType="Department" useCache="true">
        select * from `myemployees`.`departments`;
    </select>
    <select id="getDepartmentById" resultType="Department" >
        select * from myemployees.departments where `department_id`=#{departmentId};
    </select>
    <select id="getDepartmentByName" resultType="Department" >
        select * from myemployees.departments where `department_name`=#{departmentName};
    </select>
    <insert id="insert">
        insert into myemployees.departments
        values (#{departmentId},#{departmentName},#{managerId},#{locationId});
    </insert>
    <delete id="deleteDepartmentById">
        delete *from myemployees.departments where `department_id`=#{departmentId};
    </delete>
    <update id="update">
        update `departments`
        set `department_name`=#{departmentName},`manager_id`=#{managerId},`location_id`=#{locationId})
        WHERE `department_id`=#{departmentId};
    </update>


</mapper>

2.2service

package com.zjy.service;


import com.zjy.mapper.DepartmentMapper;
import com.zjy.pojo.Department;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Service
public class DepartmentService {
    @Resource
    private DepartmentMapper departmentMapper;

    public List<Department> getDepartmentList(){
        return departmentMapper.getDepartmentList();
    }
    public Department getDepartmentById(Integer departmentId){
        return departmentMapper.getDepartmentById(departmentId);
    }
    public List<Department> getDepartmentByName(String departmentName){
        return departmentMapper.getDepartmentByName(departmentName);
    }
    public void insert(Department department){
         departmentMapper.insert(department);
    }
    public void deleteDepartmentById(Integer departmentId){
        departmentMapper.deleteDepartmentById(departmentId);
    }
    public void update(Department department){
        departmentMapper.update(department);
    }
}

2.3controller

package com.zjy.controller;


import com.zjy.pojo.Department;
import com.zjy.pojo.Employee;
import com.zjy.service.DepartmentService;
import com.zjy.service.EmployeeService;
import com.zjy.service.JobService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;



@RestController
@Tag(name="部门")
@RequestMapping("/dept")
public class DepartmentController {
    @Resource
    DepartmentService departmentService;
    @Resource
    EmployeeService employeeService;
    @Resource
    JobService jobService;

    @Operation(summary = "获取部门列表")
    @GetMapping("/list")
    public List<Department> getAll(){
        return departmentService.getDepartmentList();
    }

    @Operation(summary = "通过id查找部门")
    @GetMapping("/query/id/{departmentId}")
    public Department queryById(@PathVariable Integer departmentId){
        return departmentService.getDepartmentById(departmentId);
    }
    @Operation(summary = "通过名称查找部门")
    @GetMapping("/query/id/{departmentName}")
    public List<Department> queryByName(@PathVariable String departmentName){
        return departmentService.getDepartmentByName(departmentName);
    }
}

2.4环境验证

进入swagger后台http://localhost:8000/swagger-ui/index.html#/验证各个方法。

3.consumer及均衡负载

引入依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

这里我们选择Feign作为均衡负载。Feign底层仍然用的是Ribbon实现,而在代码层面,Feign实际上就是在consumer的controller层下加了一层FeignClient接口。

思路:

  1. 新建接口,用@FeignClient(name=“[provider服务名]”)
  2. 接口内写所需方法,Mapping指向的是provider的url路径
  3. Consumer的Controller内自动装配一个上述FeignClient接口的实现类,用与三层架构相仿的方式配置调用。

代码如下:


package com.zjy.consumer_9001.FeignClient;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;
import java.util.Map;

@FeignClient("provider-8000")//服务名,取决于provider服务名,Feign通过这个名字来找到provider
@Component
public interface DeptService {
    //这里仅先引入一个查询方法来验证环境配置无误
    @GetMapping("/dept/list")
    List<Map> getAll();
}

加入Feign后的consumerController

package com.zjy.consumer_9001.controller;

import com.zjy.consumer_9001.FeignClient.DeptService;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/dept")
public class DeptController {
    @Resource
    DeptService deptService;

    @RequestMapping("/list")
    public List<Map> getAll(){return deptService.getAll();}


}

配置完毕后访问验证。

4.服务安全机制(服务降级与熔断,通过Hystrix实现)

引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

4.1功能一览

Hystrix作用方法上的注释为@HystrixCommand,其源代码如下:

/**
 * Copyright 2012 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.netflix.hystrix.contrib.javanica.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
 * This annotation used to specify some methods which should be processes as hystrix commands.
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface HystrixCommand {

    /**
     * The command group key is used for grouping together commands such as for reporting,
     * alerting, dashboards or team/library ownership.
     * <p/>
     * default => the runtime class name of annotated method
     *
     * @return group key
     */
    String groupKey() default "";

    /**
     * Hystrix command key.
     * <p/>
     * default => the name of annotated method. for example:
     * <code>
     *     ...
     *     @HystrixCommand
     *     public User getUserById(...)
     *     ...
     *     the command name will be: 'getUserById'
     * </code>
     *
     * @return command key
     */
    String commandKey() default "";

    /**
     * The thread-pool key is used to represent a
     * HystrixThreadPool for monitoring, metrics publishing, caching and other such uses.
     *
     * @return thread pool key
     */
    String threadPoolKey() default "";

    /**
     * Specifies a method to process fallback logic.
     * A fallback method should be defined in the same class where is HystrixCommand.
     * Also a fallback method should have same signature to a method which was invoked as hystrix command.
     * for example:
     * <code>
     *      @HystrixCommand(fallbackMethod = "getByIdFallback")
     *      public String getById(String id) {...}
     *
     *      private String getByIdFallback(String id) {...}
     * </code>
     * Also a fallback method can be annotated with {@link HystrixCommand}
     * <p/>
     * default => see {@link com.netflix.hystrix.contrib.javanica.command.GenericCommand#getFallback()}
     *
     * @return method name
     */
    String fallbackMethod() default "";

    /**
     * Specifies command properties.
     *
     * @return command properties
     */
    HystrixProperty[] commandProperties() default {};

    /**
     * Specifies thread pool properties.
     *
     * @return thread pool properties
     */
    HystrixProperty[] threadPoolProperties() default {};

    /**
     * Defines exceptions which should be ignored.
     * Optionally these can be wrapped in HystrixRuntimeException if raiseHystrixExceptions contains RUNTIME_EXCEPTION.
     *
     * @return exceptions to ignore
     */
    Class<? extends Throwable>[] ignoreExceptions() default {};

    /**
     * Specifies the mode that should be used to execute hystrix observable command.
     * For more information see {@link ObservableExecutionMode}.
     *
     * @return observable execution mode
     */
    ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;

    /**
     * When includes RUNTIME_EXCEPTION, any exceptions that are not ignored are wrapped in HystrixRuntimeException.
     *
     * @return exceptions to wrap
     */
    HystrixException[] raiseHystrixExceptions() default {};

    /**
     * Specifies default fallback method for the command. If both {@link #fallbackMethod} and {@link #defaultFallback}
     * methods are specified then specific one is used.
     * note: default fallback method cannot have parameters, return type should be compatible with command return type.
     *
     * @return the name of default fallback method
     */
    String defaultFallback() default "";
}


4.2具体操作

根据本次需要,我们选择使用fallbackMethod进行服务降级,所以对原有方法queryById()作出如下改动:

  • 加入注释@HystrixCommand(fallbackMethod = “queryFallback”)
  • 加入方法queryFallback()
  • 主启动类加入注释**@EnableCircuitBreaker**

2022.10.12.鉴于

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值