SpringGateway网关

SpringGateway

  • SpringGateway网关
    • 奈非框架简介
    • 什么是网关
    • Spring Gateway简介
    • 为什么选择 Gateway
      • Gateway 的特性
      • Gateway 与 Zuul 的区别
    • Gateway 的三大核心概念
      • Route (路由)
      • Predicate (断言)
      • Filter (过滤)
      • 总结
    • Gateway 的工作流程
    • 简单网关演示
    • 网关多路由配置
    • Gateway配置路由的两种方式
    • 动态路由
    • 内置断言
      • **时间相关**
      • **要求指定参数的请求**
      • **带 Cookie 参数的断言**
      • 带 Header 参数的断言
      • Host 断言
      • Method 断言
    • 内置过滤器
      • AddRequestParameter过滤器
      • 自定义过滤器
    • 路由配置的设计规则
    • csmall项目网关
      • 网关项目的knife4j配置
      • Gateway和SpringMvc依赖冲突问题和解决

SpringGateway网关

奈非框架简介

早期(2020年前)奈非提供的微服务组件和框架受到了很多开发者的欢迎

这些框架和SpringCloud Alibaba的对应关系我们要了解

现在还有很多旧项目维护是使用奈非框架完成的微服务架构

Nacos对应Eureka都是注册中心

Dubbo对应Ribbon+feign都是实现微服务远程RPC调用的组件

Sentinel对应Hystrix都是做项目限流熔断降级的组件

SpringGateway对应Zuul都是网关组件

Gateway框架不是阿里写的,是Spring提供的

什么是网关

"网"指网络,"关"指关口或关卡

网关:就是指网络中的关口\关卡

网关就是当前微服务项目的"统一入口"

程序中的网关就是当前微服务项目对外界开放的统一入口

所有外界的请求都需要先经过网关才能访问到我们的程序

提供了统一入口之后,方便对所有请求进行统一的检查和管理

在这里插入图片描述

网关的主要功能有

  • 将所有请求统一经过网关
  • 网关可以对这些请求进行检查
  • 网关方便记录所有请求的日志
  • 网关可以统一将所有请求路由到正确的模块\服务上

“路由"的近义词就是"分配”

Spring Gateway简介

我们使用Spring Gateway作为当前项目的网关框架

Spring Gateway是Spring自己编写的,也是SpringCloud中的组件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Spring Gateway官网

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/

网关实例项目git地址

https://gitee.com/jtzhanghl/gateway-demo.git

为什么选择 Gateway

在这里插入图片描述

Gateway 的特性

在这里插入图片描述

Gateway 与 Zuul 的区别

在这里插入图片描述
在这里插入图片描述

Gateway 的三大核心概念

Route (路由)

在这里插入图片描述

Predicate (断言)

在这里插入图片描述

Filter (过滤)

在这里插入图片描述

总结

在这里插入图片描述

Gateway 的工作流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

简单网关演示

SpringGateway网关是一个依赖,不是一个软件

所以我们要使用它的话,必须先创建一个SpringBoot项目

这个项目也要注册到Nacos注册中心,因为网关项目也是微服务项目的一个组成部分

beijing和shanghai是编写好的两个项目

gateway项目就是网关项目,需要添加相关配置

<dependencies>
    <!--   SpringGateway的依赖   -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!--   Nacos依赖   -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!--   网关负载均衡依赖    -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>
</dependencies>

我们从yml文件配置开始添加

server:
  port: 9000
spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      # route就是路由的意思,下面就是配置路由信息
      # 一个网关项目大多会配置很多路由
      # 所以这个网关配置是一个List集合类型
      routes:
        # List类型元素赋值时,每个元素都要以"-"开头,在这个"-"之后,
        # 编写的所有内容,都是同一个对象的属性值
        # id设置当前路由的名称,也是唯一标识,和其它配置没有对应关系,注意不能和之后的id名称重复即可
        - id: gateway-beijing
          # uri属性配置的是路由目标服务器的名称,"beijing"指注册到Nacos名称为"beijing"的模块
          # lb就是负载均衡LoadBalance的缩写,标识路由支持负载均衡
          uri: lb://beijing
          # predicate是断言的意思,断言指某些条件满足时,执行某些操作
          # predicates配置也是一个List类型的属性,所以它赋值也要以"-"开头
          predicates:
            # 下面是断言的内容,Path表示判断路径,"/bj/**"表示判断路径是否以"/bj/"开头
            # 当断言条件满足时,就会按上面uri的配置,路由到该服务器模块
            # ↓   P是大写的!!!!!
            - Path=/bj/**

先启动nacos

再启动beijing

最后启动gateway

网关多路由配置

上面只配置了一个beijing的路由设置

下面我们修改yml文件也实现shanghai的路由设置

gateway:
  # route就是路由的意思,下面就是配置路由信息
  # 一个网关项目大多会配置很多路由
  # 所以这个网关配置是一个List集合类型
  routes:
    - id: gateway-shanghai
      uri: lb://shanghai
      predicates: 
        - Path=/sh/**
   # beijing配置略

在保证nacos启动的情况下

beijing服务器如果启动无需重启

启动shanghai项目

最后重启网关

测试网关路由到两个模块的效果

http://localhost:9000/bj/show可以访问beijing服务器的资源

http://localhost:9000/sh/show可以访问shanghai服务器的资源

以此类推,再有很多服务器时,我们都可以仅使用9000端口号来将请求路由到正确的服务器

就实现了gateway成为项目的统一入口的效果

Gateway配置路由的两种方式

  • 在配置文件yml中配置
  • 代码中注入RouteLocator的Bean

以第二种为例, 业务需求 - 通过端口为9527网关访问到百度网址
百度国内新闻网址,需要外网 - http://baidu.com

编码: 创建 config.GateWayConfig 类
在这里插入图片描述

package com.atguigu.springcloud.config;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GateWayConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();

        routes.route("path_route_atguigu",
                r -> r.path("/guonei")
                        .uri("http://baidu.com")).build();

        return routes.build();
    }
}

浏览器输入http://localhost:9527/guonei,返回http://baidu.com相同的页面。

动态路由

网关项目的配置会随着微服务模块数量增多而变得复杂,维护的工作量也会越来越大

所以我们希望gateway能够设计一套默认情况下自动路由到每个模块的路由规则

这样的话,不管当前项目有多少个路由目标,都不需要维护yml文件了

这就是我们SpringGateway的动态路由功能

在这里插入图片描述

配置文件中开启即可

gateway:
  discovery:
    locator:
      # 开启动态路由功能,默认值是关闭的
      # 动态路由规则:在网关端口号后,先编写要路由目标服务器注册到Naocs的名称
      # 在编写访问这个服务器的具体路径
      # 例如要访问 localhost:9001/bj/show  -> localhost:9000/beijing/bj/show
      enabled: true

按上面修改完配置之后

我们可以重启gateway来测试动态路由路径是否生效

动态路由生成规则为:在网关端口号后先写要路由到的目标服务器在nacos注册的名称,再编写具体路径

内置断言

我们上面章节在网关配置中使用了predicates(断言)的配置

断言的意思就是判断某个条件是否满足

我们之前使用了Path断言,判断请求的路径是不是满足条件,例如是不是/sh/** /bj/**

如果路径满足这个条件,就路由到指定的服务器

但是Path实际上只是SpringGateway提供的多种内置断言中的一种
在这里插入图片描述

还有很多其它断言

  • After
  • Before
  • Between
  • Cookie
  • Header
  • Host
  • Method
  • Path
  • Query
  • Remoteaddr

时间相关

After,Before,Between

判断当前时间在指定时间之前,之后或之间的操作

如果条件满足可以执行路由操作,否则拒绝访问

表示时间的格式比较特殊,先使用下面代码获得时间

ZonedDateTime.now()

运行程序输出,可获得当前时间,这个时间的格式可能是

2023-04-21T11:13:54.967+08:00[Asia/Shanghai]

下面在yml配置中添加新的断言配置

使用After设置必须在指定时间之后访问

routes:
  - id: gateway-shanghai
    uri: lb://shanghai
    predicates:
      - Path=/sh/**
      # After是时间断言,判断当前请求访问时的时间是否晚于配置的时间
      # 如果成立正常访问,如果判断不成立,返回404错误,多个断言之间是"与"的关系
      - After=2023-04-21T11:21:30.967+08:00[Asia/Shanghai]

使用Before设置必须在指定时间之前才能访问服务

否则发生404错误拒绝访问

predicates:
  - Path=/sh/**
  - Before=2023-04-21T11:23:20.967+08:00[Asia/Shanghai]

使用Between设置必须在指定时间之间访问

predicates:
  - Path=/sh/**
  - Between=2023-04-21T11:25:25.967+08:00[Asia/Shanghai],2023-04-21T11:25:45.967+08:00[Asia/Shanghai]

要求指定参数的请求

Query断言,判断是否包含指定的参数名称,包含参数名称才能通过路由
在这里插入图片描述

predicates:
  - Path=/sh/**
  # Query断言判断请求中是否包含指定参数名称,这里设置为username,如果没有发生404错误
  - Query=username

重启gateway测试

必须是包含username参数的请求才能访问到指定的页面

例如:http://localhost:9000/sh/show?username=tom

带 Cookie 参数的断言

在这里插入图片描述

spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=username, yyx

不带 Cookie 访问
在这里插入图片描述
携带 Cookie 访问
在这里插入图片描述

带 Header 参数的断言

在这里插入图片描述

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+  # 请求头要有 X-Request-Id 属性并且值为整数的正则表达式

在这里插入图片描述

Host 断言

在这里插入图片描述

Method 断言

在这里插入图片描述

内置过滤器

Gateway还提供的内置过滤器

不要和我们学习的filter混淆

内置过滤器允许我们在路由请求到目标资源的同时,对这个请求进行一些加工或处理

在这里插入图片描述

常见过滤器也有一些

AddRequestParameter过滤器

我们给大家演示一下AddRequestParameter过滤器

它的作用是在请求中添加参数和它对应的值

routes:
  - id: gateway-shanghai
    uri: lb://shanghai
    filters:
      # 如果路由顺利成功,这个内置过滤器会自动在请求中添加下面的参数
      # 属性名称为age,默认值18,如果请求中包含age的值,这个值就不会生效了
      - AddRequestParameter=age,18
    predicates:
      - Path=/sh/**
      # Query断言判断请求中是否包含指定参数名称,这里设置为username,如果没有发生404错误
      - Query=username

在shanghai的控制器方法中添加代码接收username,age的值

@GetMapping("/show")
public String show(String username,Integer age){
    // 2023-04-21T11:13:54.967+08:00[Asia/Shanghai]
    System.out.println(ZonedDateTime.now());
    return "这里是上海!username:"+username+",age:"+age;
}

重启shanghai和gateway进行测试

http://localhost:9000/sh/show?username=jerry

因为过滤器的存在,控制器可以获取网关过滤器添加的参数值

在这里插入图片描述

自定义过滤器

创建类 filter.MyLogGateWayFilter

package com.atguigu.springcloud.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Date;

@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("*********** come in MyLogGateWayFilter:  " + new Date());

        String uname = exchange.getRequest().getQueryParams().getFirst("uname");

        if(uname == null)
        {
            log.info("******* 用户名为null,非法用户,o(╥﹏╥)o");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;  // 数字越小,过滤器优先级越高
    }
}

启动项目,正常访问携带参数,不携带报错
正常访问如:http://localhost:9527/payment/lb?uname=123
错误访问如:http://localhost:9527/payment/lb

路由配置的设计规则

路由规则解释

路由规则一定是在开发之前就设计好的

一般可以使用约定好的路径开头来实现的

例如

gateway项目

如果路径以 /bj开头,就是要访问beijing项目

如果路径以 /sh开头.就是养访问shanghai项目

csmall项目

如果路径是 /base/business开头的, 就去找nacos-business服务器

如果路径是 /base/cart开头的, 就去找nacos-cart服务器

如果路径是 /base/order开头的, 就去找nacos-order服务器

如果路径是 /base/stock开头的, 就去找nacos-stock服务器

在这里插入图片描述

csmall项目网关

创建网关项目,然后父子相认

修改子项目pom文件和依赖

<?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>cn.tedu</groupId>
        <artifactId>csmall</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.tedu</groupId>
    <artifactId>gateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gateway</name>
    <description>Demo project for Spring Boot</description>
    <dependencies>
        <!-- web实例 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--  Nacos注册依赖 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

</project>

也删除test测试文件夹

application.properties换为yml

配置如下

server:
  port: 19000
spring:
  application:
    name: gateway-server
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          # 开启动态路由
          enabled: true
  main:
    # 防止SpringMVC和SpringGateway依赖冲突的配置
    web-application-type: reactive

网关项目的knife4j配置

我们希望配置网关之后,在使用knife4j测试时

就不来回切换端口号了

我们需要在网关项目中配置Knife4j才能实现

而这个配置是固定的,

只要是网关项目配置各个子模块的knife4j功能,就直接复制这几个类即可

csmall-finish中直接复制config\controller\filter

cn.tedu.gateway.config

SwaggerProvider

@Component
public class SwaggerProvider implements SwaggerResourcesProvider {
    /**
     * 接口地址
     */
    public static final String API_URI = "/v2/api-docs";
    /**
     * 路由加载器
     */
    @Autowired
    private RouteLocator routeLocator;
    /**
     * 网关应用名称
     */
    @Value("${spring.application.name}")
    private String applicationName;

    @Override
    public List<SwaggerResource> get() {
        //接口资源列表
        List<SwaggerResource> resources = new ArrayList<>();
        //服务名称列表
        List<String> routeHosts = new ArrayList<>();
        // 获取所有可用的应用名称
        routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null)
                .filter(route -> !applicationName.equals(route.getUri().getHost()))
                .subscribe(route -> routeHosts.add(route.getUri().getHost()));
        // 去重,多负载服务只添加一次
        Set<String> existsServer = new HashSet<>();
        routeHosts.forEach(host -> {
            // 拼接url
            String url = "/" + host + API_URI;
            //不存在则添加
            if (!existsServer.contains(url)) {
                existsServer.add(url);
                SwaggerResource swaggerResource = new SwaggerResource();
                swaggerResource.setUrl(url);
                swaggerResource.setName(host);
                resources.add(swaggerResource);
            }
        });
        return resources;
    }
}

