当前位置: 首页 > news >正文

微服务day04

网关

网关路由

快速入门

创建新模块:hm-gateway继承hmall父项目。

引入依赖:引入网关依赖和nacos负载均衡的依赖

<?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>com.heima</groupId><artifactId>hmall</artifactId><version>1.0.0</version></parent><groupId>com.wmmczk</groupId><artifactId>hm-gateway</artifactId><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--common--><dependency><groupId>com.heima</groupId><artifactId>hm-common</artifactId><version>1.0.0</version></dependency><!--网关--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--nacos discovery--><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><build><finalName>${project.artifactId}</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

编写配置文件:一个模块中有多个collection类就可以写多个判断路径。

server:port: 8080
spring:application:name: gatewaycloud:nacos:server-addr: 192.168.21.101:8848gateway:routes:- id: item # 路由规则id,自定义,唯一uri: lb://item-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉取服务列表predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由到目标服务- Path=/items/**,/search/** # 这里是以请求路径作为判断规则- id: carturi: lb://cart-servicepredicates:- Path=/carts/**- id: useruri: lb://user-servicepredicates:- Path=/users/**,/addresses/**- id: tradeuri: lb://trade-servicepredicates:- Path=/orders/**- id: payuri: lb://pay-servicepredicates:- Path=/pay-orders/**

路由属性

网关登陆校验

自定义过滤器

 GlobaFilter自定义过滤器

//Ordered接口为spring中的排序接口,为核心接口
//GlobalFilter要在NettyRoutingFilter之前,NettyRoutingFilter的Ordered的值为int的最大值,确保其最后执行
public class MyGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//获取requestServerHttpRequest request = exchange.getRequest();//获取header头HttpHeaders headers = request.getHeaders();System.out.println("headers = " + headers);return chain.filter(exchange);//将exchange传给下一个过滤器}@Overridepublic int getOrder() {// 过滤器执行顺序,值越小,优先级越高return 0;}
}
 GatewayFilter自定义过滤器

登录校验

JWT工具

登录校验需要用到JWT,而且JWT的加密需要秘钥和加密工具。这些在hm-service中已经有了,我们直接拷贝过来:

具体作用如下:

  • AuthProperties:配置登录校验需要拦截的路径,因为不是所有的路径都需要登录才能访问

  • JwtProperties:定义与JWT工具有关的属性,比如秘钥文件位置

  • SecurityConfig:工具的自动装配

  • JwtTool:JWT工具,其中包含了校验和解析token的功能

  • hmall.jks:秘钥文件

其中AuthPropertiesJwtProperties所需的属性要在application.yaml中配置

hm:jwt:location: classpath:hmall.jks # 秘钥地址alias: hmall # 秘钥别名password: hmall123 # 秘钥文件密码tokenTTL: 30m # 登录有效期auth:excludePaths: # 无需登录校验的路径- /search/**- /users/login- /items/**

创建自定义拦截器:

package com.hmall.gateway.Filte;import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.AntPathMatcher;
import com.hmall.common.exception.UnauthorizedException;
import com.hmall.gateway.config.AuthProperties;
import com.hmall.gateway.util.JwtTool;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.List;@Component
@RequiredArgsConstructor
@EnableConfigurationProperties(AuthProperties.class)
public class AuthGlobalFilter implements GlobalFilter, Ordered {//用于读取配置文件中要放行的路径private final AuthProperties authProperties;private final AntPathMatcher antPathMatcher = new AntPathMatcher();private final JwtTool jwtTool;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//获取requsetServerHttpRequest request = exchange.getRequest();//获取path进行判断是否需要拦截RequestPath path = request.getPath();//使工具类进行判断if (isPath(path)){//放行return chain.filter(exchange);}//获取tokenString token = null;HttpHeaders headers = request.getHeaders();List<String> list = headers.get("Authorization");if (!CollUtil.isEmpty(list)){//给token赋值token = list.get(0);}//校验tokenLong userId = null;try {userId =  jwtTool.parseToken(token);} catch (UnauthorizedException e) {//token无效进行拦截//获取Response进行编辑ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();//该状态可以使后面的过滤器不在执行,返回错误}//TODO 传递用户信息System.out.println("userId = " + userId);return chain.filter(exchange);}private boolean isPath(RequestPath path) {//转为String类型String string = path.toString();//将配置文件中定义的路径进行遍历for (String excludePath : authProperties.getExcludePaths()) {if (antPathMatcher.match(excludePath, string)){//使用工具类进行匹配 antPathMatcher.match ,匹配成功返回truereturn true;}}return false;}@Overridepublic int getOrder() {return 0;}
}

