Java17 --- SpringCloud之Gateway

news2024/12/25 13:07:48

目录

一、Gateway网关创建

1.1、创建微服务子工程9527及配置和依赖

1.1.1、pom依赖

1.1.2、yml配置

1.1.3、主启动类并测试入驻consul 

二、实现路由映射 

2.1、服务8001新增测试代码 

2.2、修改9527服务yml配置文件 

2.3、远程调用接口加gateway

2.3.1、新增80服务测试代码 

三、路由以微服务名动态获取服务URL 

3.1、修改9527服务yml文件 

四、断言 

4.1、常用断言api的yml配置 

4.1.1、时间范围访问设置

4.1.2、cookie访问

4.1.3、X-Request-Id访问

4.1.4、Host访问

4.1.5、Query访问 

 4.1.6、RemoteAddr访问

 4.1.7、Method访问

4.2、自定义断言 

五、过滤器 

5.1、常用内置过滤器 

5.1.1、请求头添加、修改、删除

5.1.2、请求参数删除和添加 

5.1.3、回应头添加、修改、删除 

 5.1.4、前缀和路径相关

5.2、自定义过滤器 

5.2.1、自定义全局过滤器 

5.2.2、自定义条件过滤器 


一、Gateway网关创建

核心功能:反向代理、鉴权、流量控制、熔断、监控日志

三大核心:路由(route)、断言(predicate)、过滤(filter)

工作流程核心逻辑:路由转发-》断言判断-》执行过滤链

1.1、创建微服务子工程9527及配置和依赖

1.1.1、pom依赖

<dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--服务注册发现consul discovery,网关也要注册进服务注册中心统一管控-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!-- 指标监控健康检查的actuator,网关是响应式编程删除掉spring-boot-starter-web dependency-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

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

1.1.2、yml配置

server:
  port: 9527

spring:
  application:
    name: cloud-gateway #以微服务注册进consul或nacos服务列表内
  cloud:
    consul: #配置consul地址
      host: localhost
      port: 8500
      discovery:
        prefer-ip-address: true
        service-name: ${spring.application.name}

1.1.3、主启动类并测试入驻consul 

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

二、实现路由映射 

2.1、服务8001新增测试代码 

@RestController
public class PayGateWayController {
    @Resource
    private PayService payService;

    @GetMapping(value = "/pay/gateway/get/{id}")
    public ResultData<Pay> getById(@PathVariable("id") Integer id)
    {
        Pay pay = payService.getById(id);
        return ResultData.success(pay);
    }

    @GetMapping(value = "/pay/gateway/info")
    public ResultData<String> getGatewayInfo()
    {
        return ResultData.success("gateway info test:"+ IdUtil.simpleUUID());
    }
}

 

2.2、修改9527服务yml配置文件 

server:
  port: 9527

spring:
  application:
    name: cloud-gateway #以微服务注册进consul或nacos服务列表内
  cloud:
    consul: #配置consul地址
      host: localhost
      port: 8500
      discovery:
        prefer-ip-address: true
        service-name: ${spring.application.name}
    gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由

 结果:

2.3、远程调用接口加gateway

/**
     * GateWay进行网关测试案例01
     * @param id
     * @return
     */
    @GetMapping(value = "/pay/gateway/get/{id}")
    public ResultData getById(@PathVariable("id") Integer id);

    /**
     * GateWay进行网关测试案例02
     * @return
     */
    @GetMapping(value = "/pay/gateway/info")
    public ResultData<String> getGatewayInfo();

2.3.1、新增80服务测试代码 

@RestController
public class OrderGateWayController {
    @Resource
    private PayFeignApi payFeignApi;

    @GetMapping(value = "/feign/pay/gateway/get/{id}")
    public ResultData getById(@PathVariable("id") Integer id)
    {
        return payFeignApi.getById(id);
    }

    @GetMapping(value = "/feign/pay/gateway/info")
    public ResultData<String> getGatewayInfo()
    {
        return payFeignApi.getGatewayInfo();
    }
}

 

