1.若依中的provider

发布时间 2023-08-21 10:19:08作者: 求知律己

1.前言

  为对前面微服务知识点的巩固,决定实践若依的微服务项目。这篇博客主要是为熟悉该项目的服务提供者provider,其在项目中的应用。在之前的微服务基础学习中,我的认知是将@FeignClient注解添加在consumer包中的接口上面;但是在对若依微服务项目的学习中,我发现将provider的被调用接口方法放在provider包中能更好地复用,减少重复代码。

2.实战

2.1 搭建cloud-ruoyi项目

   删除该模块的下面除.idea和pom.xml文件以外的所有文件

2.2 添加依赖

<?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>com.ku</groupId>
    <artifactId>cloud-RuoYi</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>ruoyi-system</module>
        <module>ruoyi-common</module>
        <module>ruoyi-auth</module>
    </modules>

    <properties>
        <ruoyi.version>3.6.3</ruoyi.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>

        <spring-boot.version>2.7.13</spring-boot.version>
        <spring-cloud.version>2021.0.8</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
        <spring-boot-admin.version>2.7.10</spring-boot-admin.version>
        <swagger.fox.version>3.0.0</swagger.fox.version>
        <swagger.core.version>1.6.2</swagger.core.version>
        <tobato.version>1.27.2</tobato.version>
        <kaptcha.version>2.3.3</kaptcha.version>
        <pagehelper.boot.version>1.4.7</pagehelper.boot.version>
        <druid.version>1.2.16</druid.version>
        <dynamic-ds.version>3.5.2</dynamic-ds.version>
        <commons.io.version>2.13.0</commons.io.version>
        <velocity.version>2.3</velocity.version>
        <fastjson.version>2.0.39</fastjson.version>
        <jjwt.version>0.9.1</jjwt.version>
        <minio.version>8.2.2</minio.version>
        <poi.version>4.1.2</poi.version>
        <transmittable-thread-local.version>2.14.3</transmittable-thread-local.version>
    </properties>

    <!-- 依赖声明 -->
    <dependencyManagement>
        <dependencies>

            <!-- SpringCloud 微服务 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- SpringCloud Alibaba 微服务 -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- SpringBoot 依赖配置 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- FastDFS 分布式文件系统 -->
            <dependency>
                <groupId>com.github.tobato</groupId>
                <artifactId>fastdfs-client</artifactId>
                <version>${tobato.version}</version>
            </dependency>

            <!-- Swagger 依赖配置 -->
            <dependency>
                <groupId>io.swagger</groupId>
                <artifactId>swagger-models</artifactId>
                <version>${swagger.core.version}</version>
            </dependency>
            <dependency>
                <groupId>io.swagger</groupId>
                <artifactId>swagger-annotations</artifactId>
                <version>${swagger.core.version}</version>
            </dependency>

            <!-- 验证码 -->
            <dependency>
                <groupId>pro.fessional</groupId>
                <artifactId>kaptcha</artifactId>
                <version>${kaptcha.version}</version>
            </dependency>

            <!-- pagehelper 分页插件 -->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pagehelper.boot.version}</version>
            </dependency>

            <!-- io常用工具类 -->
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>${commons.io.version}</version>
            </dependency>

            <!-- excel工具 -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>${poi.version}</version>
            </dependency>

            <!-- 代码生成使用模板 -->
            <dependency>
                <groupId>org.apache.velocity</groupId>
                <artifactId>velocity-engine-core</artifactId>
                <version>${velocity.version}</version>
            </dependency>

            <!-- JSON 解析器和生成器 -->
            <dependency>
                <groupId>com.alibaba.fastjson2</groupId>
                <artifactId>fastjson2</artifactId>
                <version>${fastjson.version}</version>
            </dependency>

            <!-- JWT -->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>${jjwt.version}</version>
            </dependency>

            <!-- 线程传递值 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>transmittable-thread-local</artifactId>
                <version>${transmittable-thread-local.version}</version>
            </dependency>

            <!-- 核心模块 -->
            <dependency>
                <groupId>com.ku</groupId>
                <artifactId>ruoyi-common-core</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>

            <!--&lt;!&ndash; 接口模块 &ndash;&gt;-->
            <!--<dependency>-->
                <!--<groupId>com.ku</groupId>-->
                <!--<artifactId>ruoyi-common-swagger</artifactId>-->
                <!--<version>1.0-SNAPSHOT</version>-->
            <!--</dependency>-->

            <!-- 安全模块 -->
            <dependency>
                <groupId>com.ku</groupId>
                <artifactId>ruoyi-common-security</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>

            <!--&lt;!&ndash; 权限范围 &ndash;&gt;-->
            <!--<dependency>-->
                <!--<groupId>com.ku</groupId>-->
                <!--<artifactId>ruoyi-common-datascope</artifactId>-->
                <!--<version>1.0-SNAPSHOT</version>-->
            <!--</dependency>-->

            <!--&lt;!&ndash; 多数据源 &ndash;&gt;-->
            <!--<dependency>-->
                <!--<groupId>com.ku</groupId>-->
                <!--<artifactId>ruoyi-common-datasource</artifactId>-->
                <!--<version>1.0-SNAPSHOT</version>-->
            <!--</dependency>-->

            <!--&lt;!&ndash; 分布式事务 &ndash;&gt;-->
            <!--<dependency>-->
                <!--<groupId>com.ku</groupId>-->
                <!--<artifactId>ruoyi-common-seata</artifactId>-->
                <!--<version>1.0-SNAPSHOT</version>-->
            <!--</dependency>-->

            <!--&lt;!&ndash; 日志记录 &ndash;&gt;-->
            <!--<dependency>-->
                <!--<groupId>com.ku</groupId>-->
                <!--<artifactId>ruoyi-common-log</artifactId>-->
                <!--<version>1.0-SNAPSHOT</version>-->
            <!--</dependency>-->

            <!-- 缓存服务 -->
            <dependency>
                <groupId>com.ku</groupId>
                <artifactId>ruoyi-common-redis</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>

            <!-- 系统接口 -->
            <dependency>
                <groupId>com.ku</groupId>
                <artifactId>ruoyi-system</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>

        </dependencies>
    </dependencyManagement>


    <dependencies>
        <!-- bootstrap 启动器 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
        <!--<pluginManagement>-->
            <!--<plugins>-->
                <!--<plugin>-->
                    <!--<groupId>org.springframework.boot</groupId>-->
                    <!--<artifactId>spring-boot-maven-plugin</artifactId>-->
                    <!--<version>${spring-boot.version}</version>-->
                    <!--<executions>-->
                        <!--<execution>-->
                            <!--<goals>-->
                                <!--<goal>repackage</goal>-->
                            <!--</goals>-->
                        <!--</execution>-->
                    <!--</executions>-->
                <!--</plugin>-->
            <!--</plugins>-->
        <!--</pluginManagement>-->
    </build>

    <repositories>
        <repository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>