网关传递用户信息

        //TODO 传递用户信息String userinfo = userId.toString();//exchange提供了修改请求头信息的方法mutateServerWebExchange build = exchange.mutate().request(b -> b.header("user-info",userinfo)).build();System.out.println("userId = " + userId);return chain.filter(build);
package com.hmall.gateway.Filte;import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.AntPathMatcher;
import com.hmall.common.exception.UnauthorizedException;
import com.hmall.gateway.config.AuthProperties;
import com.hmall.gateway.util.JwtTool;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.List;@Component
@RequiredArgsConstructor
@EnableConfigurationProperties(AuthProperties.class)
public class AuthGlobalFilter implements GlobalFilter, Ordered {//用于读取配置文件中要放行的路径private final AuthProperties authProperties;private final AntPathMatcher antPathMatcher = new AntPathMatcher();private final JwtTool jwtTool;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//获取requsetServerHttpRequest request = exchange.getRequest();//获取path进行判断是否需要拦截RequestPath path = request.getPath();//使工具类进行判断if (isPath(path)){//放行return chain.filter(exchange);}//获取tokenString token = null;HttpHeaders headers = request.getHeaders();List<String> list = headers.get("Authorization");if (!CollUtil.isEmpty(list)){//给token赋值token = list.get(0);}//校验tokenLong userId = null;try {userId =  jwtTool.parseToken(token);} catch (UnauthorizedException e) {//token无效进行拦截//获取Response进行编辑ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();//该状态可以使后面的过滤器不在执行,返回错误}//TODO 传递用户信息String userinfo = userId.toString();//exchange提供了修改请求头信息的方法mutateServerWebExchange build = exchange.mutate().request(b -> b.header("user-info",userinfo)).build();System.out.println("userId = " + userId);return chain.filter(build);}private boolean isPath(RequestPath path) {//转为String类型String string = path.toString();//将配置文件中定义的路径进行遍历for (String excludePath : authProperties.getExcludePaths()) {if (antPathMatcher.match(excludePath, string)){//使用工具类进行匹配 antPathMatcher.match ,匹配成功返回truereturn true;}}return false;}@Overridepublic int getOrder() {return 0;}
}

定义拦截器:

拦截器实现了HandlerInterceptor接口

package com.hmall.common.interceptor;import cn.hutool.core.util.StrUtil;
import com.hmall.common.utils.UserContext;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;// 拦截器需要进行注册
public class UserINfointerceptor implements HandlerInterceptor {//请求到达时执行获取用户信息@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1.获取请求头中的用户信息String userInfo = request.getHeader("user-info");// 2.判断是否为空if (StrUtil.isNotBlank(userInfo)) {// 不为空,保存到ThreadLocalUserContext.setUser(Long.valueOf(userInfo));System.out.println(userInfo);}// 3.放行return true;}//业务执行后的操作,删除线程存储中的数据@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserContext.removeUser();}
}

由于拦截器需要配置类进行注册才可以启用,创建一个配置类:

由于网关模块并没有使用springMVC进行编写,所以网关就会报错,因此使用该注解:@ConditionalOnClass(DispatcherServlet.class)//用于判断是否存在某个类,存在就加载,不存在就不加载,使得网关模块不在加载该配置类,避免报错。

package com.hmall.common.config;import com.hmall.common.interceptor.UserINfointerceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration//配置类的指定注释
@ConditionalOnClass(DispatcherServlet.class)//用于判断是否存在某个类,存在就加载,不存在就不加载
public class MyUserInfoConfig implements WebMvcConfigurer {//将拦截器添加到容器中@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new UserINfointerceptor ());}
}

在hm-common模块下的文件 spring.factories 中添加路径,在启动时扫描该配置

添加该代码:

  com.hmall.common.config.MyUserInfoConfig,\
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.hmall.common.config.MyBatisConfig,\com.hmall.common.config.MyUserInfoConfig,\com.hmall.common.config.JsonConfig

OpenFeign传递用户

在Api模块中的

DefaultFeignConfig配置类中添加拦截器,拦截所有的okhttp请求即所有的微服务之间的请求

使用匿名内部类进行配置

由于需要获取用户信息,添加hm-common的依赖获取UserContext对象。

        <!--common--><dependency><groupId>com.heima</groupId><artifactId>hm-common</artifactId><version>1.0.0</version></dependency>
