一篇文章让你了解“JWT“
一.JWT简介
1.概念
JWT (JSON Web Token) 是一种用于在网络上安全传输信息的开放标准(RFC 7519)。它是一种紧凑且自包含的方式,用于在不同组件之间传递信息,通常用于身份验证和授权目的。JWT 是以 JSON 格式编码的令牌,它包含了声明(claims),并使用数字签名或加密来验证其完整性
2.组成
-
Header(头部):头部通常包括两部分信息,标明该令牌的类型("typ")以及所使用的签名算法("alg")。例如:
{ "alg": "HS256","typ": "JWT" }在头部中,通常也可以指定使用非对称加密算法(例如RSA)来进行签名或加密。
-
Payload(负载):负载包含了一组声明,这些声明描述了令牌的一些信息。有三种类型的声明:
- Registered Claims(注册声明):这些是一些预定义的声明,包括 iss(令牌的发行者)、sub(主题)、aud(受众)、exp(过期时间)、nbf(生效时间)、iat(发布时间)等。
- Public Claims(公共声明):这些声明可以由令牌的发行者和使用者协商定义。
- Private Claims(私有声明):这些是自定义的声明,用于在双方之间共享信息。
例如:
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 } -
Signature(签名):签名用于验证令牌的完整性和真实性。签名是通过使用头部中指定的签名算法以及密钥来计算的。它可以防止令牌被篡改。签名是在头部和负载的 Base64 编码字符串上计算的,例如:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)这个签名将会附加在令牌的末尾,形成最终的JWT,如:
header.payload.signature。
3.JWT 的主要优势
- 自包含:JWT 包含了所有必要的信息,不需要在服务器端存储会话信息。
- 可验证:接收方可以验证令牌的完整性和真实性,因为签名是依靠密钥计算的。
- 跨域:JWT 可以在不同域之间传递,因为它是一种标准格式。
- 扩展性:可以包含自定义声明,适用于各种不同的应用场景。
- 轻量级:JWT 是一种紧凑的数据格式,易于传输和处理。
然而,要注意的是,JWT 令牌的安全性高度依赖于密钥的安全性。如果密钥泄露,那么攻击者可能能够伪造有效的JWT。因此,必须妥善保管密钥,并使用适当的安全措施来保护JWT。
二.JWT的工具类
package com.YU.ssm.jwt;import java.util.Date;
import java.util.Map;
import java.util.UUID;import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;import org.apache.commons.codec.binary.Base64;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;/*** JWT验证过滤器:配置顺序 CorsFilte->JwtUtilsr-->StrutsPrepareAndExecuteFilter**/
public class JwtUtils {/*** JWT_WEB_TTL:WEBAPP应用中token的有效时间,默认30分钟*/public static final long JWT_WEB_TTL = 30 * 60 * 1000;/*** 将jwt令牌保存到header中的key*/public static final String JWT_HEADER_KEY = "jwt";// 指定签名的时候使用的签名算法,也就是header那部分,jwt已经将这部分内容封装好了。private static final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256;private static final String JWT_SECRET = "f356cdce935c42328ad2001d7e9552a3";// JWT密匙private static final SecretKey JWT_KEY;// 使用JWT密匙生成的加密keystatic {byte[] encodedKey = Base64.decodeBase64(JWT_SECRET);JWT_KEY = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");}private JwtUtils() {}/*** 解密jwt,获得所有声明(包括标准和私有声明)* * @param jwt* @return* @throws Exception*/public static Claims parseJwt(String jwt) {Claims claims = Jwts.parser().setSigningKey(JWT_KEY).parseClaimsJws(jwt).getBody();return claims;}/*** 创建JWT令牌,签发时间为当前时间* * @param claims* 创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)* @param ttlMillis* JWT的有效时间(单位毫秒),当前时间+有效时间=过期时间* @return jwt令牌*/public static String createJwt(Map<String, Object> claims, long ttlMillis) {// 生成JWT的时间,即签发时间 2021-10-30 10:02:00 -> 30 10:32:00long nowMillis = System.currentTimeMillis();//链式语法:// 下面就是在为payload添加各种标准声明和私有声明了// 这里其实就是new一个JwtBuilder,设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。// 可以在未登陆前作为身份标识使用.setId(UUID.randomUUID().toString().replace("-", ""))// iss(Issuser)签发者,写死.setIssuer("YU")// iat: jwt的签发时间.setIssuedAt(new Date(nowMillis))// 代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可放数据{"uid":"zs"}。此处没放// .setSubject("{}")// 设置签名使用的签名算法和签名使用的秘钥.signWith(SIGNATURE_ALGORITHM, JWT_KEY)// 设置JWT的过期时间.setExpiration(new Date(nowMillis + ttlMillis));return builder.compact();}/*** 复制jwt,并重新设置签发时间(为当前时间)和失效时间* * @param jwt* 被复制的jwt令牌* @param ttlMillis* jwt的有效时间(单位毫秒),当前时间+有效时间=过期时间* @return*/public static String copyJwt(String jwt, Long ttlMillis) {//解密JWT,获取所有的声明(私有和标准)//oldClaims claims = parseJwt(jwt);// 生成JWT的时间,即签发时间long nowMillis = System.currentTimeMillis();// 下面就是在为payload添加各种标准声明和私有声明了// 这里其实就是new一个JwtBuilder,设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。// 可以在未登陆前作为身份标识使用//.setId(UUID.randomUUID().toString().replace("-", ""))// iss(Issuser)签发者,写死// .setIssuer("zking")// iat: jwt的签发时间.setIssuedAt(new Date(nowMillis))// 代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可放数据{"uid":"zs"}。此处没放// .setSubject("{}")// 设置签名使用的签名算法和签名使用的秘钥.signWith(SIGNATURE_ALGORITHM, JWT_KEY)// 设置JWT的过期时间.setExpiration(new Date(nowMillis + ttlMillis));return builder.compact();}
}
1.工具类解析
1.初始化相关信息
-
JWT_WEB_TTL常量:定义了JWT令牌的有效时间,单位是毫秒,默认为30分钟。这个常量指定了在WEBAPP应用中生成的JWT令牌的有效期限。 -
JWT_HEADER_KEY常量:定义了JWT令牌在HTTP请求的头部中的键名。在HTTP请求的头部中,JWT令牌会作为值与这个键名相关联,用于传递JWT令牌。 -
SIGNATURE_ALGORITHM常量:指定了在JWT中使用的签名算法。在这个例子中,使用了HS256(HMAC SHA-256)签名算法。HS256是一种使用密钥进行签名和验证的算法。 -
JWT_SECRET常量:指定了用于生成JWT签名的密钥。在这个例子中,密钥是一个字符串,用于生成JWT签名。请注意,实际应用中应该将密钥存储在安全的地方,不建议硬编码在代码中。 -
JWT_KEY常量:使用JWT_SECRET密钥生成的加密key。这个key用于在生成JWT签名时进行加密。 -
静态块:这个类中的静态块用来初始化
JWT_KEY。在静态块中,JWT_SECRET字符串经过Base64解码,并使用解码后的字节数组创建了一个SecretKeySpec对象,用于生成JWT签名时的加密key。
2.解密JWT令牌
-
使用
Jwts.parser()创建一个JWT解析器对象。 -
使用
.setSigningKey(JWT_KEY)方法将JWT解析器配置为使用特定的密钥JWT_KEY来验证JWT令牌的签名。这是为了确保JWT令牌的完整性和真实性。 -
使用
.parseClaimsJws(jwt)方法来解析传入的JWT令牌jwt,并将其转换为Jws<Claims>对象。Jws表示JWT令牌的完整签名结构,包括头部、负载和签名。 -
最后,使用
.getBody()方法从Jws对象中获取JWT令牌的声明部分,这些声明包括标准声明(例如iss、sub、exp等)以及任何自定义的私有声明。这些声明将被包装在一个Claims对象中。
如果JWT解析成功,将返回包含声明的Claims对象,如果JWT解析成功,将返回包含声明的Claims对象
3.创建JWT令牌
-
获取当前时间的时间戳,用作JWT令牌的签发时间。
-
使用
JwtBuilder对象创建JWT令牌,采用链式语法。 -
使用
.setClaims(claims)方法设置JWT的声明部分,包括标准声明和自定义的私有声明。claims参数是一个包含声明信息的Map对象。 -
使用
.setId()方法设置JWT的唯一标识,通常用于防止重放攻击。 -
使用
.setIssuer("YU")方法设置JWT的签发者。 -
使用
.setIssuedAt()方法设置JWT的签发时间。 -
使用
.signWith(SIGNATURE_ALGORITHM, JWT_KEY)方法来对JWT进行签名,SIGNATURE_ALGORITHM表示签名算法,JWT_KEY表示用于签名的密钥。 -
使用
.setExpiration()方法设置JWT的过期时间,即JWT的有效期。 -
最后,使用
.compact()方法将JWT令牌压缩为字符串并返回
4. 复制jwt
-
方法签名:这个方法被定义为
public static String copyJwt(String jwt, Long ttlMillis),它接受两参数:jwt是要被复制的JWT令牌,ttlMillis是JWT的有效时间,以毫秒为单位。ttlMillis会被用来计算新JWT的失效时间。 -
解密JWT:在方法内部的第一行,代码调用了
parseJwt(jwt)函数来解密jwt,并将其内容提取为声明(claims),包括标准声明和私有声明。 -
签发时间(Issued At - iat):在JWT的payload(令牌的主体部分)中,设置了签发时间,即
iat。这个时间用System.currentTimeMillis()获取当前时间,然后作为JWT的签发时间。 -
JWT的构建:接下来,通过
JwtBuilder对象来构建一个新的JWT。这个对象会包含JWT的各种声明。 -
私有声明:在JWT中,你可以包含一些自定义的私有声明,用来存储额外的信息。在这个代码中,通过
.setClaims(claims)将之前解密的声明添加到JWT的payload中。 -
唯一标识(JWT ID - jti):这段代码注释掉了唯一标识声明的设置,但你可以根据需要取消注释,并为每个JWT生成一个唯一的标识。
-
签发者(Issuer - iss):签发者声明通常是JWT的签发者,这里被写死为"zking"。
-
签名算法和秘钥:使用
.signWith(SIGNATURE_ALGORITHM, JWT_KEY)设置JWT的签名算法和秘钥,以确保JWT的完整性和安全性。 -
失效时间:最后,通过
.setExpiration(new Date(nowMillis + ttlMillis))设置JWT的失效时间。失效时间是签发时间加上有效时间(ttlMillis)。 -
返回值:最后,使用
builder.compact()将JWT构建为一个紧凑的字符串表示,并返回这个字符串。
2.JWT测试
package com.YU.ssm.service.impl;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;import com.YU.ssm.jwt.JwtUtils;
import io.jsonwebtoken.Claims;
import org.junit.*;public class JwtDemo {private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");@Testpublic void test1() {// 生成JWT//JWT Token=Header.Payload.Signature//头部.载荷.签名//Payload=标准声明+私有声明+公有声明//定义私有声明Map<String, Object> claims = new HashMap<String, Object>();claims.put("username", "zss");claims.put("age", 18);//TTL:Time To LiveString jwt = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL);System.out.println(jwt);//获取Payload(包含标准和私有声明)Claims parseJwt = JwtUtils.parseJwt(jwt);for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());}Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}@Testpublic void test2() {// 解析oldJwt//io.jsonwebtoken.ExpiredJwtException:JWT过期异常//io.jsonwebtoken.SignatureException:签名异常//String oldJwt="eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1OTA3MTg2NzcsImlhdCI6MTU5MDcxNjg3NywiYWdlIjoxOCwianRpIjoiNDFmZjFiZGFkYzkxNDA3OGE4ZGUyNGRkZDEwYjU4N2IiLCJ1c2VybmFtZSI6InpzcyJ9.DdPvioX6kuhV6lEfD9QAN2eQSk_mO3dYkmDmTQsqa78";//eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MzU1NjE3MjcsImlhdCI6MTYzNTU1OTkyNywiYWdlIjoxOCwianRpIjoiN2RlYmIzM2JiZTg3NDBmODgzNDI5Njk0ZWE4NzcyMTgiLCJ1c2VybmFtZSI6InpzcyJ9.dUR-9JUlyRdoYx-506SxXQ3gbHFCv0g5Zm8ZGzK1fzwString newJwt="eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ6a2luZyIsImV4cCI6MTY2MjM0Njg3MSwiaWF0IjoxNjYyMzQ1MDcxLCJhZ2UiOjE4LCJqdGkiOiI4YjllNzc3YzFlMDM0MjViYThmMDVjNTFlMTU3NDQ1MiIsInVzZXJuYW1lIjoienNzIn0.UWpJxPxwJ09PKxE2SY5ME41W1Kv3jP5bZGKK-oNUDuM";String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MzU1NjE3MjcsImlhdCI6MTYzNTU1OTkyNywiYWdlIjoxOCwianRpIjoiN2RlYmIzM2JiZTg3NDBmODgzNDI5Njk0ZWE4NzcyMTgiLCJ1c2VybmFtZSI6InpzcyJ9.dUR-9JUlyRdoYx-506SxXQ3gbHFCv0g5Zm8ZGzK1fzw";Claims parseJwt = JwtUtils.parseJwt(newJwt);for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());}Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}@Testpublic void test3() {// 复制jwt,并延时30分钟String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ6a2luZyIsImV4cCI6MTY2MjM0Njg3MSwiaWF0IjoxNjYyMzQ1MDcxLCJhZ2UiOjE4LCJqdGkiOiI4YjllNzc3YzFlMDM0MjViYThmMDVjNTFlMTU3NDQ1MiIsInVzZXJuYW1lIjoienNzIn0.UWpJxPxwJ09PKxE2SY5ME41W1Kv3jP5bZGKK-oNUDuM";//String newJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDU3NTM2NTUsImlhdCI6MTYwNTc1MTg1NSwiYWdlIjoxOCwianRpIjoiYmNmN2Q1MzQ2YjE3NGU2MDk1MmIxYzQ3ZTlmMzQyZjgiLCJ1c2VybmFtZSI6InpzcyJ9.m1Qn84RxgbKCnsvrdbbAnj8l_5Jwovry8En0j4kCxhc";//String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjI5MDMzNjAsImlhdCI6MTU2MjkwMTU2MCwiYWdlIjoxOCwianRpIjoiZDVjMzE4Njg0MDcyNDgyZDg1MDE5ODVmMDY3OGQ4NjkiLCJ1c2VybmFtZSI6InpzcyJ9.XDDDRRq5jYq5EdEBHtPm7GcuBz4S0VhDTS1amRCdf48";String newJwt = JwtUtils.copyJwt(oldJwt, JwtUtils.JWT_WEB_TTL);System.out.println(newJwt);Claims parseJwt = JwtUtils.parseJwt(newJwt);for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());}Date d1 = parseJwt.getIssuedAt();Date d2 = parseJwt.getExpiration();System.out.println("令牌签发时间:" + sdf.format(d1));System.out.println("令牌过期时间:" + sdf.format(d2));}}
1.测试方法1
运行结果

当我们通过携带身份信息运行时会获得jwt值并携带它的一个签发时间和过期值
2.测试方法2
我们可以通过token值来解析获取到令牌的信息以及签发时间和过期时间,但是只能获取到还未过期的令牌
当我们使用已经过期的令牌时会抛出异常
例:
1.已过期令牌

2.未过期令牌

使用未过期令牌即可获取它的登录信息值以及它的签发时间和过期时间
3.测试方法3
复制延长jwt值的有效时间

可以对比上面的令牌时间,我们使用同一个令牌进行延长时间
三.JWT集成spa项目
1.定义好jwt的基本信息
1.1定义变量
export default {TName:'YU',jwt:''
}
1.2 基本get、set方法
setJWT:(state,payload)=>{state.jwt = payload.jwt;}
getJWT:(state)=>{return state.jwt;}
2.存值
2.1 在响应拦截器和请求拦截器中将响应头中的jwt串放入state.js中
// 请求拦截器
axios.interceptors.request.use(function(config) {let jwt = window.vm.$store.getters.getJWT;if(jwt){config.headers['jwt'] = jwt;}return config;
}, function(error) {return Promise.reject(error);
});// 响应拦截器
axios.interceptors.response.use(function(response) {let jwt = response.headers['jwt'];if(jwt){window.vm.$store.commit('setJWT',{jwt:jwt});}return response;
}, function(error) {return Promise.reject(error);
});
2.2执行效果
我们在登录之后的userLogin包中会展示我们的jwt值

相关文章:
一篇文章让你了解“JWT“
一.JWT简介 1.概念 JWT (JSON Web Token) 是一种用于在网络上安全传输信息的开放标准(RFC 7519)。它是一种紧凑且自包含的方式,用于在不同组件之间传递信息,通常用于身份验证和授权目的。JWT 是以 JSON 格式编码的令牌ÿ…...
HJ73 计算日期到天数转换
HJ73 计算日期到天数转换 int main() {int year, month, day;cin >> year >> month >> day;int monthDays[13] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };int nday monthDays[month - 1] day;if (month > 2 &&((year…...
Unity实现设计模式——适配器模式
Unity实现设计模式——适配器模式 适配器模式又称为变压器模式、包装模式(Wrapper) 将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。 在一个在役的项目期望在原有接口的基础…...
【2023年11月第四版教材】专题1 - 计算题考点汇总 (合集篇)
专题1 - 计算题考点汇总 (合集篇) 1 进度类1.1 PERT三点估算1.1.1 β分布1.1.2 三角分布 1.2 单代号网络图1.2.1 画图1.2.2 找关键路径1.2.3 计算总工期1.2.4 总时差1.2.5 自由时差1.2.6 工期压缩 1.3 双代号网络图1.4 双代号时标网络图1.4.1 画图1.4.2 找关键路径1…...
系统架构设计:17 论信息系统的安全性与保密性设计
目录 一 信息安全基础 1 信息安全的基本要素 2 信息安全的范围 3 网络安全...
使用EasyDarwin+ffmpeg+EasyPlayerPro完成rtsp的推流操作和拉流操作
本文分享在做视频类测试过程中所用到的工具EasyDarwinffmpegEasyPlayerPro 首先说一下EasyDarwin,简单来讲,它就是个推流和拉流及系统消耗的监测软件,具体使用方法我会写在下方。 EasyDarwin 1、解压下载好的EasyDarwin压缩包,并找到EasyD…...
FPGA project : flash_secter_erase
flash的指定扇区擦除实验。 先发写指令,再进入写锁存周期等待500ns,进入写扇区擦除指令,然后写扇区地址,页地址,字节地址。即可完成扇区擦除。 模块框图: 时序图: 代码: module…...
HarmonyOS/OpenHarmony原生应用-ArkTS万能卡片组件Radio
单选框,提供相应的用户交互选择项。该组件从API Version 8开始支持。无子组件。 一、接口 Radio(options: {value: string, group: string}) 从API version 9开始,该接口支持在ArkTS卡片中使用。 参数: 二、属性 除支持通用属性外,还支持以…...
python opencv 深度学习 指纹识别算法实现 计算机竞赛
1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 python opencv 深度学习 指纹识别算法实现 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分工作量:4分创新点:4分 该项目较为新颖…...
一图看懂CodeArts Inspector 三大特性,带你玩转漏洞管理服务
华为云漏洞管理服务CodeArts Inspector是面向软件研发和服务运维提供的一站式漏洞管理能力,通过持续评估系统和应用等资产,内置风险量化管理和在线风险分析处置能力,帮助组织快速感应和响应漏洞,并及时有效地完成漏洞修复工作&…...
【Mysql】Mysql的启动选项和系统变量(二)
概述 在Mysql的设置项中一般都有各自的默认值,比方说mysql 5.7服务器端允许同时连入的客户端的默认数量是 151 ,表的默认存储引擎是 InnoDB ,我们可以在程序启动的时候去修改这些默认值,对于这种在程序启动时指定的设置项也称之为…...
FPGA project : flash_read
实验目标: flash的普通读指令,在指定地址开始读。可以更改地址与读的数据个数。 先发送读指令扇区地址页地址字节地址。 然后读数据。再把读到的串行数据转化为8bit的数据,存入fifo。 然后读出FIFO中数据,通过uart_tx模块发送…...
nnunetv2训练报错 ValueError: mmap length is greater than file size
目录 报错解决办法 报错 笔者在使用 nnunetv2 进行 KiTS19肾脏肿瘤分割实验的训练步骤中 使用 2d 和3d_lowres 训练都没有问题 nnUNetv2_train 40 2d 0nnUNetv2_train 40 3d_lowres 0但是使用 3d_cascade_fullres 和 3d_fullres 训练 nnUNetv2_train 40 3d_cascade_fullres …...
React知识点系列(2)-每天10个小知识
目录 1. 如何优化 React 应用的性能?你用过哪些性能分析工具?2. 在 React 中,什么是 Context API?你在什么场景下会使用它?3. 你能解释一下什么是 React Fiber 吗?4. 在项目中,你是否使用过 Rea…...
AutoGPT:让 AI 帮你完成任务事情 | 开源日报 No.54
Significant-Gravitas/AutoGPT Stars: 150.4k License: MIT AutoGPT 是开源 AI 代理生态系统的核心工具包。它采用模块化和可扩展的框架,使您能够专注于以下方面: 构建 - 为惊人之作打下基础。测试 - 将您的代理调整到完美状态。查看 - 观察进展成果呈…...
USB 转串口芯片 CH340
目录 1、概述 2、特点 3、封装 4、引脚 6、参数 6.1 绝对最大值(临界或者超过绝对最大值将可能导致芯片工作不正常甚至损坏) 6.2 电气参数(测试条件:TA25℃,VCC5V,不包括连接 USB 总线的引脚&…...
Day 05 python学习笔记
循环 应用:循环轮播图 最基础、最核心 循环:周而复始,谓之循环 (为了代码尽量不要重复) while循环 while的格式 索引定义 while 表达式(只要结果为布尔值即可): 循环体 通过条件的不断变化,从…...
Python如何17行代码画一个爱心
🌈write in front🌈 🧸大家好,我是Aileen🧸.希望你看完之后,能对你有所帮助,不足请指正!共同学习交流. 🆔本文由Aileen_0v0🧸 原创 CSDN首发🐒 如…...
生产环境中常用Linux命令
太简单的我就不讲解啦,浪费时间,直接将生产中常用的 文章目录 1.总纲2.整机 top3.CPU vmstat3. 内存 free4. 硬盘: df5. 磁盘IO iostat6. 网络IO ifstat7: 内存过高的情景排查 1.总纲 整机:topcpu:vmstat内存:free硬盘:df磁盘io: iostat网络io:ifstat 2.整机 top 首先们要查…...
【使用 TensorFlow 2】03/3 创建自定义损失函数
一、说明 TensorFlow 2发布已经接近5年时间,不仅继承了Keras快速上手和易于使用的特性,同时还扩展了原有Keras所不支持的分布式训练的特性。3大设计原则:简化概念,海纳百川,构建生态.这是本系列的第三部分,…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