cn.tedu.gateway.controller

SwaggerController类

@RestController
@RequestMapping("/swagger-resources")
public class SwaggerController {
    @Autowired(required = false)
    private SecurityConfiguration securityConfiguration;
    @Autowired(required = false)
    private UiConfiguration uiConfiguration;
    private final SwaggerResourcesProvider swaggerResources;
    @Autowired
    public SwaggerController(SwaggerResourcesProvider swaggerResources) {
        this.swaggerResources = swaggerResources;
    }
    @GetMapping("/configuration/security")
    public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
    }
    @GetMapping("/configuration/ui")
    public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
    }
    @GetMapping("")
    public Mono<ResponseEntity> swaggerResources() {
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    }
}

cn.tedu.gateway.filter

SwaggerHeaderFilter类

@Component
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
    private static final String HEADER_NAME = "X-Forwarded-Prefix";

    private static final String URI = "/v2/api-docs";

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getURI().getPath();
            if (!StringUtils.endsWithIgnoreCase(path,URI )) {
                return chain.filter(exchange);
            }
            String basePath = path.substring(0, path.lastIndexOf(URI));
            ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
            ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
            return chain.filter(newExchange);
        };
    }
}

gateway项目删除test文件夹

测试网关路由效果,和knife4j效果

启动Nacos\Seata\Sentinel