三、路由以微服务名动态获取服务URL 

3.1、修改9527服务yml文件 

gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由


        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由

四、断言 

4.1、常用断言api的yml配置 

4.1.1、时间范围访问设置

    gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
#            - After=2024-05-04T23:53:30.106114600+08:00[Asia/Shanghai] #在此时间之后访问
#            - Before=2024-05-04T23:56:30.106114600+08:00[Asia/Shanghai] #在此时间之前访问
#            - Between=2024-05-04T23:57:30.106114600+08:00[Asia/Shanghai],2024-05-05T00:59:30.106114600+08:00[Asia/Shanghai]

4.1.2、cookie访问

    gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
#            - After=2024-05-04T23:53:30.106114600+08:00[Asia/Shanghai] #在此时间之后访问
#            - Before=2024-05-04T23:56:30.106114600+08:00[Asia/Shanghai] #在此时间之前访问
#            - Between=2024-05-04T23:57:30.106114600+08:00[Asia/Shanghai],2024-05-05T00:59:30.106114600+08:00[Asia/Shanghai]
#            - Cookie=username,cjc #必须要携带cookie才能访问

 测试1:原生命令访问

测试2:使用postman访问

测试3:使用浏览器访问

 

4.1.3、X-Request-Id访问

    gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
#            - After=2024-05-04T23:53:30.106114600+08:00[Asia/Shanghai] #在此时间之后访问
#            - Before=2024-05-04T23:56:30.106114600+08:00[Asia/Shanghai] #在此时间之前访问
#            - Between=2024-05-04T23:57:30.106114600+08:00[Asia/Shanghai],2024-05-05T00:59:30.106114600+08:00[Asia/Shanghai]
#            - Cookie=username,cjc #必须要携带cookie才能访问
            - Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数

 

4.1.4、Host访问

    gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
#            - After=2024-05-04T23:53:30.106114600+08:00[Asia/Shanghai] #在此时间之后访问
#            - Before=2024-05-04T23:56:30.106114600+08:00[Asia/Shanghai] #在此时间之前访问
#            - Between=2024-05-04T23:57:30.106114600+08:00[Asia/Shanghai],2024-05-05T00:59:30.106114600+08:00[Asia/Shanghai]
#            - Cookie=username,cjc #必须要携带cookie才能访问
#            - Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数
            - Host=**.cjc.com

 

4.1.5、Query访问 

    gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
#            - After=2024-05-04T23:53:30.106114600+08:00[Asia/Shanghai] #在此时间之后访问
#            - Before=2024-05-04T23:56:30.106114600+08:00[Asia/Shanghai] #在此时间之前访问
#            - Between=2024-05-04T23:57:30.106114600+08:00[Asia/Shanghai],2024-05-05T00:59:30.106114600+08:00[Asia/Shanghai]
#            - Cookie=username,cjc #必须要携带cookie才能访问
#            - Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数
#            - Host=**.cjc.com
            - Query=username, \d+  # 要有参数名username并且值还要是整数才能路由

 

 4.1.6、RemoteAddr访问

    gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
#            - After=2024-05-04T23:53:30.106114600+08:00[Asia/Shanghai] #在此时间之后访问
#            - Before=2024-05-04T23:56:30.106114600+08:00[Asia/Shanghai] #在此时间之前访问
#            - Between=2024-05-04T23:57:30.106114600+08:00[Asia/Shanghai],2024-05-05T00:59:30.106114600+08:00[Asia/Shanghai]
#            - Cookie=username,cjc #必须要携带cookie才能访问
#            - Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数
#            - Host=**.cjc.com
#            - Query=username, \d+  # 要有参数名username并且值还要是整数才能路由
            - RemoteAddr=192.168.200.1/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。

 4.1.7、Method访问

    gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