@Beanpublic RequestInterceptor MyRequestInterceptor(){return new RequestInterceptor() {@Overridepublic void apply(RequestTemplate requestTemplate) {Long user = UserContext.getUser();if (user != null){requestTemplate.header("user-info",user.toString());}}};}
package com.hmall.api.config;import com.hmall.common.utils.UserContext;
import feign.Logger;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;public class DefaultFeignConfig {@Beanpublic Logger.Level feignLogLevel(){return Logger.Level.FULL;}@Beanpublic RequestInterceptor MyRequestInterceptor(){return new RequestInterceptor() {@Overridepublic void apply(RequestTemplate requestTemplate) {Long user = UserContext.getUser();if (user != null){requestTemplate.header("user-info",user.toString());}}};}
}

微服务的登录解决方案:

配置管理

配置共享

我们可以把微服务共享的配置抽取到Nacos中统一管理,这样就不需要每个微服务都重复配置了。分为两步:

  • 在Nacos中添加共享配置

  • 微服务拉取配置

添加共享配置:

1、在nacos的配置列表下进行新建共享配置

  • Data ID:表示共享配置文件的名称,即在项目中引入是的名字
  • 使用默认分组
  • 配置内容即要共享的配置,可以使用占位符进行动态的设置配置数据

jdbc的更共享配置:shared-jdbc.yaml ,有数据库设置和mp的配置使用占位符来进行不同的设置。

        占位符后面的 :表示默认字符,即没有设置的默认数据

spring:datasource:url: jdbc:mysql://${hm.db.host:192.168.21.101}:${hm.db.port:3306}/${hm.db.database}?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Driverusername: ${hm.db.user:root}password: ${hm.db.pw:123}
mybatis-plus:configuration:default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandlerglobal-config:db-config:update-strategy: not_nullid-type: auto

日志的共享配置: shared-log.yaml

logging:level:com.hmall: debugpattern:dateformat: HH:mm:ss:SSSfile:path: "logs/${spring.application.name}"

swagger的共享配置;shared-swagger.yaml

knife4j:enable: trueopenapi:title: ${hm.swagger.title:黑马商城接口文档}description: ${hm.swagger.description:黑马商城接口文档}email: ${hm.swagger.email:zhanghuyi@itcast.cn}concat: ${hm.swagger.concat:虎哥}url: https://www.itcast.cnversion: v1.0.0group:default:group-name: defaultapi-rule: packageapi-rule-resources:- ${hm.swagger.package}

接下来,我们要在微服务拉取共享配置。将拉取到的共享配置与本地的application.yaml配置合并,完成项目上下文的初始化。

不过,需要注意的是,读取Nacos配置是SpringCloud上下文(ApplicationContext)初始化时处理的,发生在项目的引导阶段。然后才会初始化SpringBoot上下文,去读取application.yaml

也就是说引导阶段,application.yaml文件尚未读取,根本不知道nacos 地址,该如何去加载nacos中的配置文件呢?

SpringCloud在初始化上下文的时候会先读取一个名为bootstrap.yaml(或者bootstrap.properties)的文件,如果我们将nacos地址配置到bootstrap.yaml中,那么在项目引导阶段就可以读取nacos中的配置了。

/2、在项目中引入依赖:

  <!--nacos配置管理--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--读取bootstrap文件--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency>

创建bootstrap.yml

spring:application:name: cart-service # 服务名称profiles:active: devcloud:nacos:server-addr: 192.168.21.101 # nacos地址config:file-extension: yaml # 文件后缀名shared-configs: # 共享配置- dataId: shared-jdbc.yaml # 共享mybatis配置- dataId: shared-log.yaml # 共享日志配置- dataId: shared-swagger.yaml # 共享日志配置

修改原有的配置文件,为占位符赋值 application.yaml

server:port: 8082
feign:okhttp:enabled: true # 开启OKHttp连接池支持
hm:swagger:title: 购物车服务接口文档package: com.hmall.cart.controllerdb:database: hm-cart

配置热更新

注意文件的dataId格式:

[服务名]-[spring.active.profile].[后缀名]

文件名称由三部分组成:

  • 服务名:我们是购物车服务,所以是cart-service

  • spring.active.profile:就是spring boot中的spring.active.profile,可以省略,则所有profile共享该配置

  • 后缀名:例如yaml

设置nacos配置热更新文件:

名字为:cart-service

hm:cart:maxAmount: 10

在代码中创建配置类:,设置配置文件关联。

创建包: config

@Data
@Component
@ConfigurationProperties(prefix = "hm.cart")
public class CartProperties {private Integer maxAmount;
}