启动cart\stock\order\business

最后启动gateway

可以通过19000端口测试各个业务模块的功能

http://localhost:19000/nacos-stock/doc.html

http://localhost:19000/nacos-cart/doc.html

http://localhost:19000/nacos-order/doc.html

http://localhost:19000/nacos-business/doc.html

如果不使用网关一切正常,但是启动网关访问失败的话,就是gateway项目配置问题

Gateway和SpringMvc依赖冲突问题和解决

之前网关的演示项目我们添加的网关依赖

<!-- Spring Gateway 网关依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

当前csmall项目需要配置knife4j的路由配置,需要编写一个控制器

所以我们添加了SpringMVC的依赖

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

这两个依赖在同一个项目中时,默认情况下启动会报错

SpringMVC框架依赖中自带一个Tomcat服务器

而SpringGateway框架中自带一个Netty的服务器

在启动项目时,两个框架中包含的服务器都想占用相同端口,因为争夺端口号的主动权而发生冲突

导致启动服务时报错

要想能够正常启动必须在yml文件配置

spring:
  main:
    web-application-type: reactive

reactive:反应的

添加这个配置之后,会Tomcat服务器会变成非阻塞的运行

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL之创建表

创建emp表 #创建表的练习 -- 字段 属性 -- Id 整形 -- name 字符型 -- sex 字符型 -- birthday 日期型 -- entry_date 日期型 -- job 字符型 -- Salary 小数型 -- resume 文本型 CREATE TABLE emp(id INT,name VARCHAR(32),sex CHAR(1),birthday DATE,entry_date DAT…

