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

JWT使用教程

目录

  • JWT (JSON Web Token)
    • 1. JWT简介
      • (1) 什么是JWT
      • (2) JWT有什么用
      • (3) JWT认证方式
    • 2. JWT的组成部分
    • 3. 签名的目的
    • 4. JWT与Token的区别
    • 5 JWT的优势
    • 6 JJWT签发与验证token
      • (1) 引入依赖
      • (2) 创建 Token
      • (3) 解析Token
      • (4) 设置过期时间
      • (5) 自定义claims
    • 7. JWT自定义工具类

JWT (JSON Web Token)

1. JWT简介

(1) 什么是JWT

JWT是一种基于 Token 的认证授权机制.
JWT (JSON Web Token) 是目前最流行的跨域认证解决方案,是一种基于 Token 的认证授权机制。从 JWT 的全称可以看出,JWT 本身也是 Token,一种规范化之后的 JSON 结构的 Token。

(2) JWT有什么用

JWT最常见的场景就是授权认证,用户登录之后,后续的每个请求都将包含JWT, 系统在每次处理用户请求之前,都要先进行JWT的安全校验,通过校验之后才能进行接下来的操作。

(3) JWT认证方式

  • JWT通过数字签名的方式,以JSON对象为载体,在用户和服务器之间传递安全可靠的信息.

image.png

  1. 首先,前端通过Web表单将自己的用户名和密码发送到后端的接口。这一过程一般是一个HTTP POST请求。建议的方式是通过SSL加密的传输(https协议),从而避免敏感信息被嗅探。
  2. 后端核对用户名和密码成功后,将用户的id等其他信息作为JWT Payload(负载),将其与头部分别进行Base64编码拼接后签名,形成一个JWT(Token)。形成的JWT就是一个形同lll.zzz.xxx的字符串。 token head.payload.singurater
  3. 后端将JWT字符串作为登录成功的返回结果返回给前端。前端可以将返回的结果保存在localStorage或sessionStorage上,退出登录时前端删除保存的JWT即可。
  4. 前端在每次请求时将JWT放入HTTP Header中的Authorization位。(解决XSS和XSRF问题) HEADER
  5. 后端检查是否存在,如存在验证JWT的有效性。例如,检查签名是否正确;检查Token是否过期;检查Token的接收方是否是自己(可选)。
  6. 验证通过后后端使用JWT中包含的用户信息进行其他逻辑操作,返回相应结果。

2. JWT的组成部分

头部(Header)

  • 描述 JWT 的元数据,定义了生成签名的算法以及 Token 的类型。
 {"typ":"JWT","alg":"HS256"}//typ(Type):令牌类型,也就是 JWT。//alg(Algorithm) :签名算法,比如 HS256。

JWT签名算法中,一般有两个选择,一个采用HS256,另外一个就是采用RS256

进行BASE64编码https://base64.us/,编码后的字符串如下:eyJhbGciOiJIUzI1NiJ9

image.png

载荷(payload)

载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分

 {"sub":"1234567890","name":"John Doe","admin":true}

将上面的JSON数据进行base64编码,得到Jwt第二部分: eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

image.png

字段说明,下面的字段都是由 JWT的标准所定义的

 iss: jwt签发者sub: jwt所面向的用户aud: 接收jwt的一方exp: jwt的过期时间,这个过期时间必须要大于签发时间nbf: 定义在什么时间之前,该jwt都是不可用的.iat: jwt的签发时间jti: jwt的唯一身份标识,主要用来作为一次性token。

签名(signature)

服务器通过 Payload、Header 和一个密钥(Secret) 使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成。

Signature 部分是对前两部分的签名,作用是防止 Token(主要是 payload) 被篡改。

这个签名的生成需要用到:

  • Header + Payload。
  • 存放在服务端的密钥(一定不要泄露出去)。
  • 签名算法。

例如,如果要使用HMAC SHA256算法,则将通过以下方式创建签名:

 String encodeString = base64UrlEncode(header) + "." + base64UrlEncode(payload);String secret = HMACSHA256(encodeString,secret);

签名用于验证消息在此过程中没有更改,并且对于使用私钥进行签名的令牌,它还可以验证JWT的发送者是它所说的真实身份。

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

3. 签名的目的

最后一步签名的过程,实际上是对头部以及载荷内容进行签名。

image.png

一般而言,加密算法对于不同的输入产生的输出总是不一样的。对于两个不同的输入,产生同样的输出的概率极其地小(有可能比我成世界首富的概率还小)。所以,我们就把“不一样的输入产生不一样的输出”当做必然事件来看待吧。