#            - After=2024-05-04T23:53:30.106114600+08:00[Asia/Shanghai] #在此时间之后访问
#            - Before=2024-05-04T23:56:30.106114600+08:00[Asia/Shanghai] #在此时间之前访问
#            - Between=2024-05-04T23:57:30.106114600+08:00[Asia/Shanghai],2024-05-05T00:59:30.106114600+08:00[Asia/Shanghai]
#            - Cookie=username,cjc #必须要携带cookie才能访问
#            - Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数
#            - Host=**.cjc.com
#            - Query=username, \d+  # 要有参数名username并且值还要是整数才能路由
            - RemoteAddr=192.168.200.1/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。
            - Method=Put

4.2、自定义断言 

测试代码

@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {

    public MyRoutePredicateFactory(){
        super(MyRoutePredicateFactory.Config.class);
    }
    //断言规则
    @Validated
    public static class Config{
        @Getter@Setter@NotEmpty
        private String userType;
    }
   //重写支持短格式
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("userType");
    }

    @Override
    public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
        return new Predicate<ServerWebExchange>() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                //检查request的参数里面,userType是否为指定的值,符合配置就通过
                String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
               //如果说参数存在,就和config的数据进行比较
                if (userType.equalsIgnoreCase(config.getUserType())) {
                    return true;
                } else if (userType == null) {
                    return false;
                }
                return false;
            }
        };
    }
}

配置yml文件

    gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
#            - After=2024-05-04T23:53:30.106114600+08:00[Asia/Shanghai] #在此时间之后访问
#            - Before=2024-05-04T23:56:30.106114600+08:00[Asia/Shanghai] #在此时间之前访问
#            - Between=2024-05-04T23:57:30.106114600+08:00[Asia/Shanghai],2024-05-05T00:59:30.106114600+08:00[Asia/Shanghai]
#            - Cookie=username,cjc #必须要携带cookie才能访问
#            - Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数
#            - Host=**.cjc.com
#            - Query=username, \d+  # 要有参数名username并且值还要是整数才能路由
#            - RemoteAddr=192.168.200.1/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。
#            - Method=Put
            - My=diamond
#            - name: My  #全面支持
#              args:
#                userType: diamond

 

五、过滤器 

5.1、常用内置过滤器 

5.1.1、请求头添加、修改、删除

修改9527yml配置文件

    gateway:
      routes:
        - id: pay_routh1 #pay_routh1                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/get/**              # 断言,路径相匹配的进行路由
#            - After=2024-05-04T23:53:30.106114600+08:00[Asia/Shanghai] #在此时间之后访问
#            - Before=2024-05-04T23:56:30.106114600+08:00[Asia/Shanghai] #在此时间之前访问
#            - Between=2024-05-04T23:57:30.106114600+08:00[Asia/Shanghai],2024-05-05T00:59:30.106114600+08:00[Asia/Shanghai]
#            - Cookie=username,cjc #必须要携带cookie才能访问
#            - Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数
#            - Host=**.cjc.com
#            - Query=username, \d+  # 要有参数名username并且值还要是整数才能路由
#            - RemoteAddr=192.168.200.1/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。
#            - Method=Put
            - My=diamond
#            - name: My  #全面支持
#              args:
#                userType: diamond

        - id: pay_routh2 #pay_routh2                #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001                #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/pay/gateway/info/**              # 断言,路径相匹配的进行路由

        - id: pay_routh3 #pay_routh3
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由
          filters:
            - AddRequestHeader=X-Request-cjc1,cjcValue1  # 请求头kv,若一头含有多参则重写一行设置
            - AddRequestHeader=X-Request-cjc2,cjcValue2
            - RemoveRequestHeader=cache-control      # 删除请求头cache-control
            - SetRequestHeader=x-forwarded-host, yyyy # 将请求头x-forwarded-host对应的值修改为yyyy

8001测试代码