python 使用linux find命令引导用户定位和选择文档

字多不看板&#xff08;InsCode&#xff09; 演示代码 # -*- coding:UTF-8 -*-# region import DebugInfo from DebugInfo.DebugInfo import *# endregion 画板 打印模板()# localSearch posix搜索接口类() localSearch 本地搜索接口类()用户选择 交互接口类.指定选择文档(…

羊大师,从对问题的认知到寻找答案

作为一个处于快速变化的世界中的个体&#xff0c;我们每天都要面对各种各样的问题。有些问题可能很小&#xff0c;可以迅速解决&#xff0c;而其他问题可能需要更多的时间和精力来应对。不管问题的大小&#xff0c;我们都希望能找到合适的解决方案&#xff0c;以便能够继续前进…

UI设计中的2.5D插画是什么?

2.5d插画&#xff0c;你可能第一时间会想2D应该是平面的&#xff0c;3D是立体的&#xff0c;介于2D和3D之间&#xff0c;那么它就是在平面上面看立体的2.5D透视原理图像&#xff0c;就是物体的正面、光面和暗面三面组成&#xff0c;也算是伪3D。 首先&#xff0c;设计师需要设…

【算法题】智能成绩表(js)

总分相同按名字字典顺序。 解法&#xff1a; function solution(lines) {const [personNum, subjectNum] lines[0].split(" ").map((item) > parseInt(item));const subjects lines[1].split(" ");const classMates [];let results [];for (let i…

数字社会观察:TikTok如何影响青少年文化?

TikTok&#xff0c;这个全球短视频巨头&#xff0c;正在成为塑造青少年文化的引领者。在这个数字社会中&#xff0c;TikTok的崛起不仅改变了信息传递的方式&#xff0c;更深刻地影响着青少年的价值观、审美观和社交方式。本文将深入探讨TikTok如何在数字社会中塑造和影响青少年…

Flutter工具安装与环境搭建

1、下载 Flutter SDK&#xff0c;下载完成后&#xff0c;在需要放置SDK的地方解压即可。 注意&#xff1a; 请勿将 Flutter 有特殊字符或空格的路径下。请勿将 Flutter 安装在需要高权限的文件夹内&#xff0c;例如 C:\Program Files\。 2、配置环境变量 例如&#xff1a; …

RFID复习内容整理

第一章 日常生活中的RFID技术 身份证&#xff08;高频&#xff09; typeB13.56MHz 一卡通&#xff08;高频&#xff09; ISO/IEC 14443 typeA 图书馆门禁停车场门票ETC 微波段、超高频 服装快销品牌 物联网定义 最初的定义 将各种信息传感设备&#xff0c;如射频识别(RFID)…

富集分析后得到很多term,选谁为研究方向:直播分享不同大语言模型的回答(Claude、ChatGPT3.5、Gemini)

大家好&#xff0c;今天生信小博士再来聊一聊&#xff1a;如何选择富集分析的term进行下一步研究。如果你不想看文字&#xff0c;可以本周日晚八点十分来我视频号直播间一起聊聊&#xff0c;到时会有代码实战与经验分享。欢迎预约~ 我用同样的问题&#xff0c;问了不同的大预言…

1、Redis变慢原因排查(上)

感觉Redis变慢了&#xff0c;这些可能的原因你查了没 &#xff1f;(上) Redis 作为一款业内使用率最高的内存数据库&#xff0c;其拥有非常高的性能&#xff0c;单节点的QPS压测能达到18万以上。但也正因此如此&#xff0c;当应用访问 Redis 时&#xff0c;如果发现响应延迟变…