</project>
cloud-ruoyi项目依赖

2.3 搭建ruoyi-system模块

2.3.1 导入依赖

<?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">
    <parent>
        <artifactId>cloud-RuoYi</artifactId>
        <groupId>com.ku</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>ruoyi-system</artifactId>


    <dependencies>
        <!-- RuoYi Common Core-->
        <dependency>
            <groupId>com.ku</groupId>
            <artifactId>ruoyi-common-core</artifactId>
        </dependency>
    </dependencies>


</project>
ruoyi-system依赖

  在ruoyi-system模块中需要导入ruoyi-common-core模块,该模块中包含若依项目中核心的代码部分,包含注解、常量、消息响应、异常、分页、XSS、工具类等功能包的使用。

2.3.2 编写实体类

  编写SysDept、SysDictType、SysDictData、SysFile、SysLogininfor、SysOperLog、SysRole、SysRole等实体类的属性及其对应的set和get方法以及toString()方法。

2.3.3 编写provider的三个业务接口的服务降级类

package com.ku.system.api.factory;

import com.ku.common.core.domain.R;
import com.ku.system.api.RemoteUserService;
import com.ku.system.api.domain.SysUser;
import com.ku.system.api.model.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;

public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserService> {

    private static final Logger log = LoggerFactory.getLogger(RemoteUserFallbackFactory.class);
    @Override
    public RemoteUserService create(Throwable cause) {
        log.error("用户服务调用失败:{}", cause.getMessage());

        return new RemoteUserService() {
            @Override
            public R<LoginUser> getUserInfo(String username, String source) {
                return R.fail("获取用户失败:"+cause.getMessage());
            }

            @Override
            public R<Boolean> registerUserInfo(SysUser sysUser, String source) {
                return R.fail("注册用户失败:"+cause.getMessage());
            }
        };
    }
}
RemoteFileFallbackFactory
package com.ku.system.api.factory;