修改业务文件中判断购物车最大数量:

    private void checkCartsFull(Long userId) {int count = Math.toIntExact(lambdaQuery().eq(Cart::getUserId, userId).count());if (count >= cartProperties.getMaxAmount()) {throw new BizIllegalException(StrUtil.format("用户购物车课程不能超过{}", cartProperties.getMaxAmount()));}}

动态路由

动态路由的相关操作

相关文章:

微服务day04

网关 网关路由 快速入门 创建新模块&#xff1a;hm-gateway继承hmall父项目。 引入依赖&#xff1a;引入网关依赖和nacos负载均衡的依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"…...

Spring Boot 集成JWT实现Token验证详解

文章目录 Spring Boot 集成JWT实现Token验证详解一、引言二、JWT和Token基础1、什么是Token2、什么是JWT3、JWT的结构4、JWT的工作原理 三、集成JWT1、引入JWT依赖2、创建Token工具类3、创建拦截器4、注册拦截器 四、总结 Spring Boot 集成JWT实现Token验证详解 一、引言 在现…...

如何快速搭建一个spring boot项目

一、准备工作 1.1 安装JDK&#xff1a;确保计算机上已安装Java Development Kit (JDK) 8或更高版本、并配置了环境变量 1.2 安装Maven&#xff1a;下载并安装Maven构建工具&#xff0c;这是Spring Boot官方推荐的构建工具。 1.3 安装代码编辑器&#xff1a;这里推荐使用Inte…...

学习笔记:黑马程序员JavaWeb开发教程(2024.11.9)

9.1 Mybatis-基础操作-环境准备 这里也没做&#xff0c;到时候写案例&#xff0c;如果需要环境配置什么的&#xff0c;可以看看这个 9.2 Mybatis-基础操作-删除 删除需要动态获取需要删除的id&#xff0c;使用方法传参&#xff0c;#{}的方式实现 在编写的delete方法中&a…...

【软考】系统分析师第二版 新增章节 第20章微服务系统分析与设计

微服务系统是一类基于微服务架构风格的分布式系统&#xff0c;它将应用程序拆分成多个独立的小型服务&#xff0c;每个服务都运行在独立的进程中&#xff0c;并采用轻量级通信协议进行通信。这些服务可以由不同的团队开发、不同的编程语言编写&#xff0c;并且可以按需部署。微…...

抓包工具WireShark使用记录

目录 网卡选择&#xff1a; 抓包流程&#xff1a; 捕获过滤器 常用捕获过滤器&#xff1a; 抓包数据的显示 显示过滤器&#xff1a; 常用的显示过滤器&#xff1a; 实际工作中&#xff0c;在平台对接&#xff0c;设备对接等常常需要调试接口&#xff0c;PostMan虽然可以进…...

C++上机实验|多态性编程练习

1.实验目的 (1)理解多态性的概念。 (2)掌握如何用虚函数实现动态联编 (3)掌握如何利用虚基类。 2.实验内容 设计一个飞机类 plane,由它派生出歼击机类fighter和轰炸机类 bomber,歼击机类fighter 和轰炸机类bomber 又共同派生出歼轰机(多用途战斗机)。利用虚函数和虚基类描述…...

php伪协议介绍

PHP伪协议共有12种,具体如下: file:// — 访问本地文件系统http:// — 访问 HTTP(s) 网址ftp:// — 访问 FTP(s) URLsphp:// — 访问各个输入/输出流(I/O streams)php://stdin, php://stdout 和 php://stderrphp://inputphp://outputphp://memory 和 php://tempphp://filte…...

『事善能』MySQL基础 — 2.MySQL 5.7安装(一)

1、通过msi安装软件进行MySQL安装 &#xff08;1&#xff09;点击运行MySQL安装文件 &#xff08;2&#xff09;选择安装类型 我们选择自定义安装&#xff0c;点击Next。 说明 Develop Default&#xff1a;默认开发类型&#xff0c;安装MySQL服务器以及开发MySQL应用所需要的工…...

漫谈分布式唯一ID

文章目录 本系列前言UUIDDB自增主键Redis incr命令号段模式雪花算法 本系列 漫谈分布式唯一ID&#xff08;本文&#xff09;分布式唯一ID生成&#xff08;二&#xff09;&#xff1a;leaf分布式唯一ID生成&#xff08;三&#xff09;&#xff1a;uid-generator&#xff08;待完…...

【复旦微FM33 MCU 开发指南】ADC