所以,如果有人对头部以及载荷的内容解码之后进行修改,再进行编码的话,那么新的头部和载荷的签名和之前的签名就将是不一样的。而且,如果不知道服务器加密的时候用的密钥的话,得出来的签名也一定会是不一样的。

服务器应用在接受到JWT后,会首先对头部和载荷的内容用同一算法再次签名。那么服务器应用是怎么知道我们用的是哪一种算法呢?别忘了,我们在JWT的头部中已经用** alg字段指明了我们的加密算法了。

如果服务器应用对头部和载荷再次以同样方法签名之后发现,自己计算出来的签名和接受到的签名不一样,那么就说明这个Token的内容被别人动过的,我们应该拒绝这个Token,返回一个HTTP 401 Unauthorized响应。

image.png

4. JWT与Token的区别

Token 和 JWT (JSON Web Token) 都是用来在客户端和服务器之间传递身份验证信息的一种方式。但是它们之间有一些区别。

  • Token 是一个通用术词,可以指代任何用来表示身份的字符串。它可以是任何形式的字符串,并不一定是 JWT。
  • JWT 是一种特殊的 Token,它是一个 JSON 对象,被编码成字符串并使用秘密密钥进行签名。JWT 可以用来在身份提供者和服务提供者之间安全地传递身份信息,因为它可以被加密,并且只有拥有秘密密钥的方能解密。

总的来说,JWT 是一种特殊的 Token,它具有更强的安全性和可靠性。

5 JWT的优势

  • 简洁(Compact): 可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快
  • 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库
  • 因为Token是以JSON加密的形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式都支持
  • 不需要在服务端保存会话信息,特别适用于分布式微服务。

6 JJWT签发与验证token

使用jjwt实现jwt的签发和解析获取payload中的数据.

JJWT是一个提供端到端的JWT创建和验证的Java库。永远免费和开源(Apache License,版本2.0)。

官方文档:https://github.com/jwtk/jjwt

(1) 引入依赖

 <!--jwt依赖--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>