import com.ku.common.core.domain.R;
import com.ku.system.api.RemoteLogService;
import com.ku.system.api.domain.SysLogininfor;
import com.ku.system.api.domain.SysOperLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;

public class RemoteLogFallbackFactory implements FallbackFactory<RemoteLogService> {
    private static final Logger log = LoggerFactory.getLogger(RemoteLogFallbackFactory.class);
    @Override
    public RemoteLogService create(Throwable cause) {
        log.error("日志服务调用失败:{}", cause.getMessage());
        return new RemoteLogService() {
            @Override
            public R<Boolean> saveLog(SysOperLog sysOperLog, String source) throws Exception {
                return R.fail("保存操作日志失败:"+cause.getMessage());
            }

            @Override
            public R<Boolean> saveLogininfor(SysLogininfor sysLogininfor, String source) {
                return R.fail("保存登录用户信息失败:"+cause.getMessage());
            }
        };
    }
}
RemoteLogFallbackFactory
package com.ku.system.api.factory;

import com.ku.common.core.domain.R;
import com.ku.system.api.RemoteUserService;
import com.ku.system.api.domain.SysUser;
import com.ku.system.api.model.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;

public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserService> {

    private static final Logger log = LoggerFactory.getLogger(RemoteUserFallbackFactory.class);
    @Override
    public RemoteUserService create(Throwable cause) {
        log.error("用户服务调用失败:{}", cause.getMessage());

        return new RemoteUserService() {
            @Override
            public R<LoginUser> getUserInfo(String username, String source) {
                return R.fail("获取用户失败:"+cause.getMessage());
            }

            @Override
            public R<Boolean> registerUserInfo(SysUser sysUser, String source) {
                return R.fail("注册用户失败:"+cause.getMessage());
            }
        };
    }
}
RemoteUserFallbackFactory

2.3.4 编写provider的三个被调用服务业务接口

package com.ku.system.api;

import com.ku.common.core.constant.ServiceNameConstants;
import com.ku.common.core.domain.R;
import com.ku.system.api.domain.SysFile;
import com.ku.system.api.factory.RemoteFileFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;

//作为服务提供者,为其他服务提供服务
//contextId指定Feign客户端的上下文ID,用于区分不同的Feign客户端。

@FeignClient(contextId = "remoteFileService", value = ServiceNameConstants.FILE_SERVICE, fallbackFactory = RemoteFileFallbackFactory.class)
public interface RemoteFileService {
    /**
     * 上传文件
     */
    //SpringMVC用于文件上传的注解,MULTIPART_FORM_DATA_VALUE多部分请求,可用于文件上传
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    //@RequestPart用于处理文件请求
    public R<SysFile> upload(@RequestPart(value = "file")MultipartFile file);
}
RemoteFileService
package com.ku.system.api;

import com.ku.common.core.constant.SecurityConstants;
import com.ku.common.core.constant.ServiceNameConstants;
import com.ku.common.core.domain.R;
import com.ku.system.api.domain.SysLogininfor;
import com.ku.system.api.domain.SysOperLog;
import com.ku.system.api.factory.RemoteLogFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;

@FeignClient(contextId = "remoteLogService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteLogFallbackFactory.class)
public interface RemoteLogService {
    /**
     * 保存系统日志
     */
    @PostMapping("/operlog")
    public R <Boolean> saveLog(@RequestBody SysOperLog sysOperLog, @RequestHeader(SecurityConstants.FROM_SOURCE) String source) throws Exception;

    @PostMapping("/logininfor")
    public R<Boolean> saveLogininfor(@RequestBody SysLogininfor sysLogininfor, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}
RemoteLogService
package com.ku.system.api;

import com.ku.common.core.constant.SecurityConstants;
import com.ku.common.core.constant.ServiceNameConstants;
import com.ku.common.core.domain.R;
import com.ku.system.api.domain.SysUser;
import com.ku.system.api.factory.RemoteUserFallbackFactory;
import com.ku.system.api.model.LoginUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;

@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteUserService {

    @GetMapping("/user/info/{username}")
    //@RequestHeader(SecurityConstants.FROM_SOURCE)用于获取HTTP请求中的指定名称的值
    public R<LoginUser> getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);

    //注册用户信息
    @GetMapping("/user/register")
    public R<Boolean>registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);

}
RemoteUserService

若依项目链接

RuoYi-Cloud: ? 基于Spring Boot、Spring Cloud & Alibaba的分布式微服务架构权限管理系统,同时提供了 Vue3 的版本 (gitee.com)