前言 本系列基于复旦微FM33LC0系列单片机的DataSheet编写&#xff0c;旨在提供手册解析和开发指南。 本文章及本系列其他文章将持续更新&#xff0c;本系列其它文章请跳转【复旦微FM33 MCU 外设开发指南】总集篇 本文章最后更新日期&#xff1a;2024/11/09 全文字数&#xff…...

ORB_SLAM3安装

ORB_SLAM3安装 一.前期准备1.1ubuntu查看当前版本的命令1.2 根据ubuntu版本&#xff0c;更新下载软件源1.3 先下载git1.4 vim语法高亮1.5 常见的linux命令 二.ORB-SLAM3下载2.1 ORB_SLAM3源码下载2.2 安装依赖库2.2.1 依赖库2.2.2 安装pangolin2.2.3 安装opencv2.2.4 Eigen3安装…...

GoLang协程Goroutiney原理与GMP模型详解

本文原文地址:GoLang协程Goroutiney原理与GMP模型详解 什么是goroutine Goroutine是Go语言中的一种轻量级线程&#xff0c;也成为协程&#xff0c;由Go运行时管理。它是Go语言并发编程的核心概念之一。Goroutine的设计使得在Go中实现并发编程变得非常简单和高效。 以下是一些…...

全文检索ElasticSearch到底是什么?

学习ElasticSearch之前&#xff0c;我们先来了解一下搜索 1 搜索是什么 ① 概念&#xff1a;用户输入想要的关键词&#xff0c;返回含有该关键词的所有信息。 ② 场景&#xff1a; ​ 1互联网搜索&#xff1a;谷歌、百度、各种新闻首页&#xff1b; ​ 2 站内搜索&#xff…...

FPGA实现串口升级及MultiBoot(五)通过约束脚本添加IPROG实例

本文目录索引 一个指令和三种方式通过约束脚本添加Golden位流工程MultiBoot位流工程验证example1总结代码缩略词索引: K7:Kintex 7V7:Vertex 7A7:Artix 7MB:MicroBlaze上一篇文章种总结了MultiBoot 关键技术,分为:一个指令、二种位流、三种方式、四样错误。针对以上四句话我…...

文献阅读 | Nature Methods:使用 STAMP 对空间转录组进行可解释的空间感知降维

文献介绍 文献题目&#xff1a; 使用 STAMP 对空间转录组进行可解释的空间感知降维 研究团队&#xff1a; 陈金妙&#xff08;新加坡科学技术研究局&#xff09; 发表时间&#xff1a; 2024-10-15 发表期刊&#xff1a; Nature Methods 影响因子&#xff1a; 36.1&#xff0…...

【模块化大作战】Webpack如何搞定CommonJS与ES6混战(1-3)

在前端开发中&#xff0c;模块化是一个重要的概念&#xff0c;不同的模块化标准有不同的特点和适用场景。webpack 同时支持 CommonJS 和 ES6 Module&#xff0c;因此需要理解它们在互操作时 webpack 是如何处理的。 同模块化标准 如果导出和导入使用的是同一种模块化标准&…...

[NewStar 2024] week5完结

每次都需要用手机验证码登录&#xff0c;题作的差不多就没再进过。今天把week5解出的部分记录下。好像时间过去很久了。 Crypto 没e也能完 这题给了e,p,q,dp,dq。真不清楚还缺啥 long_to_bytes(pow(c,dp,p)) 格格你好棒 给了a,b和提示((p2*r) * 3*a q) % b < 70 其中r…...

IntelliJ IDEA的快捷键

IntelliJ IDEA 是一个非常强大的集成开发环境&#xff0c;它提供了大量的快捷键来加速开发者的日常工作。这里为您整理了一份 IntelliJ IDEA 的快捷键大全&#xff0c;包含了编辑、导航、重构、运行等多个方面的快捷键。请注意&#xff0c;这些快捷键是基于 Windows 版本的 Int…...

暮雨直播 1.3.2 | 内置直播源,频道丰富,永久免费

暮雨直播是一款内置直播源的电视直播应用程序&#xff0c;提供丰富的频道内容&#xff0c;包括教学、首页、一线、博主、解说、动漫、堆堆等。该应用的内置直播源持续更新维护&#xff0c;确保用户可以稳定地观看各种电视频道。暮雨直播承诺永久免费&#xff0c;为用户提供了一…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

华为OD机考-机房布局

import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

DiscuzX3.5发帖json api

参考文章&#xff1a;PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下&#xff0c;适配我自己的需求 有一个站点存在多个采集站&#xff0c;我想通过主站拿标题&#xff0c;采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...