网站首页 全球最实用的IT互联网站!

人工智能P2P分享Wind搜索发布信息网站地图标签大全

当前位置:诺佳网 > 软件工程 > 后端开发 > Java >

通用型产品发布解决方案(基于分布式微服务技术

时间:2025-04-22 12:56

人气:

作者:admin

标签:

导读:通用型产品发布解决方案(基于分布式微服务技术栈:SpringBootSpringCloudSpring CloudAlibabaVueElementUIMyBatis-PlusMySQLGitMavenLinuxDockerNginx - 《02》 项目的源码地址: GitHu...

通用型产品发布解决方案(基于分布式微服务技术栈:SpringBoot+SpringCloud+Spring CloudAlibaba+Vue+ElementUI+MyBatis-Plus+MySQL+Git+Maven+Linux+Docker+Nginx - 《02》

项目的源码地址:

创建 GateWay 服务 和配置

通过 GateWay 进行对各个服务的转发,重定向进行配置信息。从而就简化配置,同时注意存在一个“同源策略” 的问题——》就是一个跨域问题。 CORS 的问题。

GateWay 不是一个 Web 服务,所以千万不可以在 GateWay 引入 Web 相关的依赖模块,不然会发生冲突

重点:注意:我们这里的 GateWay 不是一个 Web 服务,所以所以所以,我们千万千万千万不可以将 Web 相关的依赖的模块导入到 GateWay 当中,不然是会报错的,发生一个冲突。

gateway本身不是一个做 web服务器的,因此不要引入 spring-boot-starter-web,
否则会报告冲突 

注意是: spring-boot-starter-web重点

server:
  port: 5050 #gateway监听端口
spring:
  cloud:
    #配置网关
    #http://localhost:5050/api/commodity/brand/list
    #http://www.hspliving.com/api/commodity/brand/list
    gateway:
      routes: #配置路由,可以有多个路由
        - id: rainbowsealiving_renren_fast_route # 路由id, 由程序员指定,保证唯一
            # 当前配置完成的需求说明:
            # 如果到网关的请求时 http://localhost:5050/commodity/brand/list ,gateway 通过断言。
            # 最终将请求路由转发到 http://localhost:9090/commodity/brand/list = >url=uri+path
          uri: lb://renren-fast
          predicates:
            - Path=/api/** #断言,路径相匹配的进行路由
#        - id: member_routh01 # 路由id, 由程序员指定,保证唯一
#          # 当前配置完成的需求说明:
#          # 如果到网关的请求时 http://localhost:5050/commodity/brand/list ,gateway 通过断言。
#          # 最终将请求路由转发到 http://localhost:9090/commodity/brand/list = >url=uri+path
#          uri: http://localhost:9090
#          predicates:
#            - Path=/commodity/brand/list #断言,路径相匹配的进行路由
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #配置nacos地址
  application:
    name: rainbowsealiving-gateway
server:
  port: 5050 #gateway监听端口
spring:
  cloud:
    #配置网关
    #http://localhost:5050/api/commodity/brand/list
    #http://www.hspliving.com/api/commodity/brand/list
    gateway:
      routes: #配置路由,可以有多个路由
        - id: rainbowsealiving_renren_fast_route # 路由id, 由程序员指定,保证唯一
            # 当前配置完成的需求说明:
            # 如果到网关的请求时 http://localhost:5050/api/???/??? ,gateway 通过断言。
            # 最终将请求路由转发到 http://renren-fast [注册到 nacosd  renren-fast 服务ip+端口] = >url=uri+path
          uri: lb://renren-fast
          predicates:
            - Path=/api/** #断言,路径相匹配的进行路由
server:
  port: 5050 #gateway监听端口
spring:
  cloud:
    #配置网关
    #http://localhost:5050/api/commodity/brand/list
    #http://www.hspliving.com/api/commodity/brand/list
    gateway:
      routes: #配置路由,可以有多个路由
        - id: rainbowsealiving_renren_fast_route # 路由id, 由程序员指定,保证唯一
            # 当前配置完成的需求说明:
            # 如果到网关的请求时 http://localhost:5050/api/???/??? ,gateway 通过断言。
            # 最终将请求路由转发到 http://renren-fast [注册到 nacosd  renren-fast 服务ip+端口] = >url=uri+path
          uri: lb://renren-fast
          predicates:
            - Path=/api/** #断言,路径相匹配的进行路由
#        - id: member_routh01 # 路由id, 由程序员指定,保证唯一
#          # 当前配置完成的需求说明:
#          # 如果到网关的请求时 http://localhost:5050/commodity/brand/list ,gateway 通过断言。
#          # 最终将请求路由转发到 http://localhost:9090/commodity/brand/list = >url=uri+path
#          uri: http://localhost:9090
#          predicates:
#            - Path=/commodity/brand/list #断言,路径相匹配的进行路由
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #配置nacos地址
  application:
    name: rainbowsealiving-gateway

路径重定向,替换重改- segment

server:
  port: 5050 #gateway监听端口
spring:
  cloud:
    #配置网关
    #http://localhost:5050/api/commodity/brand/list
    #http://www.hspliving.com/api/commodity/brand/list
    gateway:
      routes: #配置路由,可以有多个路由
        - id: rainbowsealiving_renren_fast_route # 路由id, 由程序员指定,保证唯一
            # 当前配置完成的需求说明:
            # 如果到网关的请求时 http://localhost:5050/api/???/??? ,gateway 通过断言。
            # 最终将请求路由转发到 http://renren-fast [注册到 nacosd  renren-fast 服务ip+端口]/????? = >url=uri+path
            # 因为我们要去掉断言到 Path的/api ,所以这里我们需要使用上路径重写。
          uri: lb://renren-fast
          predicates:
            - Path=/api/** #断言,路径相匹配的进行路由
          filters:
            - RewritePath=/api/(?<segment>.*), /renren-fast/$\{segment}
#        - id: member_routh01 # 路由id, 由程序员指定,保证唯一
#          # 当前配置完成的需求说明:
#          # 如果到网关的请求时 http://localhost:5050/commodity/brand/list ,gateway 通过断言。
#          # 最终将请求路由转发到 http://localhost:9090/commodity/brand/list = >url=uri+path
#          uri: http://localhost:9090
#          predicates:
#            - Path=/commodity/brand/list #断言,路径相匹配的进行路由
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #配置nacos地址
  application:
    name: rainbowsealiving-gateway

server:
  port: 5050 #gateway监听端口
spring:
  cloud:
    #配置网关
    #http://localhost:5050/api/commodity/brand/list
    #http://www.hspliving.com/api/commodity/brand/list
    gateway:
      routes: #配置路由,可以有多个路由
        - id: rainbowsealiving_renren_fast_route # 路由id, 由程序员指定,保证唯一
            # 当前配置完成的需求说明:
            # 如果到网关的请求时 http://localhost:5050/api/???/??? ,gateway 通过断言。
            # 最终将请求路由转发到 http://renren-fast [注册到 nacosd  renren-fast 服务ip+端口]/????? = >url=uri+path
            # 因为我们要去掉断言到 Path的/api ,所以这里我们需要使用上路径重写。
          uri: lb://renren-fast
          predicates:
            - Path=/api/** #断言,路径相匹配的进行路由
          filters:
            - RewritePath=/api/(?<segment>.*), /renren-fast/$\{segment}
#        - id: member_routh01 # 路由id, 由程序员指定,保证唯一
#          # 当前配置完成的需求说明:
#          # 如果到网关的请求时 http://localhost:5050/commodity/brand/list ,gateway 通过断言。
#          # 最终将请求路由转发到 http://localhost:9090/commodity/brand/list = >url=uri+path
#          uri: http://localhost:9090
#          predicates:
#            - Path=/commodity/brand/list #断言,路径相匹配的进行路由
        - id: rainbowSealiving_commodity_route # 路由id, 由程序员指定,保证唯一
            # 当前配置完成的需求说明:
            # 如果到网关的请求时 http://localhost:5050/api/commodity/???/??? ,gateway 通过断言。
            # 最终将请求路由转发到 http://rainbowSealiving-commodity [注册到 nacosd  renren-fast 服务ip+端口]/????? = >url=uri+path
            # 因为我们要去掉断言到 Path的/api ,所以这里我们需要使用上路径重写。
          uri: lb://rainbowSealiving-commodity
          predicates:
            - Path=/api/commodity/** #断言,路径相匹配的进行路由
          filters:
              - RewritePath=/api/(?<segment>.*), /renren-fast/$\{segment}
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #配置nacos地址
  application:
    name: rainbowsealiving-gateway

GateWay 网关的跨域问题

使用之前的 config ,配置的 WEbMvcConfig 不行了,而且 GateWay 不是一个 Web 项目,引入 Web 项目反而会报错。

GateWay 5050 端口访问 ——> 9090 端口跨域问题

9090 ——》阿里云跨域问题

同理,在 config 路径下配置一个跨域处理

package com.rainbowsea.rainbowsealiving.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

public class RainbowsealivingGatewayCorsConfiguration {
    @Bean
    public CorsWebFilter corsWebFilter(){
        System.out.println("enter....");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //1、配置跨域
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.setAllowCredentials(true);
        source.registerCorsConfiguration("/**",corsConfiguration);
        return new CorsWebFilter(source);
    }

}

同时注意:

server:
  port: 5050 #gateway监听端口
spring:
  cloud:
    #配置网关
    #http://localhost:5050/api/commodity/brand/list
    #http://www.hspliving.com/api/commodity/brand/list
    gateway:
      routes: #配置路由,可以有多个路由
#        - id: member_routh01 # 路由id, 由程序员指定,保证唯一
#          # 当前配置完成的需求说明:
#          # 如果到网关的请求时 http://localhost:5050/commodity/brand/list ,gateway 通过断言。
#          # 最终将请求路由转发到 http://localhost:9090/commodity/brand/list = >url=uri+path
#          uri: http://localhost:9090
#          predicates:
#            - Path=/commodity/brand/list #断言,路径相匹配的进行路由
        - id: raibnowsealiving_service_route # 路由id, 由程序员指定,保证唯一
            # 当前配置完成的需求说明:
            # 如果到网关的请求时 http://localhost:5050/api/service/???/??? ,gateway 通过断言。
            # 最终将请求路由转发到 http://rainbowSealiving-service [注册到 nacosd  renren-fast 服务ip+端口]/????? = >url=uri+path
            # 因为我们要去掉断言到 Path的/api ,所以这里我们需要使用上路径重写。
          uri: lb://raibnowsealiving-service
          predicates:
            - Path=/api/service/** #断言,路径相匹配的进行路由
          filters:
            # 也就是通过路径重写,最终的url 就是 http://localhost:7070
            - RewritePath=/api/service/(?<segment>.*), /$\{segment}
        - id: rainbowSealiving_commodity_route # 路由id, 由程序员指定,保证唯一
            # 当前配置完成的需求说明:
            # 如果到网关的请求时 http://localhost:5050/api/commodity/list/tree ,gateway 通过断言。
            # 最终将请求路由转发到 http://rainbowSealiving-commodity [注册到 nacosd  renren-fast 服务ip+端口]/????? = >url=uri+path
            # 因为我们要去掉断言到 Path的/api ,所以这里我们需要使用上路径重写。
            # 说明: /api/commodity/是一个更加精确的路径,必须将这组路由放在 /api/这里上
            # 否则会报错
          uri: lb://rainbowSealiving-commodity
          predicates:
            - Path=/api/commodity/** #断言,路径相匹配的进行路由
          filters:
            # 也就是通过路径重写,最终的url 就是 http://localhost:9090
            - RewritePath=/api/(?<segment>.*), /$\{segment}
        - id: rainbowsealiving_renren_fast_route # 路由id, 由程序员指定,保证唯一
            # 当前配置完成的需求说明:
            # 如果到网关的请求时 http://localhost:5050/api/???/??? ,gateway 通过断言。
            # 最终将请求路由转发到 http://renren-fast [注册到 nacosd  renren-fast 服务ip+端口]/????? = >url=uri+path
            # 因为我们要去掉断言到 Path的/api ,所以这里我们需要使用上路径重写。
          uri: lb://renren-fast
          predicates:
            - Path=/api/** #断言,路径相匹配的进行路由
          filters:
            # 也就是通过路径重写,最终的url 就是 http://localhost:8090
            - RewritePath=/api/(?<segment>.*), /renren-fast/$\{segment}
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #配置nacos地址
  application:
    name: rainbowsealiving-gateway

方案一


<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  <version>2.1.0.RELEASE</version>
</dependency>

<!--
引入 oss starter 我们引入的 stater 和 文档给的不一样,
请注意观察 artifactId ,小伙伴要和写的保持一致
老师说明: 因为我们在该 pom.xml 文件中有 dependencyManagement 指定了 spring-cloud-aliba
版本 2.1.0.RELEASE 因此这里,我们可以不写 version 而是使用版本仲裁
-->
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
  <!--            <version>2.1.0.RELEASE</version>-->
</dependency>

    <dependencies>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.1.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!--
                引入 oss starter 我们引入的 stater 和 文档给的不一样,
                请注意观察 artifactId ,小伙伴要和写的保持一致
                    老师说明: 因为我们在该 pom.xml 文件中有 dependencyManagement 指定了 spring-cloud-aliba
                    版本 2.1.0.RELEASE 因此这里,我们可以不写 version 而是使用版本仲裁
        -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
    </dependencies>
<?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.1.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.rainbowsea.RainbowSealiving</groupId>
    <artifactId>raibnowsealiving-service</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>raibnowsealiving-service</name>
    <description>顺平( 家居生活)- 第三方服务模块 OSS</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>2020.0.5</spring-cloud.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.1.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!--
                引入 oss starter 我们引入的 stater 和 文档给的不一样,
                请注意观察 artifactId ,小伙伴要和写的保持一致
                    老师说明: 因为我们在该 pom.xml 文件中有 dependencyManagement 指定了 spring-cloud-aliba
                    版本 2.1.0.RELEASE 因此这里,我们可以不写 version 而是使用版本仲裁
        -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <!--        引入公共模块,排除 mybatis-plus -->
        <dependency>
            <groupId>com.rainbowsea.RainbowSealiving</groupId>
            <artifactId>RainbowSealiving-common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <!--            排除公共模块当中的 mybatis-plus-boot-starter 依赖-->
            <exclusions>
                <exclusion>
                    <groupId>com.baomidou</groupId>
                    <artifactId>mybatis-plus-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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>

方案二:

在 Nacos 配置中心按以前讲解的方式创建命名空间, dataId 和组并将配置信息放在Nacos ,具体如图。

在 resources 下创建一个 bootstrap.properties 用于获取/访问 Nacos 当中的配置信息,也可以用 yml

#注册到 nacos的名字
spring.application.name=rainbowsealiving-service
#指定 nacos的发现注册地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#指定 nacos的配置地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
#要获取的配置文件所在的配置空间
spring.cloud.nacos.config.namespace=73bded0a-1c06-4292-a8ff-e5b177114551
#配置空间的哪一个组,这个组下可以有多个配置文件,通过 ext-config[?]来指定要加载某空间下的某组的第几个文件
spring.cloud.nacos.config.group=dev
#通过 ext-config[?]来指定要加载某空间下的某组的第几个文件
# 和指定 data-id 和是否实时刷新的配置
spring.cloud.nacos.config.ext-config[0].data-id=rainbowsealiving-service.yml
spring.cloud.nacos.config.ext-config[0].group=dev
spring.cloud.nacos.config.ext-config[0].refresh=true

注意这里配置的 pom.xml 的相关的依赖

 <dependencies>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.1.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!--
                引入 oss starter 我们引入的 stater 和 文档给的不一样,
                请注意观察 artifactId ,小伙伴要和写的保持一致
                    老师说明: 因为我们在该 pom.xml 文件中有 dependencyManagement 指定了 spring-cloud-aliba
                    版本 2.1.0.RELEASE 因此这里,我们可以不写 version 而是使用版本仲裁
        -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-config</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
    </dependencies>
<?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.1.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.rainbowsea.RainbowSealiving</groupId>
    <artifactId>raibnowsealiving-service</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>raibnowsealiving-service</name>
    <description>顺平( 家居生活)- 第三方服务模块 OSS</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>2020.0.5</spring-cloud.version>
    </properties>

    <dependencies>



        <!--
            通过回顾,我们指定,如果该服务需要去拉取nacos配置中心的配置, 需要加入
            spring-cloud-starter-alibaba-nacos-config [融汇贯通]
            这里,我们使用版本仲裁,来指定version
        -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <!--引入 oss starter 我们引入的stater 和文档给的不一样,
        请注意观察artifactId , 小伙伴要和老师写的保持一致
            老师说明: 因为我们在该pom.xml文件中有 dependencyManagement 指定了 spring-cloud-alibaba-dependencies
            版本 2.1.0.RELEASE, 因此这里,我们可以不写version 而是使用版本仲裁
        -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
            <!--<version>2.1.0.RELEASE</version>-->
        </dependency>

        <!--        引入公共模块,排除 mybatis-plus -->
        <dependency>
            <groupId>com.rainbowsea.RainbowSealiving</groupId>
            <artifactId>RainbowSealiving-common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <!--            排除公共模块当中的 mybatis-plus-boot-starter 依赖-->
            <exclusions>
                <exclusion>
                    <groupId>com.baomidou</groupId>
                    <artifactId>mybatis-plus-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!--
         1. 这里老师想回顾使用dependencyManagement 在进行版本控制
         2. 老韩再强调一下dependencyManagement 用于指定依赖版本,
             但是本身并不引入相关依赖
   -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <!--
                    老师解读:
                    1. type: pom  和 scope import 配合使用
                    2. 表示 在这个项目的子模块和当前这个模块,
                       在引入spring-cloud-alibaba相关依赖时 锁定版本为2.1.0.RELEASE
                    3. 通过 pom + import 解决maven单继承机制
                 -->
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

通过 @Value 注解的方式,获取到 Nacos 当中的配置,再赋值到对应相等内容上。



import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.rainbowsea.common.utils.R;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

@RestController
public class OssServiceController {
    // 装配属性
    @Resource
    OSS ossClient;

    @Value("${spring.cloud.alicloud.access-key}")
    private String accessId;


    @Value("${spring.cloud.alicloud.oss.endpoint}")
    private String endpoint;


    @Value("${spring.cloud.alicloud.oss.bucket}")
    private String bucket;

}
package com.rainbowsea.rainbowsealiving.service.controller;


import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.rainbowsea.common.utils.R;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

@RestController
public class OssServiceController {
    // 装配属性
    @Resource
    OSS ossClient;

    @Value("${spring.cloud.alicloud.access-key}")
    private String accessId;


    @Value("${spring.cloud.alicloud.oss.endpoint}")
    private String endpoint;


    @Value("${spring.cloud.alicloud.oss.bucket}")
    private String bucket;


    @RequestMapping("/oss/policy")
    public R policy() {

        String host = "https://" + bucket + "." + endpoint;
        // host的 格 式 为 // bucketname.endpoint
        // callbackUrl为 上传回调服务器的 URL,请将下面的 IP和 Port配置为您自己的真实信息。暂时不用
        // String callbackUrl = "http://88.88.88.88:8888";
        // 我们可以将文件按照 年-月-日的形式分目录存放在阿里云[以后优化]
        // 得到 dir
        // java 基础的日期 -SimpleDateFormat
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dir = format + "/"; //用户上传文件时指定的前缀。
        Map<String, String> respMap = null;
        try {
            long expireTime = 30;  // 默认超时时间 30s
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0,
                    1048576000);
            policyConds.addConditionItem(MatchMode.StartWith,
                    PolicyConditions.COND_KEY, dir);
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);
            respMap = new LinkedHashMap<String, String>();
            respMap.put("accessid", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            // respMap.put("expire", formatISO8601Date(expiration));
        } catch (Exception e) {
            // Assert.fail(e.getMessage());
            System.out.println(e.getMessage());
        }
        return R.ok().put("data", respMap);
    }

}

阿里云 key

用户登录名称 rainbowsealiving-10000@1562236733667461.onaliyun.com
AccessKey ID LTAI5tP4G6hDJqh7FPe1Cahh
AccessKey Secret vl5kaBORH1QADEzKq9NInpRdD8JJeF
LTAI5tP4G6hDJqh7FPe1Cahh
vl5kaBORH1QADEzKq9NInpRdD8JJeF
用户登录名称 rainbowsealiving-10000@1562236733667461.onaliyun.com
AccessKey ID LTAI5tP4G6hDJqh7FPe1Cahh
AccessKey Secret vl5kaBORH1QADEzKq9NInpRdD8JJeF

后端校验器

防止,用户走后端,比如使用 Postman 进行访问,登录时候。

使用 JSR 303 校验

JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现

package com.rainbowsea.rainbowsealiving.commodity.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import org.hibernate.validator.constraints.URL;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

/**
 * 家居品牌
 * 
 * @author rainbowsea
 * @email rainbowsea@gmail.com
 * @date 2025-03-08 20:11:04
 */
@Data
@TableName("commodity_brand")
public class BrandEntity implements Serializable {
	private static final long serialVersionUID = 2L;

	/**
	 * id
	 */
	@TableId
	private Long id;
	/**
	 * 品牌名
	 * 1. @NotBlank 表示 name 必须包括一个非空字符
	 * 2. message = "品牌名不能为空" 是老师指定一个校验消息
	 * 3. 如果没有指定 message = "品牌名不能为空",就会返回默认的校验信息 key = javax.validation.constion
	 * 4. 这个默认的消息是在 ValidationMessages_zh_CN.properties 文件配置javax.validation.constran
	 * 5. @NotBlank 可以用于 CharSequence
	 */

	@NotBlank(message = "品牌名不能为空")
	private String name;
	/**
	 * logo 因为这个 Logo 对应的是图片的 url
	 * 1.@NotBlank 和 @URL 组合去校验 logo
	 */
	@NotBlank(message = "logo 不能为空")
	@URL(message = "logo 不是一个合法的 URL ")
	private String logo;
	/**
	 * 说明
	 */
	private String description;
	/**
	 * 显示,isshow 后面的 s 是小写
	 * 1. 这里我们使用的注解是(@NotNull,他可以接收任意类型)
	 * 2. 如果这里使用 @NotBlank,会报错,因为 @NotBlank 不支持 Integer
	 * 3. 大家在开发时,需要知道注解可以用在哪些类型上,可以查看注解源码
	 * 4. 说明: 假如 isshow 规定时 0 / 1,这时我们后面通过自定义约束来解决
	 * 5. 如果是 String 类型,可以直接使用@Pattern 来进一步校验。
	 */
	@NotNull(message = "显示状态不能为空")
	private Integer isshow;
	/**
	 * 检索首字母 a-z, A-Z
	 * 因为 firstLetter 是 String 可以直接使用 @Pattern
	 */

	@NotBlank(message = "检索首字母不能为空")
	@Pattern(regexp = "^[a-zA-Z]$",message = "检索首字母必须是 a-z 或者 A-Z")
	private String firstLetter;
	/**
	 * 排序
	 */
	@NotNull(message = "排序值不能为空")
	@Min(value = 0,message = "排序值要求大于等于 0 ")
	private Integer sort;

}

/**
     * 保存
     * 说明:
     * 1. @Validated 注解的作用就是启用 BrandEntity 字段校验
     * 2. 注解如果没有写 @Validated 这个校验规则不生效
     * 3. BindingResult result: springboot 会将校验的错误放入到 result
     * 4. 程序员可以通过 BindingResult result 将校验得到错误取出,然后进行相应处理
     */
    @RequestMapping("/save")
    //@RequiresPermissions("commodity:brand:save")
    public R save(@Validated  @RequestBody BrandEntity brand, BindingResult result){

		// 先创建一个 Map,用于收集校验错误
        Map<String,String> map = new HashMap<>();

        if (result.hasErrors()) {  // 如果有校验错误
            // 遍历 result ,将错误信息收集到 map
            result.getFieldErrors().forEach((item) ->{
                // 得到 field
                String field = item.getField();
                // 得到校验错误信息
                String message = item.getDefaultMessage();
                // 放入 map
                map.put(field,message);
            });

            return R.error(400,"品牌表单数据不合法").put("data",map);
        } else { // 如果没有校验错误,入库
            brandService.save(brand);
            return R.ok();
        }
        
    }

全局异常处理

我们可以使用@ControllerAdvice 统一管理异常/错误

package com.rainbowsea.rainbowsealiving.commodity.exception;


import com.rainbowsea.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;


/**
 * 说明:
 * @ResponseBody : 表示以 json 格式返回数据
 * @Slf4j 可以输出日志,便于数据
 * @ControllerAdvice(basePackages = "com.rainbowsea.rainbowsealiving.commodity.controller")
 *   表示统一接管 com.rainbowsea.rainbowsealiving.commodity.controller 这个路径包下的
 *   抛出了的数据校验的异常,就由  @ExceptionHandler(value = MethodArgumentNotValidException.class)
 *   处理
 */
@Slf4j
@ResponseBody
@ControllerAdvice(basePackages = "com.rainbowsea.rainbowsealiving.commodity.controller")
public class RainbowSealivingExceptionControllerAdvice {


    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R handleValidException(MethodArgumentNotValidException e) {

        log.error(" 数据校验出现问题{},异常类型:{}",e.getMessage(),e.getClass());
        BindingResult bindingResult = e.getBindingResult();

        Map<String, String> errorMap = new HashMap<>();
        bindingResult.getFieldErrors().forEach((fieldError) -> {
            errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
        });
        return R.error(400, " 方法参数异常").put("data", errorMap);
    }

    /**
     *
     这里再写一个处理 Throwable类型的异常的方法,没有精确匹配到的异常,走这里
     */
    @ExceptionHandler(value = Throwable.class)
    public R handleException(Throwable throwable){
        return R.error(40000," 系统未知错误");
    }
}

/**
     * 保存
     * 说明:
     * 1. @Validated 注解的作用就是启用 BrandEntity 字段校验
     * 2. 注解如果没有写 @Validated 这个校验规则不生效
     * 3. BindingResult result: springboot 会将校验的错误放入到 result
     * 4. 程序员可以通过 BindingResult result 将校验得到错误取出,然后进行相应处理
     * 5.如果使用@ControllerAdvice统一接管异常,就不用单独封装返回异常信息了,将其注释
     * 6.异常会统一抛出给@ControllerAdvice类
     */
    @RequestMapping("/save")
    //@RequiresPermissions("commodity:brand:save")
    public R save(@Validated  @RequestBody BrandEntity brand, BindingResult result){

		// 先创建一个 Map,用于收集校验错误
        //Map<String,String> map = new HashMap<>();
        //
        //if (result.hasErrors()) {  // 如果有校验错误
        //    // 遍历 result ,将错误信息收集到 map
        //    result.getFieldErrors().forEach((item) ->{
        //        // 得到 field
        //        String field = item.getField();
        //        // 得到校验错误信息
        //        String message = item.getDefaultMessage();
        //        // 放入 map
        //        map.put(field,message);
        //    });
        //
        //    return R.error(400,"品牌表单数据不合法").put("data",map);
        / 
温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信