@GetMapping(value = "/pay/gateway/filter")
    public ResultData<String> getGatewayFilter(HttpServletRequest request)
    {
        String result = "";
        Enumeration<String> headers = request.getHeaderNames();
        while(headers.hasMoreElements())
        {
            String headName = headers.nextElement();
            String headValue = request.getHeader(headName);
            System.out.println("请求头名: " + headName +"\t\t\t"+"请求头值: " + headValue);
            if(headName.equalsIgnoreCase("X-Request-cjc1")
                    || headName.equalsIgnoreCase("X-Request-cjc2")) {
                result = result+headName + "\t " + headValue +" ";
            }
        }
        return ResultData.success("getGatewayFilter 过滤器 test: "+result+" \t "+ DateUtil.now());
    }

5.1.2、请求参数删除和添加 

- id: pay_routh3 #pay_routh3
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由
          filters:
            - AddRequestHeader=X-Request-cjc1,cjcValue1  # 请求头kv,若一头含有多参则重写一行设置
            - AddRequestHeader=X-Request-cjc2,cjcValue2
            - RemoveRequestHeader=cache-control      # 删除请求头cache-control
            - SetRequestHeader=x-forwarded-host, yyyy # 将请求头x-forwarded-host对应的值修改为yyyy
            - AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
            - RemoveRequestParameter=customerName   # 删除url请求参数customerName,你传递过来也是null

5.1.3、回应头添加、修改、删除 

- id: pay_routh3 #pay_routh3
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由
          filters:
            - AddRequestHeader=X-Request-cjc1,cjcValue1  # 请求头kv,若一头含有多参则重写一行设置
            - AddRequestHeader=X-Request-cjc2,cjcValue2
            - RemoveRequestHeader=cache-control      # 删除请求头cache-control
            - SetRequestHeader=x-forwarded-host, yyyy # 将请求头x-forwarded-host对应的值修改为yyyy
            - AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
            - RemoveRequestParameter=customerName   # 删除url请求参数customerName,你传递过来也是null
            - AddResponseHeader=X-Response-cjc, BlueResponse # 新增请求参数X-Response-cjc并设值为BlueResponse
            - SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
            - RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除

 5.1.4、前缀和路径相关

- id: pay_routh3 #pay_routh3
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由
#            - Path=/gateway/filter/**              # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
#            - Path=/XYZ/abc/{segment}           # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
          filters:
            - RedirectTo=302, http://www.baidu.com/ # 访问http://localhost:9527/pay/gateway/filter跳转到http://www.baidu.com/
#             - SetPath=/pay/gateway/{segment}  # {segment}表示占位符,你写abc也行但要上下一致
#            - PrefixPath=/pay # http://localhost:9527/pay/gateway/filter PrefixPath + Path

5.2、自定义过滤器 

5.2.1、自定义全局过滤器 

9527服务测试接口耗时代码

@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered {
    private static final String BEGIN_VISIT_TIME = "begin_visit_time";
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(BEGIN_VISIT_TIME, System.currentTimeMillis());
        return chain.filter(exchange).then(Mono.fromRunnable(()-> {
            Long bvtime = exchange.getAttribute(BEGIN_VISIT_TIME);
            if (bvtime != null){
                log.info("访问接口主机: " + exchange.getRequest().getURI().getHost());
                log.info("访问接口端口: " + exchange.getRequest().getURI().getPort());
                log.info("访问接口URL: " + exchange.getRequest().getURI().getPath());
                log.info("访问接口URL参数: " + exchange.getRequest().getURI().getRawQuery());
                log.info("访问接口时长: " + (System.currentTimeMillis() - bvtime) + "ms");
                log.info("我是美丽分割线: ###################################################");
                System.out.println();
            }
        }));
    }
    //数字越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

5.2.2、自定义条件过滤器 

9527服务测试代码