(2) 创建 Token

 @SpringBootTestclass SpringsecurityExampleApplicationTests {@Testvoid contextLoads() {}@Testpublic void testJJWT(){JwtBuilder builder = Jwts.builder().setId("9527")  //设置唯一ID.setSubject("hejiayun_community")   //设置主体.setIssuedAt(new Date())    //设置签约时间.signWith(SignatureAlgorithm.HS256, "mashibing");//设置签名 使用HS256算法,并设置SecretKey//压缩成String形式,签名的JWT称为JWSString jws = builder.compact();System.out.println(jws);/*** eyJhbGciOiJIUzI1NiJ9.* eyJqdGkiOiI5NTI3Iiwic3ViIjoiaGVqaWF5dW5fY29tbXVuaXR5IiwiaWF0IjoxNjgxMTM1ODY2fQ.* ybkDJLVj1Fsi8m3agyxtyd0wxv7lHDqCWNOLN-eOxC8*/}}

运行打印结果:

 eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI5NTI3Iiwic3ViIjoiaGVqaWF5dW5fY29tbXVuaXR5IiwiaWF0IjoxNjgxMTM1ODY2fQ.ybkDJLVj1Fsi8m3agyxtyd0wxv7lHDqCWNOLN-eOxC

(3) 解析Token

我们刚才已经创建了token ,在web应用中这个操作是由服务端进行然后发给客户端,客户端在下次向服务端发送请求时需要携带这个token(这就好像是拿着一张门票一样),那服务端接到这个token 应该解析出token中的信息(例如用户id),根据这些信息查询数据库返回相应的结果。

解析JJWS的方法如下:

  1. 使用该 Jwts.parser()方法创建 JwtParserBuilder实例。
  2. setSigningKey() 与builder中签名方法signWith()对应,parser中的此方法拥有与signWith()方法相同的三种参数形式,用于设置JWT的签名key,用户后面对JWT进行解析。
  3. 最后,parseClaimsJws(String)用您的jws调用该方法,生成原始的JWS。
  4. 如果解析或签名验证失败,则整个调用将包装在try / catch块中。
 @Testpublic void parserJWT(){String JWS = "eyJhbGciOiJIUzI1NiJ9." +"eyJqdGkiOiI5NTI3Iiwic3ViIjoiaGVqaWF5dW5fY29tbXVuaXR5IiwiaWF0IjoxNjgxMTM1ODY2fQ." +"ybkDJLVj1Fsi8m3agyxtyd0wxv7lHDqCWNOLN-eOxC8";//claims = 载荷 (payload)try {Claims claims = Jwts.parser().setSigningKey("mashibing").parseClaimsJws(JWS).getBody();System.out.println(claims);} catch (Exception e) {System.out.println("Token验证失败! !");e.printStackTrace();}}

运行打印结果:

 {jti=9527, sub=hejiayun_community, iat=1681135866}iat: jwt的签发时间jti: jwt的唯一身份标识,主要用来作为一次性token。sub: jwt所面向的用户

(4) 设置过期时间

有很多时候,我们并不希望签发的token是永久生效的,所以我们可以为token添加一个过期时间。

  • 创建token 并设置过期时间
     @Testpublic void testJJWT2(){long currentTimeMillis = System.currentTimeMillis();Date expTime = new Date(currentTimeMillis);JwtBuilder builder = Jwts.builder().setId("9527")  //设置唯一ID.setSubject("hejiayun_community")   //设置主体.setIssuedAt(new Date())    //设置签约时间.setExpiration(expTime)     //设置过期时间.signWith(SignatureAlgorithm.HS256, "mashibing");//设置签名 使用HS256算法,并设置SecretKey//压缩成String形式,签名的JWT称为JWSString jws = builder.compact();System.out.println(jws);/*** eyJhbGciOiJIUzI1NiJ9.* eyJqdGkiOiI5NTI3Iiwic3ViIjoiaGVqaWF5dW5fY29tbXVuaXR5IiwiaWF0IjoxNjgxMTM3MjI0LCJleHAiOjE2ODExMzcyMjR9.* evc01MRxLjpbksbMLdVPM9sJGYGhpC3UYOfm4-0sMGE  */}
  • 解析TOKEN
 打印效果: 异常信息: JWT签名与本地计算的签名不匹配。JWT有效性不能断言,也不应该被信任Token验证失败! !io.jsonwebtoken.MalformedJwtException: JWT strings must contain exactly 2 period characters. Found: 

(5) 自定义claims

我们刚才的例子只是存储了id和subject两个信息,如果你想存储更多的信息(例如角色)可以定义自定义claims。

创建测试类,并设置测试方法:

     @Testpublic void testJJWT3(){long currentTimeMillis = System.currentTimeMillis()+100000000L;Date expTime = new Date(currentTimeMillis);JwtBuilder builder = Jwts.builder().setId("9527")  //设置唯一ID.setSubject("hejiayun_community")   //设置主体.setIssuedAt(new Date())    //设置签约时间.setExpiration(expTime)     //设置过期时间.claim("roles","admin")       //设置角色.signWith(SignatureAlgorithm.HS256, "mashibing");//设置签名 使用HS256算法,并设置SecretKey//压缩成String形式,签名的JWT称为JWSString jws = builder.compact();System.out.println(jws);/*** eyJhbGciOiJIUzI1NiJ9.* eyJqdGkiOiI5NTI3Iiwic3ViIjoiaGVqaWF5dW5fY29tbXVuaXR5IiwiaWF0IjoxNjgxMTM3MjI0LCJleHAiOjE2ODExMzcyMjR9.* evc01MRxLjpbksbMLdVPM9sJGYGhpC3UYOfm4-0sMGE*/}

解析TOKEN,打印结果

 {jti=9527, sub=hejiayun_community, iat=1681137464, exp=1681237464, roles=admin}

7. JWT自定义工具类

/*** JWT工具类*/
public class JwtUtil {//有效期为public static final Long JWT_TTL = 60 * 60 *1000L;// 60 * 60 *1000  一个小时//设置秘钥明文public static final String JWT_KEY = "pan";public static String getUUID(){String token = UUID.randomUUID().toString().replaceAll("-", "");return token;}/*** 生成jtw* @param subject token中要存放的数据(json格式)* @return*/public static String createJWT(String subject) {JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 设置过期时间return builder.compact();}/*** 生成jtw* @param subject token中要存放的数据(json格式)* @param ttlMillis token超时时间* @return*/public static String createJWT(String subject, Long ttlMillis) {JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 设置过期时间return builder.compact();}private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;SecretKey secretKey = generalKey();long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);if(ttlMillis==null){ttlMillis=JwtUtil.JWT_TTL;}long expMillis = nowMillis + ttlMillis;Date expDate = new Date(expMillis);return Jwts.builder().setId(uuid)              //唯一的ID.setSubject(subject)   // 主题  可以是JSON数据.setIssuer("sg")     // 签发者.setIssuedAt(now)      // 签发时间.signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥.setExpiration(expDate);}/*** 创建token* @param id* @param subject* @param ttlMillis* @return*/public static String createJWT(String id, String subject, Long ttlMillis) {JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 设置过期时间return builder.compact();}public static void main(String[] args) throws Exception {String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJjYWM2ZDVhZi1mNjVlLTQ0MDAtYjcxMi0zYWEwOGIyOTIwYjQiLCJzdWIiOiJzZyIsImlzcyI6InNnIiwiaWF0IjoxNjM4MTA2NzEyLCJleHAiOjE2MzgxMTAzMTJ9.JVsSbkP94wuczb4QryQbAke3ysBDIL5ou8fWsbt_ebg";Claims claims = parseJWT(token);System.out.println(claims);}/*** 生成加密后的秘钥 secretKey* @return*/public static SecretKey generalKey() {byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;}/*** 解析** @param jwt* @return* @throws Exception*/public static Claims parseJWT(String jwt) throws Exception {SecretKey secretKey = generalKey();return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();}}

相关文章:

JWT使用教程

目录 JWT (JSON Web Token)1. JWT简介(1) 什么是JWT(2) JWT有什么用(3) JWT认证方式 2. JWT的组成部分3. 签名的目的4. JWT与Token的区别5 JWT的优势6 JJWT签发与验证token(1) 引入依赖(2) 创建 Token(3) 解析Token(4) 设置过期时间(5) 自定义claims 7. JWT自定义工具类 JWT (J…...

【大模型系列篇】如何解决DeepSeek-R1结构化输出问题,使用PydanticAl和DeepSeek构建结构化Agent

今日号外&#xff1a;&#x1f525;&#x1f525;&#x1f525; DeepSeek开源周&#xff1a;炸场&#xff01;DeepSeek开源FlashMLA&#xff0c;提升GPU效率 下面我们开始今天的主题&#xff0c;deepseek官方明确表示deepseek-r1目前不支持json输出/function call&#xff0c;可…...

老旧android项目编译指南(持续更)

原因 编译了很多项目&#xff0c;找到了一些可观的解决办法 1. android studio里面的jdk版本切换 jdk版本切换在这里&#xff0c;一般安卓开发需要用到4个版本的jdk,jdk8, jdk11, jdk17, jdk21新版的android stuio是默认使用高版本的jdk,所以切换版本是很有必要的 2. 命令…...

linux中安装部署Jenkins,成功构建springboot项目详细教程

参考别人配置Jenkins的git地址为https&#xff0c;无法连上github拉取项目&#xff0c;所以本章节介绍通过配置SSH地址来连github拉取项目 目录&#xff1a; 1、springboot项目 1.1 创建名为springcloudproject的springboot项目工程 1.2 已将工程上传到github中&#xff0c;g…...

AI开发利器:Anaconda

在Python开发过程中&#xff0c;不同的项目可能会依赖不同版本的Python以及各种不同版本的库。比如&#xff0c;项目A可能依赖Python 3.8和某个特定版本的numpy、TensorFlow和PyTorch&#xff0c;而项目B可能需要Python 3.9以及另一个版本的numpy库。如果直接在系统中安装Pytho…...

java网络编程--基于TCP协议的网络编程

Scoket介绍 利用 TCP 协议进行通信的两个应用程序是有主次之分的&#xff0c; 一个是服务器程序&#xff0c;一个是客户端程序&#xff0c; 两者的功能和编写方法不太一样&#xff0c; 其中 ServerSocket 类表示 Socket 服务器端&#xff0c;Socket 类表示 Socket 客户端。 服…...

PageHelper新发现

PageHelper 背景解决reasonablepageSizeZero 背景 今天发现了一个很有趣的现象&#xff0c;接手一个很老的项目springmvc项目、使用PageHelper分页实现常见的后端接口分页功能。但是发现当页码参数大于实际的页码数时、正常不应该返回数据&#xff0c;但是目前确一直返回数据不…...

Redis 数据结构和使用详解(带示例)

Redis 支持的主要数据结构及其对应操作命令的详细解释&#xff0c;结合具体使用场景和示例&#xff1a; 1. 字符串&#xff08;String&#xff09; 用途&#xff1a;存储文本、数值或二进制数据&#xff0c;适用于缓存、计数器等。 常用命令&#xff1a; SET key value&#x…...

深度解读 Chinese CLIP 论文:开启中文视觉对比语言预训练

目录 论文概述1.论文摘要2.论文脑图3.论文创新3.1模型构建3.2训练方法3.3数据构建3.4部署优化 4.模型架构 论文解析1. 引言2. 方法2.1数据说明2.2预训练方法2.2.1模型初始化方法2.2.2两阶段预训练方法 2.3预训练细节2.3.1模型初始化2.3.2第一阶段预训练2.3.3第二阶段预训练2.3.…...

SpringBoot 2 后端通用开发模板搭建(异常处理,请求响应)

目录 一、环境准备 二、新建项目 三、整合依赖 1、MyBatis Plus 数据库操作 2、Hutool 工具库 3、Knife4j 接口文档 4、其他依赖 四、通用基础代码 1、自定义异常 2、响应包装类 3、全局异常处理器 4、请求包装类 5、全局跨域配置 补充&#xff1a;设置新建类/接…...

【Oracle专栏】sqlplus显示设置+脚本常用显示命令

Oracle相关文档&#xff0c;希望互相学习&#xff0c;共同进步 风123456789&#xff5e;-CSDN博客 1.内容概述 本文主要针对oracle 运维中常用知识点进行整理&#xff0c;包括&#xff1a; 1&#xff09;sqlplus模式下&#xff0c;为了方便查询设置相应的行宽、列宽、行数。…...

DeepSeek 助力 Vue3 开发:打造丝滑的页眉(Header)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…...

JVM线程分析详解

java线程状态&#xff1a; 初始(NEW)&#xff1a;新创建了一个线程对象&#xff0c;但还没有调用start()方法。运行(RUNNABLE)&#xff1a;Java线程中将就绪&#xff08;ready&#xff09;和运行中&#xff08;running&#xff09;两种状态笼统的称为“运行”。 线程对象创建…...

【备赛】点亮LED

LED部分的原理图 led前面有锁存器&#xff0c;这是为了防止led会受到lcd的干扰&#xff08;lcd也需要用到这些引脚&#xff09;。 每次想要对led操作&#xff0c;就需要先打开锁存器&#xff0c;再执行操作&#xff0c;最后关闭锁存器。 这里需要注意的是&#xff0c;引脚配置…...

【音视频】编解码相关概念总结

NALU RTP PS流 三者总体关系 NALU在RTP中的应用&#xff1a;视频流的RTP传输通常将NALU作为基本的单元进行传输。每个RTP包携带一个或多个NALU&#xff0c;这些NALU包含了视频编码数据。RTP协议通过其头部信息&#xff08;如时间戳、序列号等&#xff09;帮助接收端重新排列和…...

Python爬虫(四)- Selenium 安装与使用教程

文章目录 前言一、简介及安装1. Selenium 简介2. Selenium 安装 二、Selenium 基本使用1. 导入Selenium2. 启动浏览器3. 打开网页4. 获取页面标题5. 关闭浏览器6. 完整示例代码 三、Selenium WebDriver1. 简介2. 基本操作2.1 启动浏览器2.2 关闭浏览器2.3 打开网页2.4 关闭当前…...

Node.js项目启动流程以及各个模块执行顺序详解

Node.js项目启动流程以及各个模块执行顺序的问题。首先&#xff0c;我需要仔细阅读并理解我搜索到的资料&#xff0c;从中提取关键信息&#xff0c;然后综合这些信息组织成一个结构化的回答。 首先&#xff0c;根据我搜索到的资料都详细描述了Node.js的启动流程&#xff0c;涉及…...

各种类型网络安全竞赛有哪些 网络安全大赛的简称

本文是对入门学习的一些概念了解和一些常规场景记录 1.CTF&#xff08;capture the flag&#xff09;是夺旗赛的意思。 是网络安全技术人员之间进行攻防的比赛。 起源1996年DEFCON全球黑客大会&#xff0c;替代之前真实攻击的技术比拼。 (DEFCON极客大会诞生1993&#xff0c;…...

浅谈人工智能与深度学习的应用案例研究

人工智能与深度学习的应用案例研究 人工智能(AI)与深度学习技术正以惊人的速度渗透到社会生活的各个领域,从医疗健康到艺术创作,从金融风控到城市治理,其应用案例不断突破传统边界。以下是近年来具有代表性的六大应用方向及具体案例: 一、医疗健康:精准诊断与药物研发 医…...

vue2版本elementUI的table分页实现多选逻辑

1. 需求 我们需要在表格页上实现多选要求&#xff0c;该表格支持分页逻辑。 2. 认识属性 表格属性 参数说明类型可选值默认值data显示的数据array——row-key行数据的 Key&#xff0c;用来优化 Table 的渲染&#xff1b;在使用 reserve-selection 功能与显示树形数据时&…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...