• 简单创建一个SpringCloud2021.0.3项目(一)



    1. 项目说明

    由于工作原因,有时间把之前学到的技术进行整理。


    注意:由于截图过多,不方便浏览,会分开多个文章。
    当前这篇教程是:

    1. 新建Eureka注册中心
    2. 新建Config配置中心,producerService服务读取参数
    3. 2个业务服务(producerService和webService),webService通过Feign调用producerService的服务
    4. webService用到多数据源,不同的数据源管理不同的数据

    简单创建一个SpringCloud2021.0.3项目(一)
    简单创建一个SpringCloud2021.0.3项目(二)
    简单创建一个SpringCloud2021.0.3项目(三)
    简单创建一个SpringCloud2021.0.3项目(四)

    1. 版本

    1. SpringCloud版本为2021.0.3
    2. SpringBoot版本为2.7.2

    2. 用到组件

    1. 注册中心:暂时用Eureka,后面再改成Nacos
    2. 网关:Gateway
    3. 权限:Security,Gateway集成
    4. 负载均衡:LoadBalancer,SpringCloud2020版之后就集成LoadBalancer
    5. 限流、熔断降级:Sentinel
    6. 配置中心:暂时用Config,后面改成Nacos
    7. 服务间访问:Feign

    3. 功能

    1. 项目最基本功能,权限控制,在分布式系统中基于Token的身份验证。
    2. 前端登陆,做了2种方式。用户、密码、验证码;邮箱、验证码、图片滑块;并且前端加密传给后端解密;登陆异常次数限制;
    3. 限流、负载均衡,应对高并发情况,降低系统负载;
    4. 服务熔断降级:避免系统雪崩,提高系统可用性;
    5. 两种方式的多数据源,一种是通过AOP方式动态切换数据源,另一种是不同数据源管理的数据各不相同;
    6. 日志系统Logback,是SpringBoot默认集成

    2. 新建父模块和注册中心

    1. 新建父模块

    父模块名称:SpringCloud202208

    1. 创建操作
      image
      image

    2. 删除src文件夹
      image

    3. 配置项目maven
      image
      image

    有详细注释的setting.xml文件

    点击查看代码
    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--
        详解来源:https://blog.csdn.net/qq_47759220/article/details/119079050
    -->
    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    
        <!--
            该值表示构建系统本地仓库的路径。
            默认值:${user.home}/.m2/repository
        -->
        <localRepository>D:\IT_Software\maven\maven-repository-lw</localRepository>
    
        <!--
            表示maven是否需要和用户交互以获得输入。
            如果maven需要和用户交互以获得输入,则设置成true,反之则应为false。
            默认为true。
        -->
        <interactiveMode>true</interactiveMode>
    
        <!--
            maven是否需要使用plugin-registry.xml文件来管理插件版本。
            如果需要让maven使用文件~/.m2/plugin-registry.xml来管理插件版本,则设为true。
            默认为false。
        -->
        <usePluginRegistry>false</usePluginRegistry>
    
        <!--
            这个属性表示在Maven进行项目编译和部署等操作时是否允许Maven进行联网来下载所需要的信息。
            如果构建系统需要在离线模式下运行,则为true,默认为false。
            当由于网络设置原因或者安全因素,构建服务器不能连接远程仓库的时候,该配置就十分有用。
        -->
        <offline>false</offline>
    
        <!--
            在pluginGroups元素下面可以定义一系列的pluginGroup元素。
            表示当通过plugin的前缀来解析plugin的时候到哪里寻找。pluginGroup元素指定的是plugin的groupId。
            默认情况下,Maven会自动把org.apache.maven.plugins 和 org.codehaus.mojo 添加到pluginGroups下。
        -->
        <pluginGroups>
            <!--plugin的组织Id(groupId) -->
            <pluginGroup>org.codehaus.mojo</pluginGroup>
        </pluginGroups>
    
        <!--
            一般,仓库的下载和部署是在pom.xml文件中的repositories和distributionManagement元素中定义的。
            然而,一般类似用户名、密码(有些仓库访问是需要安全认证的)等信息不应该在pom.xml文件中配置,这些信息可以配置在settings.xml中。
        -->
        <servers>
            <!--服务器元素包含配置服务器时需要的信息 -->
            <server>
                <!--这是server的id(注意不是用户登陆的id),该id与distributionManagement中repository元素的id相匹配。 -->
                <id>server001</id>
                <!--鉴权用户名。鉴权用户名和鉴权密码表示服务器认证所需要的登录名和密码。 -->
                <username>my_login</username>
                <!--鉴权密码 。鉴权用户名和鉴权密码表示服务器认证所需要的登录名和密码。密码加密功能已被添加到2.1.0 +。详情请访问密码加密页面 -->
                <password>my_password</password>
                <!--鉴权时使用的私钥位置。和前两个元素类似,私钥位置和私钥密码指定了一个私钥的路径(默认是${user.home}/.ssh/id_dsa)以及如果需要的话,一个密语。将来passphrase和password元素可能会被提取到外部,但目前它们必须在settings.xml文件以纯文本的形式声明。 -->
                <privateKey>${usr.home}/.ssh/id_dsa</privateKey>
                <!--鉴权时使用的私钥密码。 -->
                <passphrase>some_passphrase</passphrase>
                <!--文件被创建时的权限。如果在部署的时候会创建一个仓库文件或者目录,这时候就可以使用权限(permission)。这两个元素合法的值是一个三位数字,其对应了unix文件系统的权限,如664,或者775。 -->
                <filePermissions>664</filePermissions>
                <!--目录被创建时的权限。 -->
                <directoryPermissions>775</directoryPermissions>
            </server>
        </servers>
    
        <!--
            用于定义一系列的远程仓库的镜像。我们可以在pom中定义一个下载工件的时候所使用的远程仓库。
            但是有时候这个远程仓库会比较忙,所以这个时候人们就想着给它创建镜像以缓解远程仓库的压力,也就是说会把对远程仓库的请求转换到对其镜像地址的请求。
            每个远程仓库都会有一个id,这样我们就可以创建自己的mirror来关联到该仓库,那么以后需要从远程仓库下载工件的时候Maven就可以从我们定义好的mirror站点来下载,这可以很好的缓解我们远程仓库的压力。
            在我们定义的mirror中每个远程仓库都只能有一个mirror与它关联,也就是说你不能同时配置多个mirror的mirrorOf指向同一个repositoryId。
        -->
        <mirrors>
            <!-- 给定仓库的下载镜像。 -->
            <mirror>
                <!-- 该镜像的唯一标识符。id用来区分不同的mirror元素。 -->
                <id>nexus-aliyun</id>
                <!-- 镜像名称 -->
                <name>Nexus aliyun</name>
                <!-- 该镜像的URL。构建系统会优先考虑使用该URL,而非使用默认的服务器URL。 -->
                <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
                <!--
                    被镜像的服务器的id。
                    例如,如果我们要设置了一个Maven中央仓库(http://repo.maven.apache.org/maven2/)的镜像,就需要将该元素设置成central。
                    这必须和中央仓库的id central完全一致。
                -->
                <mirrorOf>central</mirrorOf>
            </mirror>
            <mirror>
                <id>nexus-aliyun</id>
                <name>Nexus aliyun</name>
                <url>http://maven.aliyun.com/nexus/content/groups/public</url>
                <mirrorOf>*,!cloudera</mirrorOf>
            </mirror>
            <mirror>
                <id>central</id>
                <name>Maven Repository Switchboard</name>
                <url>http://repo1.maven.org/maven2/</url>
                <mirrorOf>central</mirrorOf>
            </mirror>
            <mirror>
                <id>repo2</id>
                <name>Human Readable Name for this Mirror.</name>
                <url>http://repo2.maven.org/maven2/</url>
                <mirrorOf>central</mirrorOf>
            </mirror>
        </mirrors>
    
        <!--
            用来配置不同的代理。
        -->
    <!--    <proxies>-->
    <!--        &lt;!&ndash;代理元素包含配置代理时需要的信息 &ndash;&gt;-->
    <!--        <proxy>-->
    <!--            &lt;!&ndash;代理的唯一定义符,用来区分不同的代理元素。 &ndash;&gt;-->
    <!--            <id>myproxy</id>-->
    <!--            &lt;!&ndash;该代理是否是激活的那个。true则激活代理。当我们声明了一组代理,而某个时候只需要激活一个代理的时候,该元素就可以派上用处。 &ndash;&gt;-->
    <!--            <active>true</active>-->
    <!--            &lt;!&ndash;代理的协议。 协议://主机名:端口,分隔成离散的元素以方便配置。 &ndash;&gt;-->
    <!--            <protocol>http</protocol>-->
    <!--            &lt;!&ndash;代理的主机名。协议://主机名:端口,分隔成离散的元素以方便配置。 &ndash;&gt;-->
    <!--            <host>proxy.somewhere.com</host>-->
    <!--            &lt;!&ndash;代理的端口。协议://主机名:端口,分隔成离散的元素以方便配置。 &ndash;&gt;-->
    <!--            <port>8080</port>-->
    <!--            &lt;!&ndash;代理的用户名,用户名和密码表示代理服务器认证的登录名和密码。 &ndash;&gt;-->
    <!--            <username>proxyuser</username>-->
    <!--            &lt;!&ndash;代理的密码,用户名和密码表示代理服务器认证的登录名和密码。 &ndash;&gt;-->
    <!--            <password>somepassword</password>-->
    <!--            &lt;!&ndash;不该被代理的主机名列表。该列表的分隔符由代理服务器指定;例子中使用了竖线分隔符,使用逗号分隔也很常见。 &ndash;&gt;-->
    <!--            <nonProxyHosts>*.google.com|ibiblio.org</nonProxyHosts>-->
    <!--        </proxy>-->
    <!--    </proxies>-->
    
        <!--
            根据环境参数来调整构建配置的列表。
            settings.xml中的profile元素是pom.xml中profile元素的裁剪版本。
            它包含了id、activation、repositories、pluginRepositories和 properties元素。
            这里的profile元素只包含这五个子元素是因为这里只关心构建系统这个整体(这正是settings.xml文件的角色定位),而非单独的项目对象模型设置。
            如果一个settings.xml中的profile被激活,它的值会覆盖任何其它定义在pom.xml中带有相同id的profile。
            当所有的约束条件都满足的时候就会激活这个profile。
        -->
        <profiles>
            <profile>
                <!-- profile的唯一标识 -->
                <id>jdk-1.8</id>
                <!-- 自动触发profile的条件逻辑 -->
                <activation>
                    <!--当其值为true的时候表示如果没有其他的profile处于激活状态的时候,该profile将自动被激活。-->
                    <activeByDefault>true</activeByDefault>
                    <!--
                        <jdk>[1.4,1.7)</jdk> 表示1.4、1.5和1.6满足;
                        <jdk>[1.4,1.7]</jdk> 表示1.4、1.5、1.6和1.7满足;
                    -->
                    <jdk>1.8</jdk>
                    <!--表示当操作系统满足条件的时候激活。-->
                    <os>
                        <name>Windows 10</name>
                        <family>Windows</family>
                        <arch>x64</arch>
                        <version>10.0.19044.1706</version>
                    </os>
                    <!--
                        property是键值对的形式,表示当Maven检测到了这样一个键值对的时候就激活该profile。
                        (1)下面的示例表示当存在属性hello的时候激活该profile。
                        <property>
                            <name>hello</name>
                        </property>
                        (2)下面的示例表示当属性hello的值为world的时候激活该profile。
                        <property>
                            <name>hello</name>
                            <value>world</value>
                        </property>
                        这个时候如果要激活该profile的话,可以在调用Maven指令的时候加上参数hello并指定其值为world,如:mvn compile –Dhello=world
                    -->
                    <property>
                        <name>mavenVersion</name>
                        <value>2.0.3</value>
                    </property>
                    <!--
                        表示当文件存在或不存在的时候激活,exists表示存在,missing表示不存在。
                        如下面例子表示当文件hello/world不存在的时候激活该profile。
                        <profile>
                            <activation>
                                <file>
                                    <missing>hello/world</missing>
                                </file>
                            </activation>
                        </profile>
                    -->
                    <file>
                        <exists>${basedir}/file2.properties</exists>
                        <missing>${basedir}/file1.properties</missing>
                    </file>
                </activation>
                <!--
                    用于定义属性键值对的。
                    当该profile是激活状态的时候,properties下面指定的属性都可以在pom.xml中使用。对应profile的扩展属性列表。
                    注:如果该profile被激活,则可以在pom.xml中使用${maven.compiler.compilerVersion}
                -->
                <properties>
                    <maven.compiler.source>1.8</maven.compiler.source>
                    <maven.compiler.target>1.8</maven.compiler.target>
                    <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
                </properties>
                <!--
                    用于定义远程仓库的,当该profile是激活状态的时候,这里面定义的远程仓库将作为当前pom的远程仓库。
                    它是maven用来填充构建系统本地仓库所使用的一组远程仓库。
                -->
                <repositories>
                    <!--包含需要连接到远程仓库的信息 -->
                    <repository>
                        <!--远程仓库唯一标识 -->
                        <id>codehausSnapshots</id>
                        <!--远程仓库名称 -->
                        <name>Codehaus Snapshots</name>
                        <!--如何处理远程仓库里发布版本的下载 -->
                        <releases>
                            <!--true或者false表示该仓库是否为下载某种类型构件(发布版,快照版)开启。 -->
                            <enabled>false</enabled>
                            <!--
                                该元素指定更新发生的频率。
                                Maven会比较本地POM和远程POM的时间戳。
                                这里的选项是:always(一直),daily(默认,每日),interval:X(这里X是以分钟为单位的时间间隔),或者never(从不)。
                            -->
                            <updatePolicy>always</updatePolicy>
                            <!--当Maven验证构件校验文件失败时该怎么做-ignore(忽略),fail(失败),或者warn(警告)。 -->
                            <checksumPolicy>warn</checksumPolicy>
                        </releases>
                        <!--如何处理远程仓库里快照版本的下载。有了releases和snapshots这两组配置,POM就可以在每个单独的仓库中,为每种类型的构件采取不同的策略。例如,可能有人会决定只为开发目的开启对快照版本下载的支持。参见repositories/repository/releases元素 -->
    <!--                    <snapshots>-->
    <!--                        &lt;!&ndash;表示这个仓库是否允许这种类型的工件&ndash;&gt;-->
    <!--                        <enabled/>-->
    <!--                        &lt;!&ndash;表示多久尝试更新一次。可选值有always、daily、interval:minutes(表示每多久更新一次)和never。&ndash;&gt;-->
    <!--                        <updatePolicy/>-->
    <!--                        &lt;!&ndash;当Maven在部署项目到仓库的时候会连同校验文件一起提交,checksumPolicy表示当这个校验文件缺失或不正确的时候该如何处理,可选项有ignore、fail和warn。&ndash;&gt;-->
    <!--                        <checksumPolicy/>-->
    <!--                    </snapshots>-->
                        <!--远程仓库URL,按protocol://hostname/path形式 -->
                        <url>http://snapshots.maven.codehaus.org/maven2</url>
                        <!--用于定位和排序构件的仓库布局类型-可以是default(默认)或者legacy(遗留)。Maven 2为其仓库提供了一个默认的布局;然而,Maven 1.x有一种不同的布局。我们可以使用该元素指定布局是default(默认)还是legacy(遗留)。 -->
                        <layout>default</layout>
                    </repository>
                </repositories>
                <!--
                    在Maven中有两种类型的仓库,一种是存储工件的仓库,另一种就是存储plugin插件的仓库。
                    pluginRepositories的定义和repositories的定义类似,它表示Maven在哪些地方可以找到所需要的插件。
                    和repository类似,只是repository是管理jar包依赖的仓库,pluginRepositories则是管理插件的仓库。
                    maven插件是一种特殊类型的构件。由于这个原因,插件仓库独立于其它仓库。
                    pluginRepositories元素的结构和repositories元素的结构类似。
                    每个pluginRepository元素指定一个Maven可以用来寻找新插件的远程地址。
                -->
                <pluginRepositories>
                    <!-- 包含需要连接到远程插件仓库的信息.参见profiles/profile/repositories/repository元素的说明 -->
    <!--                <pluginRepository>-->
    <!--                    <releases>-->
    <!--                        <enabled/>-->
    <!--                        <updatePolicy/>-->
    <!--                        <checksumPolicy/>-->
    <!--                    </releases>-->
    <!--                    <snapshots>-->
    <!--                        <enabled/>-->
    <!--                        <updatePolicy/>-->
    <!--                        <checksumPolicy/>-->
    <!--                    </snapshots>-->
    <!--                    <id>a</id>-->
    <!--                    <name/>-->
    <!--                    <url/>-->
    <!--                    <layout>b</layout>-->
    <!--                </pluginRepository>-->
                </pluginRepositories>
            </profile>
            <profile>
                <!-- id必须唯一 -->
                <id>myRepository2</id>
                <repositories>
                    <repository>
                        <!-- id必须唯一 -->
                        <id>myRepository2_1</id>
                        <!-- 仓库的url地址 -->
                        <url>http://repository.jboss.org/nexus/content/groups/public-jboss/</url>
                        <releases>
                            <enabled>true</enabled>
                        </releases>
                        <snapshots>
                            <enabled>true</enabled>
                            <updatePolicy>always</updatePolicy>
                        </snapshots>
                    </repository>
                </repositories>
            </profile>
            <profile>
                <!-- id必须唯一 -->
                <id>myRepositoryAliyun</id>
                <repositories>
                    <repository>
                        <!-- id必须唯一 -->
                        <id>myRepositoryAliyun_1</id>
                        <!-- 仓库的url地址 -->
                        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
                        <releases>
                            <enabled>true</enabled>
                        </releases>
                        <snapshots>
                            <enabled>true</enabled>
                            <updatePolicy>always</updatePolicy>
                        </snapshots>
                    </repository>
                </repositories>
            </profile>
            <profile>
                <id>downloadSources</id>
                <properties>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </properties>
            </profile>
        </profiles>
    
        <!--
            手动激活profiles的列表,按照profile被应用的顺序定义activeProfile。
            该元素包含了一组activeProfile元素,每个activeProfile都含有一个profile id。
            任何在activeProfile中定义的profile id,不论环境设置如何,其对应的 profile都会被激活。如果没有匹配的profile,则什么都不会发生。
            例如,env-test是一个activeProfile,则在pom.xml(或者profile.xml)中对应id的profile会被激活。
            如果运行过程中找不到这样一个profile,Maven则会像往常一样运行。
        -->
        <activeProfiles>
            <!-- 要激活的profile id -->
            <activeProfile>jdk-1.8</activeProfile>
            <activeProfile>myRepositoryAliyun</activeProfile>
            <activeProfile>myRepository2</activeProfile>
        </activeProfiles>
    </settings>
    

    无注释的setting.xml文件

    点击查看代码
    <?xml version="1.0" encoding="UTF-8"?>
    
    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    
        <localRepository>D:\IT_Software\maven\maven-repository-lw</localRepository>
    
        <pluginGroups>
            <pluginGroup>org.codehaus.mojo</pluginGroup>
        </pluginGroups>
    
        <mirrors>
            <mirror>
                <id>nexus-aliyun</id>
                <name>Nexus aliyun</name>
                <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
                <mirrorOf>central</mirrorOf>
            </mirror>
            <mirror>
                <id>nexus-aliyun</id>
                <name>Nexus aliyun</name>
                <url>http://maven.aliyun.com/nexus/content/groups/public</url>
                <mirrorOf>*,!cloudera</mirrorOf>
            </mirror>
            <mirror>
                <id>central</id>
                <name>Maven Repository Switchboard</name>
                <url>http://repo1.maven.org/maven2/</url>
                <mirrorOf>central</mirrorOf>
            </mirror>
            <mirror>
                <id>repo2</id>
                <name>Human Readable Name for this Mirror.</name>
                <url>http://repo2.maven.org/maven2/</url>
                <mirrorOf>central</mirrorOf>
            </mirror>
        </mirrors>
    
        <profiles>
            <profile>
                <id>jdk-1.8</id>
                <activation>
                    <activeByDefault>true</activeByDefault>
                    <jdk>1.8</jdk>
                </activation>
                <repositories>
                    <repository>
                        <id>codehausSnapshots</id>
                        <name>Codehaus Snapshots</name>
                        <releases>
                            <enabled>true</enabled>
                        </releases>
                        <url>http://snapshots.maven.codehaus.org/maven2</url>
                    </repository>
                </repositories>
            </profile>
            <profile>
                <id>myRepository2</id>
                <repositories>
                    <repository>
                        <id>myRepository2_1</id>
                        <url>http://repository.jboss.org/nexus/content/groups/public-jboss/</url>
                        <releases>
                            <enabled>true</enabled>
                        </releases>
                        <snapshots>
                            <enabled>true</enabled>
                            <updatePolicy>always</updatePolicy>
                        </snapshots>
                    </repository>
                </repositories>
            </profile>
            <profile>
                <id>myRepositoryAliyun</id>
                <repositories>
                    <repository>
                        <id>myRepositoryAliyun_1</id>
                        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
                        <releases>
                            <enabled>true</enabled>
                        </releases>
                        <snapshots>
                            <enabled>true</enabled>
                            <updatePolicy>always</updatePolicy>
                        </snapshots>
                    </repository>
                </repositories>
            </profile>
            <profile>
                <id>downloadSources</id>
                <properties>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </properties>
            </profile>
        </profiles>
    
        <activeProfiles>
            <activeProfile>jdk-1.8</activeProfile>
            <activeProfile>myRepositoryAliyun</activeProfile>
            <activeProfile>myRepository2</activeProfile>
        </activeProfiles>
    </settings>
    
    1. 修改pom.xml文件
      image
      image
      image
    pom.xml文件
    <?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>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.7.2</version>
            <relativePath/>
        </parent>
    
        <groupId>com.xiaostudy</groupId>
        <artifactId>SpringCloud202208</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <packaging>pom</packaging>
    
        <modules>
            <module>eureka</module>
            <module>config</module>
        </modules>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
    
            <java.version>1.8</java.version>
            <spring-cloud.version>2021.0.3</spring-cloud.version>
    
            <eureka.application.name>EUREKA-SERVICE</eureka.application.name>
            <eureka.ip>localhost</eureka.ip>
            <eureka.port>9900</eureka.port>
            <eureka.url.name>eureka</eureka.url.name>
            <eureka.user.name>admin</eureka.user.name>
            <eureka.user.password>xiaostudy.test</eureka.user.password>
    
            <config.application.name>CONFIG-SERVICE</config.application.name>
            <config.port>9901</config.port>
    
            <gateway.application.name>GATEWAY-SERVICE</gateway.application.name>
            <gateway.port>9904</gateway.port>
            <gateway.version>3.1.3</gateway.version>
    
            <producer.application.name>PRODUCER-SERVICE</producer.application.name>
            <producer.port>9902</producer.port>
    
            <web.application.name>WEB-SERVICE</web.application.name>
            <web.port>9903</web.port>
    
            <sentinel.version>2021.0.1.0</sentinel.version>
            <sentinel.port>9909</sentinel.port>
    
            <!--        <spring.profiles.active>dev</spring.profiles.active>-->
            <spring.profiles.active>prod</spring.profiles.active>
        </properties>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
    </project>
    

    2. 新建注册中心Eureka

    1. 创建操作
      image
      image
      image
      image

    2. 父模块添加子模块
      image

    <modules>
        <module>eureka</module>
    </modules>
    
    1. 修改pom.xml文件
      image
      image
      image
    点击查看代码
    <?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>
            <groupId>com.xiaostudy</groupId>
            <artifactId>SpringCloud202208</artifactId>
            <version>1.0-SNAPSHOT</version>
            <relativePath>../pom.xml</relativePath>
        </parent>
        <groupId>com.xiaostudy</groupId>
        <artifactId>eureka</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>eureka</name>
        <description>eureka</description>
        <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-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    此时父模块的pom.xml
    <?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>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.7.2</version>
            <relativePath/>
        </parent>
    
        <groupId>com.xiaostudy</groupId>
        <artifactId>SpringCloud202208</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <packaging>pom</packaging>
    
        <modules>
            <module>eureka</module>
        </modules>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
    
            <java.version>1.8</java.version>
            <spring-cloud.version>2021.0.3</spring-cloud.version>
    
            <eureka.application.name>EUREKA-SERVICE</eureka.application.name>
            <eureka.ip>localhost</eureka.ip>
            <eureka.port>9900</eureka.port>
            <eureka.url.name>eureka</eureka.url.name>
            <eureka.user.name>admin</eureka.user.name>
            <eureka.user.password>xiaostudy.test</eureka.user.password>
    
            <config.application.name>CONFIG-SERVICE</config.application.name>
            <config.port>9901</config.port>
    
            <gateway.application.name>GATEWAY-SERVICE</gateway.application.name>
            <gateway.port>9904</gateway.port>
            <gateway.version>3.1.3</gateway.version>
    
            <producer.application.name>PRODUCER-SERVICE</producer.application.name>
            <producer.port>9902</producer.port>
    
            <web.application.name>WEB-SERVICE</web.application.name>
            <web.port>9903</web.port>
    
            <sentinel.version>2021.0.1.0</sentinel.version>
            <sentinel.port>9909</sentinel.port>
    
            <!--        <spring.profiles.active>dev</spring.profiles.active>-->
            <spring.profiles.active>prod</spring.profiles.active>
        </properties>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${parent.version}</version>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
    </project>
    
    1. 配置文件application.properties修改为application.yml,然后配置
      image
      image
      image
    点击查看代码
    server:
      port: '@eureka.port@'
    
    eureka:
      url-name: '@eureka.url.name@'
      instance:
        hostname: '@eureka.ip@'
        # 每隔这个时间会主动心跳一次,默认值为30s
        leaseRenewalIntervalInSeconds: 25
      server:
        # 自我保护机制,默认权重0.85。默认情况下会报警告,资料:https://blog.csdn.net/hadues/article/details/105023709
        renewalPercentThreshold: 0.49
      client:
        # 声明是否将自己的信息注册到Eureka服务器上
        registerWithEureka: false
        # 是否到Eureka服务器中抓取注册信息
        fetchRegistry: false
        serviceUrl:
          defaultZone: http://@eureka.user.name@:@eureka.user.password@@${eureka.instance.hostname}:${server.port}/${eureka.url-name}/
    
    spring:
      application:
        name: '@eureka.application.name@'
      security:
        user:
          name: '@eureka.user.name@'
          password: '@eureka.user.password@'
    
    
    1. 启动类添加注解@EnableEurekaServer
      image

    2. 关闭csrf,不然其他服务注册不上
      image
      image
      image

    点击查看代码
    package com.xiaostudy.eureka.config;
    
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    @EnableWebSecurity
    public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            //关闭csrf,不然其他服务注册不上
            http.csrf().disable();
            super.configure(http);
        }
    }
    
    1. 启动注册中心
      image
      image
      image
      image
      image

    2. 访问
      http://localhost:9900/
      image
      image

    3. 新建配置中心Config

    1. 创建操作
      image
      image
      image
      image

    2. 父模块添加子模块
      image

    <module>config</module>
    
    1. 修改pom.xml文件
      image
      image
    点击查看代码
    <?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>
            <groupId>com.xiaostudy</groupId>
            <artifactId>SpringCloud202208</artifactId>
            <version>1.0-SNAPSHOT</version>
            <relativePath>../pom.xml</relativePath>
        </parent>
        <groupId>com.xiaostudy</groupId>
        <artifactId>config</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>config</name>
        <description>config</description>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-config-server</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-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    1. 配置文件application.properties修改为application.yml,然后配置
      image
      image
      image
    点击查看代码
    server:
      port: '@config.port@'
    
    eureka:
      port: '@eureka.port@'
      ip: '@eureka.ip@'
      url-name: '@eureka.url.name@'
      instance:
        # 把本机IP注册到eureka而不是本机机器名
        preferIpAddress: true
        instance-id: ${spring.cloud.client.ip-address}:${server.port}
      client:
        serviceUrl:
          defaultZone: http://@eureka.user.name@:@eureka.user.password@@${eureka.ip}:${eureka.port}/${eureka.url-name}/
    
    spring:
      application:
        name: '@config.application.name@'
      cloud:
        loadbalancer:
          retry:
            # 关闭重试
            enabled: false
      profiles:
        # 这里主要是为了掩饰和config.profile的区分
        active: native
    
    1. 删除多余的文件夹
      image
      image
      image
      image
      image

    2. 添加配置文件,给其他服务读取
      image
      image
      image
      image
      image
      image
      image

    3. 启动类添加注解@EnableDiscoveryClient和@EnableConfigServer
      image

    4. 启动config服务
      image
      image

    5. Eureka上面查看服务
      image

    4. 新建两个业务服务

    1. producerService

    1. 创建操作
      image
      image
      image
      image

    2. 父模块添加子模块
      image

    <module>producerService</module>
    
    1. pom.xml文件修改
      image
      image
    点击查看代码
    <?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>
            <groupId>com.xiaostudy</groupId>
            <artifactId>SpringCloud202208</artifactId>
            <version>1.0-SNAPSHOT</version>
            <relativePath>../pom.xml</relativePath>
        </parent>
        <groupId>com.xiaostudy</groupId>
        <artifactId>producerService</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>producerService</name>
        <description>producerService</description>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--SpringCloud 2020.*以后的版本默认禁用了bootstrap,导致读取配置文件时读取不到该属性-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-bootstrap</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</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-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    1. 配置文件application.properties修改为application.yml,然后配置
      image
    点击查看代码
    server:
      port: '@producer.port@'
    
    eureka:
      port: '@eureka.port@'
      ip: '@eureka.ip@'
      url-name: '@eureka.url.name@'
      instance:
        # 把本机IP注册到eureka而不是本机机器名
        preferIpAddress: true
        # 把本机IP注册到eureka,由下面参数组成
        instance-id: ${spring.cloud.client.ip-address}:${server.port}
      client:
        serviceUrl:
          defaultZone: http://@eureka.user.name@:@eureka.user.password@@${eureka.ip}:${eureka.port}/${eureka.url-name}/
    
    spring:
      application:
        name: '@producer.application.name@'
      cloud:
        loadbalancer:
          retry:
            # 关闭重试
            enabled: false
    
    1. 添加bootstrap.yml配置文件,bootstrap.yml
      SpringCloud-Config-Client配置文件为什么一定要是bootstrap.yml或者bootstrap.properties
      image
    点击查看代码
    eureka:
      client:
        serviceUrl:
          defaultZone: http://admin:xiaostudy.test@localhost:9900/eureka/
    
    spring:
      cloud:
        config:
          discovery:
            # 开启配置中心服务发现支持
            enabled: true
            # 配置中心服务的id,这里不能用@@去获取参数
            service-id: CONFIG-SERVICE
          # 那个文件夹,config模块resources/config下的那个文件夹
          label: prod
          # 配置文件名称
          name: config
          # 读取后缀名称
          profile: prod
          # fail-fast 如果访问配置中心失败,则停止启动服务。默认false
          fail-fast: true
          # retry 访问配置中心失败时的重试策略
          retry:
            # 重试间隔
            initial-interval: 1000
            # 最多重试次数
            max-attempts: 6
            # 最大重试间隔
            max-interval: 2000
            # 每次重试时间是之前的倍数
            multiplier: 1.1
    
    1. 启动类添加注解
      image
    @EnableDiscoveryClient
    @ComponentScan(basePackages = {"com.xiaostudy"})
    
    1. 写一个controller
      image
    点击查看代码
    package com.xiaostudy.producerservice.controller;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/producerTest")
    public class producerController {
    
        @Value("${server.port}")
        private String port;
    
        @Value("${my.test}")
        private String myTest;
    
        @GetMapping("/getByName")
        public String get(String name) {
            return "参数name:" + name + ",配置中心拿到的参数:" + myTest + ",应用端口:" + port;
        }
    }
    
    1. 启动
      image
      image

    2. 访问
      image
      image
      http://localhost:9902/producerTest/getByName?name=aaaa

    2. 创建Feign

    目前演示就只有一个feign,就是调producerService和后面的Security用户信息

    1. 创建操作
      image
      image

    2. 父模块添加子模块
      image

    <module>feign</module>
    
    1. pom.xml文件修改
      image
    点击查看代码
    <?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>
            <groupId>com.xiaostudy</groupId>
            <artifactId>SpringCloud202208</artifactId>
            <version>1.0-SNAPSHOT</version>
            <relativePath>../pom.xml</relativePath>
        </parent>
        <groupId>com.xiaostudy</groupId>
        <artifactId>feign</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>feign</name>
        <description>feign</description>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    1. 配置类,服务间调用把请求头带上,后面认证用到
      image
    点击查看代码
    package com.xiaostudy.feign.config;
    
    import feign.RequestInterceptor;
    import feign.RequestTemplate;
    import org.springframework.util.ObjectUtils;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Enumeration;
    import java.util.Locale;
    
    // 服务之间调用时 把请求头带上
    public class FeignConfig implements RequestInterceptor {
        @Override
        public void apply(RequestTemplate requestTemplate) {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (ObjectUtils.isEmpty(attributes)) {
                return;
            }
            HttpServletRequest request = attributes.getRequest();
            Enumeration<String> headerNames = request.getHeaderNames();
            String name;
            String authorization = null;
            //添加token
            while (headerNames.hasMoreElements()) {
                name = headerNames.nextElement();
                String header = request.getHeader(name);
                if ("Authorization".equals(name) || (null != name && name.toLowerCase(Locale.ROOT).equals("authorization"))) {
                    authorization = header;
                }
                requestTemplate.header(name, header);
            }
            if (ObjectUtils.isEmpty(authorization)) {
                Cookie[] cookies = request.getCookies();
                if (null == cookies) {
                    return;
                }
                for (Cookie cookie : cookies) {
                    if ("Authorization".equals(cookie.getName()) || "authorization".equals(cookie.getName().toLowerCase(Locale.ROOT))) {
                        requestTemplate.header("Authorization", cookie.getValue());
                        break;
                    }
                }
            }
        }
    }
    
    1. 配置文件application.properties修改为application-feign.yml,然后配置
      image
    点击查看代码
    producer:
      application:
        name: @producer.application.name@
    feign:
      client:
        config:
          default:
            # 默认是1000
            connect-timeout: 5000
            read-timeout: 5000
    
    1. 创建feign接口
      image
    点击查看代码
    package com.xiaostudy.feign.apis;
    
    import com.xiaostudy.feign.config.FeignConfig;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.http.MediaType;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    @FeignClient(name = "${producer.application.name}", contextId = "ProducerServiceApis"
            , configuration = FeignConfig.class)
    public interface ProducerServiceApis {
        @GetMapping(value = "/producerTest/getByName", consumes = MediaType.APPLICATION_JSON_VALUE)
        public String getByName(@RequestParam("name") String name);
    }
    
    1. 删除启动类
      image

    3. webService

    1. 创建操作
      image
      image

    2. 父模块添加子模块
      image

    <module>webService</module>
    
    1. pom.xml文件修改
      image
      image
    点击查看代码
    <?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>
            <groupId>com.xiaostudy</groupId>
            <artifactId>SpringCloud202208</artifactId>
            <version>1.0-SNAPSHOT</version>
            <relativePath>../pom.xml</relativePath>
        </parent>
        <groupId>com.xiaostudy</groupId>
        <artifactId>webService</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>webService</name>
        <description>webService</description>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
            <dependency>
                <groupId>com.xiaostudy</groupId>
                <artifactId>feign</artifactId>
                <version>0.0.1-SNAPSHOT</version>
            </dependency>
    
            <!-- druid数据源驱动 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.2.1</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.2</version>
            </dependency>
            <!--MySQL-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    
            <!-- Oracle -->
            <dependency>
                <groupId>com.oracle.database.jdbc</groupId>
                <artifactId>ojdbc8</artifactId>
            </dependency>
            <dependency>
                <groupId>com.oracle.database.nls</groupId>
                <artifactId>orai18n</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    1. 配置文件application.properties修改为application.yml,然后配置
      image
    点击查看代码
    server:
      port: '@web.port@'
    
    eureka:
      port: '@eureka.port@'
      ip: '@eureka.ip@'
      url-name: '@eureka.url.name@'
      instance:
        # 把本机IP注册到eureka而不是本机机器名
        preferIpAddress: true
        # 把本机IP注册到eureka,由下面参数组成
        instance-id: ${spring.cloud.client.ip-address}:${server.port}
      client:
        serviceUrl:
          defaultZone: http://@eureka.user.name@:@eureka.user.password@@${eureka.ip}:${eureka.port}/${eureka.url-name}/
    
    spring:
      application:
        name: '@web.application.name@'
      cloud:
        loadbalancer:
          retry:
            # 关闭重试
            enabled: false
      profiles:
        # 使用的配置文件后缀application-feign.yml引进来
        active: feign
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
          driverClassName: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://127.0.0.1:3306/test1?useUnicode=true&characterEncoding=utf8
          username: root
          password: 密码
        druid2:
          driverClassName: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://127.0.0.1:3306/test2?useUnicode=true&characterEncoding=utf8
          username: root
          password: 密码
        druid3:
          driverClassName: oracle.jdbc.OracleDriver
          url: jdbc:oracle:thin:@//localhost:1521/ORCL
          username: lw
          password: 密码
    
    
    1. MySQL测试用到的用户表,建表SQL,不规范哦
    点击查看代码
    CREATE TABLE `user` (
      `username` varchar(255) DEFAULT NULL,
      `password` varchar(255) DEFAULT NULL,
      `role` varchar(255) DEFAULT NULL,
      `error_count` int(10) DEFAULT NULL,
      `url` varchar(255) DEFAULT NULL,
      `email` varchar(255) DEFAULT NULL,
      `phone` varchar(255) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息表测试'
    
    1. Oracle测试用到的用户名,建表SQL,不规范哦
    点击查看代码
    CREATE TABLE "LW"."user" (
    "username" VARCHAR2 ( 255 ),
    "password" VARCHAR2 ( 255 ),
    "role" VARCHAR2 ( 255 )
    )
    
    1. 创建3个实体类
      image
      image
      image

    注意截图的实体类entity打错成eentity

    db1的实体类
    package com.xiaostudy.webservice.entity.db1;
    
    
    public class UserEentity {
    
        private String username;
        private String password;
        private String role;
        private int errorCount;
        private String url;
        private String email;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public String getRole() {
            return role;
        }
    
        public void setRole(String role) {
            this.role = role;
        }
    
        public int getErrorCount() {
            return errorCount;
        }
    
        public void setErrorCount(int errorCount) {
            this.errorCount = errorCount;
        }
    
        public String getUrl() {
            return url;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }
    
    db2的实体类
    package com.xiaostudy.webservice.entity.db2;
    
    public class UserEentity {
    
        private String username;
        private String password;
        private String role;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public String getRole() {
            return role;
        }
    
        public void setRole(String role) {
            this.role = role;
        }
    }
    
    db3的实体类
    package com.xiaostudy.webservice.entity.db3;
    
    public class UserEentity {
    
        private String username;
        private String password;
        private String role;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public String getRole() {
            return role;
        }
    
        public void setRole(String role) {
            this.role = role;
        }
    }
    
    1. 字符串工具类
    字符串工具类
    package com.xiaostudy.webservice.utils;
    
    
    public class StringUtils {
        public static final String DB_1_MAPPER_PACKAGE = "com.xiaostudy.webservice.mapper.db1";
        public static final String DB_1_ENTITY_PACKAGE = "com.xiaostudy.webservice.entity.db1";
        public static final String DB_1_MAPPER_LOCATION = "classpath*:mapper/db1/*.xml";
        public static final String DB_1_SQL_SESSION_FACTORY_REF = "db1SqlSessionFactory";
        public static final String DB_1_DATA_SOURCE_NAME = "db1DataSource";
        public static final String DB_1_TRANSACTION_MANAGER_NAME = "db1TransactionManager";
    
        public static final String DB_2_MAPPER_PACKAGE = "com.xiaostudy.webservice.mapper.db2";
        public static final String DB_2_ENTITY_PACKAGE = "com.xiaostudy.webservice.entity.db2";
        public static final String DB_2_MAPPER_LOCATION = "classpath*:mapper/db2/*.xml";
        public static final String DB_2_SQL_SESSION_FACTORY_REF = "db2SqlSessionFactory";
        public static final String DB_2_DATA_SOURCE_NAME = "db2DataSource";
        public static final String DB_2_TRANSACTION_MANAGER_NAME = "db2TransactionManager";
    
        public static final String DB_3_MAPPER_PACKAGE = "com.xiaostudy.webservice.mapper.db3";
        public static final String DB_3_ENTITY_PACKAGE = "com.xiaostudy.webservice.entity.db3";
        public static final String DB_3_MAPPER_LOCATION = "classpath*:mapper/db3/*.xml";
        public static final String DB_3_SQL_SESSION_FACTORY_REF = "db3SqlSessionFactory";
        public static final String DB_3_DATA_SOURCE_NAME = "db3DataSource";
        public static final String DB_3_TRANSACTION_MANAGER_NAME = "db3TransactionManager";
    
        public static final String DB_1_SERVICE_BEAN_NAME = "UserService1";
        public static final String DB_2_SERVICE_BEAN_NAME = "UserService2";
        public static final String DB_3_SERVICE_BEAN_NAME = "UserService3";
    
        public static final String DB_1_MAPPER_BEAN_NAME = "UserMapper1";
        public static final String DB_2_MAPPER_BEAN_NAME = "UserMapper2";
        public static final String DB_3_MAPPER_BEAN_NAME = "UserMapper3";
    }
    
    1. mapper接口
      image
      image
      image

    注意截图的实体类entity打错成eentity

    db1的Mapper接口
    package com.xiaostudy.webservice.mapper.db1;
    
    import com.xiaostudy.webservice.entity.db1.UserEentity;
    import com.xiaostudy.webservice.utils.StringUtils;
    import org.apache.ibatis.annotations.Param;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository(StringUtils.DB_1_MAPPER_BEAN_NAME)
    public interface UserMapper {
    
        public List<UserEentity> selectUserAll();
        public UserEentity selectUserByUsername(@Param("username") String username);
        public int insertUser(@Param("user") UserEentity userEentity);
    }
    
    db2的Mapper接口
    package com.xiaostudy.webservice.mapper.db2;
    
    import com.xiaostudy.webservice.entity.db2.UserEentity;
    import com.xiaostudy.webservice.utils.StringUtils;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository(StringUtils.DB_2_MAPPER_BEAN_NAME)
    public interface UserMapper {
    
        public List<UserEentity> selectUserAll();
    }
    
    db3的Mapper接口
    package com.xiaostudy.webservice.mapper.db3;
    
    import com.xiaostudy.webservice.entity.db3.UserEentity;
    import com.xiaostudy.webservice.utils.StringUtils;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository(StringUtils.DB_3_MAPPER_BEAN_NAME)
    public interface UserMapper {
    
        public List<UserEentity> selectUserAll();
    }
    
    1. Mapper.xml文件
      image
      image
      image
    db1的Mapper.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.xiaostudy.webservice.mapper.db1.UserMapper">
    
        <select id="selectUserAll" resultType="com.xiaostudy.webservice.entity.db1.UserEentity">
            SELECT username, password, role FROM `user`
        </select>
    
        <select id="selectUserByUsername" resultType="com.xiaostudy.webservice.entity.db1.UserEentity">
            SELECT username, password, role, error_count, url, email FROM `user` where username = #{username}
        </select>
    
        <insert id="insertUser">
            insert into `user` (username, password) values (#{user.username}, #{user.password})
        </insert>
    
    </mapper>
    
    db2的Mapper.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.xiaostudy.webservice.mapper.db2.UserMapper">
    
        <select id="selectUserAll" resultType="com.xiaostudy.webservice.entity.db2.UserEentity">
            SELECT username, password, role FROM `user`
        </select>
    
    </mapper>
    
    db3的Mapper.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.xiaostudy.webservice.mapper.db3.UserMapper">
    
        <select id="selectUserAll" resultType="com.xiaostudy.webservice.entity.db3.UserEentity">
            SELECT "username", "password", "role" FROM "user"
        </select>
    
    </mapper>
    
    1. service代码,不截图了,直接放代码
    db1的service接口
    package com.xiaostudy.webservice.service.db1;
    
    
    import com.xiaostudy.webservice.entity.db1.UserEentity;
    
    import java.util.List;
    
    public interface UserService {
    
        public List<UserEentity> selectUserAll();
        public UserEentity selectUserByUsername(String username);
        public boolean insertUser(UserEentity userEentity);
    }
    
    db2的service接口
    package com.xiaostudy.webservice.service.db2;
    
    
    import com.xiaostudy.webservice.entity.db2.UserEentity;
    
    import java.util.List;
    
    public interface UserService {
    
        public List<UserEentity> selectUserAll();
    }
    
    db3的service接口
    package com.xiaostudy.webservice.service.db3;
    
    
    import com.xiaostudy.webservice.entity.db3.UserEentity;
    
    import java.util.List;
    
    public interface UserService {
    
        public List<UserEentity> selectUserAll();
    }
    
    db1的service实现类
    package com.xiaostudy.webservice.service.db1.impl;
    
    import com.xiaostudy.webservice.entity.db1.UserEentity;
    import com.xiaostudy.webservice.mapper.db1.UserMapper;
    import com.xiaostudy.webservice.service.db1.UserService;
    import com.xiaostudy.webservice.utils.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.lang.NonNull;
    import org.springframework.stereotype.Service;
    import org.springframework.util.ObjectUtils;
    
    import java.util.List;
    
    @Service(StringUtils.DB_1_SERVICE_BEAN_NAME)
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserMapper userMapper;
    
        @Override
        public List<UserEentity> selectUserAll() {
            return userMapper.selectUserAll();
        }
    
        @Override
        public UserEentity selectUserByUsername(@NonNull String username) {
            return userMapper.selectUserByUsername(username);
        }
    
        @Override
        public boolean insertUser(@NonNull UserEentity userEentity) {
            String username = userEentity.getUsername();
            if (ObjectUtils.isEmpty(username)) {
                return false;
            }
            UserEentity userEentity1 = this.selectUserByUsername(username);
            if (!ObjectUtils.isEmpty(userEentity1)) {
                return false;
            }
            int i = userMapper.insertUser(userEentity);
            return i > 0;
        }
    }
    
    db2的service实现类
    package com.xiaostudy.webservice.service.db2.impl;
    
    import com.xiaostudy.webservice.entity.db2.UserEentity;
    import com.xiaostudy.webservice.mapper.db2.UserMapper;
    import com.xiaostudy.webservice.service.db2.UserService;
    import com.xiaostudy.webservice.utils.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service(StringUtils.DB_2_SERVICE_BEAN_NAME)
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserMapper userMapper;
    
        @Override
        public List<UserEentity> selectUserAll() {
            return userMapper.selectUserAll();
        }
    }
    
    db3的service实现类
    package com.xiaostudy.webservice.service.db3.impl;
    
    import com.xiaostudy.webservice.entity.db3.UserEentity;
    import com.xiaostudy.webservice.mapper.db3.UserMapper;
    import com.xiaostudy.webservice.service.db3.UserService;
    import com.xiaostudy.webservice.utils.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service(StringUtils.DB_3_SERVICE_BEAN_NAME)
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserMapper userMapper;
    
        @Override
        public List<UserEentity> selectUserAll() {
            return userMapper.selectUserAll();
        }
    }
    
    1. 多数据源配置类,直接上代码
      image
    db1的数据源配置类
    package com.xiaostudy.webservice.config;
    
    
    import com.alibaba.druid.pool.DruidDataSource;
    import com.xiaostudy.webservice.utils.StringUtils;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    
    import javax.sql.DataSource;
    
    @Configuration
    @MapperScan(basePackages = StringUtils.DB_1_MAPPER_PACKAGE, sqlSessionFactoryRef = StringUtils.DB_1_SQL_SESSION_FACTORY_REF)
    public class Db1Config {
    
        @Value("${spring.datasource.druid.url}")
        private String dbUrl;
    
        @Value("${spring.datasource.druid.username}")
        private String username;
    
        @Value("${spring.datasource.druid.password}")
        private String password;
    
        @Value("${spring.datasource.druid.driverClassName}")
        private String driverClassName;
    
    
        @Bean(name= StringUtils.DB_1_DATA_SOURCE_NAME)   //声明其为Bean实例
        @Primary  //在同样的DataSource中,首先使用被标注的DataSource
        public DataSource masterDataSource() {
            DruidDataSource datasource = new DruidDataSource();
    
            datasource.setUrl(dbUrl);
            datasource.setUsername(username);
            datasource.setPassword(password);
            datasource.setDriverClassName(driverClassName);
    
            return datasource;
        }
    
        @Bean(name = StringUtils.DB_1_TRANSACTION_MANAGER_NAME)
        @Primary
        public DataSourceTransactionManager masterTransactionManager() {
            return new DataSourceTransactionManager(this.masterDataSource());
        }
    
        @Bean(name = StringUtils.DB_1_SQL_SESSION_FACTORY_REF)
        @Primary
        public SqlSessionFactory masterSqlSessionFactory(@Qualifier(StringUtils.DB_1_DATA_SOURCE_NAME) DataSource masterDataSource)
                throws Exception {
            final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
            sessionFactory.setDataSource(masterDataSource);
            sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                    // 精确到目录,以便跟其他数据源隔离
                    .getResources(StringUtils.DB_1_MAPPER_LOCATION));
            sessionFactory.setTypeAliasesPackage(StringUtils.DB_1_ENTITY_PACKAGE);
            //mybatis 数据库字段与实体类属性驼峰映射配置
            sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
            return sessionFactory.getObject();
        }
    }
    
    db2的数据源配置类
    package com.xiaostudy.webservice.config;
    
    
    import com.alibaba.druid.pool.DruidDataSource;
    import com.xiaostudy.webservice.utils.StringUtils;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    
    import javax.sql.DataSource;
    
    @Configuration
    @MapperScan(basePackages = StringUtils.DB_2_MAPPER_PACKAGE, sqlSessionFactoryRef = StringUtils.DB_2_SQL_SESSION_FACTORY_REF)
    public class Db2Config {
    
        @Value("${spring.datasource.druid2.url}")
        private String dbUrl;
    
        @Value("${spring.datasource.druid2.username}")
        private String username;
    
        @Value("${spring.datasource.druid2.password}")
        private String password;
    
        @Value("${spring.datasource.druid2.driverClassName}")
        private String driverClassName;
    
    
        @Bean(name= StringUtils.DB_2_DATA_SOURCE_NAME)   //声明其为Bean实例
        @Primary  //在同样的DataSource中,首先使用被标注的DataSource
        public DataSource masterDataSource() {
            DruidDataSource datasource = new DruidDataSource();
    
            datasource.setUrl(dbUrl);
            datasource.setUsername(username);
            datasource.setPassword(password);
            datasource.setDriverClassName(driverClassName);
    
            return datasource;
        }
    
        @Bean(name = StringUtils.DB_2_TRANSACTION_MANAGER_NAME)
        @Primary
        public DataSourceTransactionManager masterTransactionManager() {
            return new DataSourceTransactionManager(masterDataSource());
        }
    
        @Bean(name = StringUtils.DB_2_SQL_SESSION_FACTORY_REF)
        @Primary
        public SqlSessionFactory masterSqlSessionFactory(@Qualifier(StringUtils.DB_2_DATA_SOURCE_NAME) DataSource masterDataSource)
                throws Exception {
            final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
            sessionFactory.setDataSource(masterDataSource);
            sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                    // 精确到目录,以便跟其他数据源隔离
                    .getResources(StringUtils.DB_2_MAPPER_LOCATION));
            sessionFactory.setTypeAliasesPackage(StringUtils.DB_2_ENTITY_PACKAGE);
            //mybatis 数据库字段与实体类属性驼峰映射配置
            sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
            return sessionFactory.getObject();
        }
    }
    
    db3的数据源配置类
    package com.xiaostudy.webservice.config;
    
    
    import com.alibaba.druid.pool.DruidDataSource;
    import com.xiaostudy.webservice.utils.StringUtils;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    
    import javax.sql.DataSource;
    
    @Configuration
    @MapperScan(basePackages = StringUtils.DB_3_MAPPER_PACKAGE, sqlSessionFactoryRef = StringUtils.DB_3_SQL_SESSION_FACTORY_REF)
    public class Db3Config {
    
        @Value("${spring.datasource.druid3.url}")
        private String dbUrl;
    
        @Value("${spring.datasource.druid3.username}")
        private String username;
    
        @Value("${spring.datasource.druid3.password}")
        private String password;
    
        @Value("${spring.datasource.druid3.driverClassName}")
        private String driverClassName;
    
    
        @Bean(name= StringUtils.DB_3_DATA_SOURCE_NAME)   //声明其为Bean实例
        @Primary  //在同样的DataSource中,首先使用被标注的DataSource
        public DataSource masterDataSource() {
            DruidDataSource datasource = new DruidDataSource();
    
            datasource.setUrl(dbUrl);
            datasource.setUsername(username);
            datasource.setPassword(password);
            datasource.setDriverClassName(driverClassName);
    
            return datasource;
        }
    
        @Bean(name = StringUtils.DB_3_TRANSACTION_MANAGER_NAME)
        @Primary
        public DataSourceTransactionManager masterTransactionManager() {
            return new DataSourceTransactionManager(masterDataSource());
        }
    
        @Bean(name = StringUtils.DB_3_SQL_SESSION_FACTORY_REF)
        @Primary
        public SqlSessionFactory masterSqlSessionFactory(@Qualifier(StringUtils.DB_3_DATA_SOURCE_NAME) DataSource masterDataSource)
                throws Exception {
            final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
            sessionFactory.setDataSource(masterDataSource);
            sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                    // 精确到目录,以便跟其他数据源隔离
                    .getResources(StringUtils.DB_3_MAPPER_LOCATION));
            sessionFactory.setTypeAliasesPackage(StringUtils.DB_3_ENTITY_PACKAGE);
            //mybatis 数据库字段与实体类属性驼峰映射配置
            sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
            return sessionFactory.getObject();
        }
    }
    
    1. 用户controller测试
      多数据源,数据分开管;测试feign服务
      image
    点击查看代码
    package com.xiaostudy.webservice.controller;
    
    import com.xiaostudy.feign.apis.ProducerServiceApis;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import java.util.List;
    import java.util.stream.Collectors;
    
    @Controller
    @RequestMapping("/webUser")
    public class UserController {
    
        @Autowired
        private com.xiaostudy.webservice.service.db1.UserService userService1;
        @Autowired
        private com.xiaostudy.webservice.service.db2.UserService userService2;
        @Autowired
        private com.xiaostudy.webservice.service.db3.UserService userService3;
        @Value("${server.port}")
        private String applicationPort;
        @Autowired
        private ProducerServiceApis producerServiceApis;
    
        @RequestMapping("/multiDataSource")
        @ResponseBody
        public String multiDataSource() {
            List<com.xiaostudy.webservice.entity.db1.UserEentity> userEentityList1 = userService1.selectUserAll();
            List<com.xiaostudy.webservice.entity.db2.UserEentity> userEentityList2 = userService2.selectUserAll();
            List<com.xiaostudy.webservice.entity.db3.UserEentity> userEentityList3 = userService3.selectUserAll();
            String testDataSource1 = userEentityList1.stream().map(com.xiaostudy.webservice.entity.db1.UserEentity::getUsername).collect(Collectors.joining(","));
            String testDataSource2 = userEentityList2.stream().map(com.xiaostudy.webservice.entity.db2.UserEentity::getUsername).collect(Collectors.joining(","));
            String testDataSource3 = userEentityList3.stream().map(com.xiaostudy.webservice.entity.db3.UserEentity::getUsername).collect(Collectors.joining(","));
            return "应用端口:" + applicationPort + ",数据源1查询的用户列表:" + testDataSource1 + ";数据源2查询的用户列表:" + testDataSource2 + ";数据源3查询的用户列表:" + testDataSource3;
        }
    
        @RequestMapping("/getProducerTest")
        @ResponseBody
        public String getProducerTest() {
            return "应用端口:" + applicationPort + "," + producerServiceApis.getByName("web服务");
        }
    
    }
    
    1. 启动类添加注解
      image
    @EnableDiscoveryClient
    @EnableFeignClients(basePackages = "com.xiaostudy.feign")
    @ComponentScan(basePackages = {"com.xiaostudy"})
    
    1. 数据库用户信息
      image
      image
      image

    2. 启动
      image
      image

    3. 访问
      image
      image
      image

  • 相关阅读:
    观察者模式
    php中compact,extract,list函数的使用
    加密解密
    python 线程池proxypool
    python qq音乐下载
    python 网易云音乐
    python 知识点
    python 格式化 header
    python 爬取百度图片
    php 过滤掉多维数组空值
  • 原文地址:https://www.cnblogs.com/xiaostudy/p/16630910.html
Copyright © 2020-2023  润新知