@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {
    public MyGatewayFilterFactory() {
        super(MyGatewayFilterFactory.Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("status");
    }

    @Override
    public GatewayFilter apply(MyGatewayFilterFactory.Config config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                ServerHttpRequest request = exchange.getRequest();
                if (request.getQueryParams().containsKey("cjc")){
                    return chain.filter(exchange);
                }else {
                    exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
                    return exchange.getResponse().setComplete();
                }
            }
        };
    }

    public static class Config{
        @Getter@Setter
        private String status;//设置一个状态标志
    }
}
      - id: pay_routh3 #pay_routh3
          uri: lb://cloud-payment-service                #匹配后提供服务的路由地址
          predicates:
            - Path=/pay/gateway/filter/**              # 断言,路径相匹配的进行路由
#            - Path=/gateway/filter/**              # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
#            - Path=/XYZ/abc/{segment}           # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
          filters:
            - My=cjc

 

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1643605.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Android学习】简单的登录页面和业务逻辑实现

实现功能 1 登录页&#xff1a;密码登录和验证码登录 2 忘记密码页&#xff1a;修改密码 3 页面基础逻辑 java代码 基础页面 XML login_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.and…

C++静态数组和C语言静态数组的区别( array,int a[])

目录 一、区别 1、越界读&#xff0c;检查不出来 2、越界写&#xff0c;抽查&#xff0c;可能检查不出来&#xff0c;有局限性 二、array缺点 一、区别 C语言的静态数组int a[]; 静态数组的越界检查不稳定的&#xff1a; 1、越界读&#xff0c;检查不出来 2、越界写&#x…

开发一款简易APP

希望打开APP后,显示当前时间..可能不实用,重在体验 安装Flutter 如果在arm架构的 Mac 电脑上进行开发&#xff0c;需要安装 Rosetta 2, 因为一些辅助工具需要&#xff0c;可通过手动运行下面的命令来安装&#xff1a; sudo softwareupdate --install-rosetta --agree-to-licens…

一篇文章带你深入了解“指针”

一篇文章带你深入了解“指针” 内存和地址了解指针指针类型const修饰指针指针的运算指针与整数之间的运算指针与指针之间的运算指针的关系运算 void* 指针传值调用和传址调用数组和指针的关系野指针野指针的形成原因规避野指针 二级指针字符指针指针数组数组指针数组传参一维数…

动态炫酷的新年烟花网页代码

烟花效果的实现可以采用前端技术&#xff0c;如HTML、CSS和JavaScript。通过结合动画、粒子效果等技术手段&#xff0c;可以创建出独特而炫目的烟花效果。同时&#xff0c;考虑到性能和兼容性&#xff0c;需要确保效果在各种设备上都能够良好运行。 效果显示http://www.bokequ.…

Transformer中的数据输入构造

文章目录 1. 文本内容2. 字典构造2.1 定义一个类用于字典构造2.2 拆分文本2.3 构造结果 3. 完整代码 1. 文本内容 假如我们有如下一段文本内容&#xff1a; Optics It is the branch of physics that studies the behaviour and properties of light . Optical Science 这段…

代码随想录Day 37|Leetcode|Python|● 1049. 最后一块石头的重量 II ● 494. 目标和 ● 474.一和零

1049. 最后一块石头的重量 II 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结…

Java web第五次作业

1.在idea中配置好数据源 2、视频案例中只给出了查询所有结果的示例&#xff0c;请自己完成添加、删除、修改操作的代码。以下供参 考。 Delete("delete from emp where id#{id}") public void delete(Integer id); 测试代码 Test public void testDelete(){ empMa…

AI产品经理需要懂的技术全景图

AI产品经理需要懂技术&#xff0c;以便与算法工程师同频沟通&#xff0c;以及合理管控AI项目进度。 项目掌握内容掌握边界数学统计学基础概念常见概念知道、了解模型构建 模型构建流程涉及角色每个角色工作内容清楚知道每个角色该做什么&#xff0c;需要花费多少成本&#xff…

使用python开发的词云图生成器2.0

使用python开发的词云图生成器2.0 更新部分词云图主要三方库工具介绍和效果工具界面&#xff1a; 代码 更新部分 1.支持选择字体&#xff1b; 2.支持选择词云图形状 词云图 词云图啊&#xff0c;简单来说&#xff0c;它可以把文本数据中的高频关键词变成不同大小、颜色的词汇…

「C/C++ 01」scanf()与回车滞留问题

目录 〇、scanf()接收用户输入的流程 一、回车的缓冲区滞留问题是什么&#xff1f; 二、为什么&#xff1f; 三、四个解决方法&#xff1a; 1. 在前面的scanf()中加上\n 2. 在scanf("%c")中添加空格 3. 使用getchar()来吸收回车 4. 使用fflush()清空缓冲区 〇、scan…

seata容器部署nacos注册配置中心、db存储实践记录

seata容器部署nacos注册&配置中心、db存储实践记录 说明seata容器初步部署(可跳过)seata初部署获取配置文件springboot简单集成seata测试 seata使用nacos注册中心、db存储环境准备准备nacos配置中心配置准备Mysql数据库 seata配置nacos注册中心准备docker-compose.yaml文件…

stm32单片机开发四、USART“串口通信“

串口的空闲状态时高电平&#xff0c;起始位是低电平&#xff0c;来打破空闲状态的高电平 必须要有停止位&#xff0c;停止位一般为一位高电平 串口常说的数据为8N1&#xff0c;其实就是8个数据位&#xff08;固定的&#xff09;&#xff0c;N就是none&#xff0c;也就是0个校验…

mfc140.dll丢失如何修复?分享各种mfc140.dll丢失的解决方法

在Windows操作系统的世界里&#xff0c;动态链接库&#xff08;Dynamic Link Library, DLL&#xff09;扮演着举足轻重的角色&#xff0c;它们是实现程序功能共享、减少内存占用、促进模块化编程的关键组件。MFC140.dll便是众多DLL文件中的一员&#xff0c;它与微软基础类库&am…

【kettle006】kettle访问华为openGauss高斯数据库并处理数据至execl文件(已更新)

1.一直以来想写下基于kettle的系列文章&#xff0c;作为较火的数据ETL工具&#xff0c;也是日常项目开发中常用的一款工具&#xff0c;最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下华为openGauss高斯数据库相关知识体系 3.欢迎批评指正&#xff0c;跪谢…

网络基础「HTTPS」

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f383;操作环境&#xff1a; CentOS 7.6 腾讯云远程服务器 文章目录 1.基本概念1.1.HTTP协议面临的问题1.2.加密与解密1.3.数字摘要1.4.数字签名 2.解决方案2.1.「对称式加密」2.2.「非对…

变分自编码器(VAE)介绍

变分自编码器&#xff08;VAE&#xff09;介绍 一、前言二、变分自编码器1、VAE的目标2、理论推导3、补充4、重参数技巧 一、前言 变分自编码器&#xff08;Variational Auto-Encoder&#xff0c;VAE&#xff09;是以自编码器结构为基础的深度生成模型。 自编码器&#xff08…

基于SpringBoot+Vue点餐系统设计和实现(源码+LW+部署讲解)

&#x1f339;作者简介&#xff1a;✌全网粉丝10W&#xff0c;前大厂员工&#xff0c;多篇互联网电商推荐系统专利&#xff0c;现有多家创业公司&#xff0c;致力于建站、运营、SEO、网赚等赛道。也是csdn特邀作者、博客专家、Java领域优质创作者&#xff0c;博客之星、掘金/华…

力扣每日一题104:二叉树的最大深度

题目 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; 输入&#xff1a;root [1,null,2…

QT5之windowswidget_菜单栏+工具栏_核心控件_浮动窗口_模态对话框_标准对话框/文本对话框

菜单栏工具栏 新建工程基类是QMainWindow 1、 2、 3、 点.pro文件&#xff0c;添加配置 因为之后用到lambda&#xff1b; 在.pro文件添加配置c11 CONFIG c11 #不能加分号 添加头文件 #include <QMenuBar>//菜单栏的头文件 主窗口代码mainwindow.cpp文件 #include &q…