【计算机设计大赛】冬残奥会可视化系统_附源码—信息可视化赛道获奖项目深入剖析【可视化项目案例-19】

🎉🎊🎉 你的技术旅程将在这里启航! 记得看本专栏里顶置的可视化宝典导航贴哦! 🚀🚀 本专栏为可视化专栏,包含现有的所有可视化技术。订阅专栏用户在文章底部可下载对应案例完整源码以供大家深入的学习研究。 🎓 每一个案例都会提供完整代码和详细的讲解,不论你…

数字基础设施及相关产业链报告:数据要素加快推进、AI终端应用加速发展

今天分享的AI系列深度研究报告&#xff1a;《数字基础设施及相关产业链报告&#xff1a;数据要素加快推进、AI终端应用加速发展》。 &#xff08;报告出品方&#xff1a;长城证券&#xff09; 报告共计&#xff1a;16页 1. 行业观点 在 TMT 各子板块&#xff1a;电子、通信、…

环境安全之配置管理及配置安全设置指导

一、前言 IT运维过程中&#xff0c;配置的变更和管理是一件非常重要且必要的事&#xff0c;除了一般宏观层面的配置管理&#xff0c;还有应用配置参数的配置优化&#xff0c;本文手机整理常用应用组件配置项配置&#xff0c;尤其安全层面&#xff0c;以提供安全加固指导实践。…

汉诺塔(函数递归)

前言 汉诺塔问题是一个经典的数学谜题&#xff0c;也是函数递归的一个经典问题&#xff0c;起源于印度。问题的设定是有三个柱子&#xff0c;第一个柱子上有一组不同大小的圆盘&#xff0c;按照从上到下依次变大的顺序摆放。目标是将所有的圆盘从第一个柱子移动到第三个柱子上&…

基于Java SSM框架实现东理咨询交流论坛系统项目【项目源码+论文说明】

基于java的SSM框架实现东理咨询交流论坛系统演示 摘要 在网络高速发展的时代&#xff0c;众多的软件被开发出来&#xff0c;给用户带来了很大的选择余地&#xff0c;而且人们越来越追求更个性的需求。在这种时代背景下&#xff0c;人们对东理咨询交流论坛越来越重视&#xff0…

Odoo:行业领先的免费开源供应链管理系统

先进且开源的供应链管理系统和全球供应链协作优化方案 为满足复杂的供应链和库存管理要求&#xff0c;如今绝大多数企业都不得不部署多个供应链管理软件和库存管理系统软件。如何利用一个库存管理与供应链管理软件&#xff0c;跨地区、跨时区地管理现代供应链&#xff1f;Odoo…

Java网络编程-深入理解BIO、NIO

深入理解BIO与NIO BIO BIO 为 Blocked-IO&#xff08;阻塞 IO&#xff09;&#xff0c;在 JDK1.4 之前建立网络连接时&#xff0c;只能使用 BIO 使用 BIO 时&#xff0c;服务端会对客户端的每个请求都建立一个线程进行处理&#xff0c;客户端向服务端发送请求后&#xff0c;…

免费!简单优雅的手机视频制作PR模板抖音素材下载

这是一款多功能的Premiere Pro模板&#xff0c;无论你是为视频、宣传内容还是社交媒体帖子短视频&#xff0c;这个pr模板都会为你的项目增添一丝优雅和专业。适用于广播&#xff0c;俱乐部&#xff0c;音乐会&#xff0c;舞蹈&#xff0c;设计&#xff0c;宣传片&#xff0c;动…

什么是前端国际化(internationalization)和本地化(localization)?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

基于QTreeWidget实现带Checkbox的多级组织结构选择树

基于QTreeWidget实现带Checkbox的多级组织结构选择树 采用基于QWidgetMingw实现的原生的组织结构树 通过QTreeWidget控件实现的带Checkbox多级组织结构树。 Qt相关系列文章&#xff1a; 一、Qt实现的聊天画面消息气泡 二、基于QTreeWidget实现多级组织结构 三、基于QTreeWidget…