SpringBoot + Vue 实现 AES 加密和 AES 工具类总结

目录

一、加密知识回顾 

AES加密模式

二、Java 自定义 AES 工具类 

三、SpringBoot 实现 AES 加密登陆

controller 层

server 层

四、Vue 实现 AES 加密登陆

五、前端AES工具类

六、实现结果


一、加密知识回顾 

        密钥是AES算法实现加密和解密的根本。对称加密算法之所以对称,是因为这类算法对明文的加密和解密需要使用同一个密钥。
AES支持三种长度的密钥:  128位,192位,256位 
平时大家所说的AES128,AES192,AES256,实际上就是指的AES算法对不同长度密钥的使用。从安全性来看,AES256 安全性最高。从性能来看,AES128 性能最高。本质原因是它们的加密处理轮数不同。

对称加密与非对称加密有什么区别,敏感数据怎么加解密和传输

AES加密模式

1 : ECB(Electronic Code Book电子密码本)模式
ECB模式是最早采用和最简单的模式,它将加密的数据分成若干组,每组的大小跟加密密钥长度相同,然后每组都用相同的密钥进行加密。


优点:1、简单;2:有利于并行计算;3、误差不会被传送; 
缺点:1、不能隐藏明文的模式;2、可能对明文进行主动攻击;
因此,此模式适于加密小消息。

2 : CBC(Cipher Block Chaining,加密块链)模式
优点:1、不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
缺点:1、不利于并行计算;2、误差传递;3、需要初始化向量IV

3 : CFB(Cipher FeedBack Mode,加密反馈)模式
优点:1、隐藏了明文模式;2、分组密码转化为流模式;3、可以及时加密传送小于分组的数据;
缺点:1、不利于并行计算;2、误差传送:一个明文单元损坏影响多个单元;3、唯一的IV;

4 : OFB(Output FeedBack,输出反馈)模式
优点:1、隐藏了明文模式;2、分组密码转化为流模式;3、可以及时加密传送小于分组的数据;
缺点:1、不利于并行计算;2、对明文的主动攻击是可能的;3、误差传送:一个明文单元损坏影响多个单元;

        ECB 不够安全,只适合于短数据的加密,而 CBC 和 CFB 相较于 ECB 更加安全,因为前一个密文块会影响当前明文块,使攻击者难以预测密文的结构。总的来说,选择 AES 的算法模式需要根据加密需要的安全性和速度来进行选择,通常推荐使用CBC 或 CFB 模式,而不是 ECB 模式。

二、Java 自定义 AES 工具类 

AES 算法在 Java 的 javax.crypto 包里有很好的封装,我们来看一下调用的方法:

public class AesSingleUtil {private static volatile AesSingleUtil aESUtil;private static String encodeRules = "9JLsB1ukY3o4mdTuuE90+Q==";private AesSingleUtil() {}public static AesSingleUtil getSingleton() {if (aESUtil == null) {Class var0 = AesSingleUtil.class;synchronized(AesSingleUtil.class) {if (aESUtil == null) {aESUtil = new AesSingleUtil();}}}return aESUtil;}public String AESEncode(String content) throws Exception {KeyGenerator keygen = KeyGenerator.getInstance("AES");keygen.init(128, new SecureRandom(encodeRules.getBytes()));SecretKey original_key = keygen.generateKey();byte[] raw = original_key.getEncoded();SecretKey key = new SecretKeySpec(raw, "AES");Cipher cipher = Cipher.getInstance("AES");cipher.init(1, key);byte[] byte_encode = content.getBytes("utf-8");byte[] byte_AES = cipher.doFinal(byte_encode);String AES_encode = new String(Base64.getEncoder().encode(byte_AES));return AES_encode;}public String AESDecode(String content) throws Exception {KeyGenerator keygen = KeyGenerator.getInstance("AES");keygen.init(128, new SecureRandom(encodeRules.getBytes()));SecretKey original_key = keygen.generateKey();byte[] raw = original_key.getEncoded();SecretKey key = new SecretKeySpec(raw, "AES");Cipher cipher = Cipher.getInstance("AES");cipher.init(2, key);byte[] byte_content = Base64.getDecoder().decode(content);byte[] byte_decode = cipher.doFinal(byte_content);String AES_decode = new String(byte_decode, "utf-8");return AES_decode;}
}

 AesSingleUtil 类:这是一个单例类,使用了双重检查锁(double-checked locking)实现按需延迟初始化。在 getSingleton 方法中,通过检查静态变量 aESUtil 是否为 null,来确定是否需要创建新的实例。通过单例模式确保了整个应用程序中只有一个实例存在,节省了资源并避免了不必要的重复创建对象。

encodeRules 变量:存储着用于生成 AES 密钥的编码规则。

AESEncode 方法:接受一个字符串作为参数,使用该字符串作为密钥的种子,生成 AES 密钥,并对输入的内容进行 AES 加密,最终返回 Base64 编码的加密结果。

AESDecode 方法:与 AESEncode 方法相对应,接受一个经过 Base64 编码的加密字符串作为参数,使用同样的密钥规则生成 AES 密钥,并对传入的加密字符串进行 AES 解密,返回解密后的原始字符串。

import com.ss.check.NotNullCheck;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class AesWebUtil {private static Logger log = LoggerFactory.getLogger(AesWebUtil.class);private static String KEY = "kl9o56u98gvjhw9i";private static String IV = "grjei564389tj843";public AesWebUtil() {}public String encrypt(String data, String key, String iv) {try {Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");int blockSize = cipher.getBlockSize();byte[] dataBytes = data.getBytes("UTF-8");int plaintextLength = dataBytes.length;if (plaintextLength % blockSize != 0) {plaintextLength += blockSize - plaintextLength % blockSize;}byte[] plaintext = new byte[plaintextLength];System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());cipher.init(1, keyspec, ivspec);byte[] encrypted = cipher.doFinal(plaintext);return (new Base64()).encodeToString(encrypted);} catch (Exception var12) {return null;}}public String desEncrypt(String data, String key, String iv) {try {byte[] encrypted1 = (new Base64()).decode(data.getBytes("UTF-8"));Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());cipher.init(2, keyspec, ivspec);byte[] original = cipher.doFinal(encrypted1);String originalString = new String(original);return originalString;} catch (Exception var10) {return null;}}public static String jiaMi(String data) {String mm = "";try {if (NotNullCheck.str(data)) {mm = (new AesWebUtil()).encrypt(data, KEY, IV).trim();}} catch (Exception var3) {}return mm;}public static String jieMi(String data) {String mm = "";try {if (NotNullCheck.str(data)) {mm = (new AesWebUtil()).desEncrypt(data, KEY, IV).trim();}} catch (Exception var3) {}return mm;}public static void main(String[] args) throws Exception {String jiemi = (new AesWebUtil()).desEncrypt("oLlc7AJnsgl93vaAEYMgGd2/G8zLFX8HrCN9HaBwS9rLJYFT8+RmlReuNHHdX+NacpP6MAByLIdxSeMBQ/9a5HA1oikanQY5I1kTCxpaN639WvA/Rj8I74PicVYemYqiMr/W6dDwpyJt7H5jL7Sofw6bnNmQAtsF9UNQthDS73ddxo19ThLpxOajVE5LF+Mu", KEY, IV).trim();System.out.println("解密:" + jiemi);new AesWebUtil();String jiami = jiaMi("123456");System.out.println("加密:" + jiami);}
}

三、SpringBoot 实现 AES 加密登陆

controller 层

    @PostMapping("login")public String userLogin(@RequestBody String user, HttpServletRequest request) {return userService.userLogin(user, request);}

server 层

    public String userLogin(String user, HttpServletRequest request) {String jiemiUserStr = null;try {jiemiUserStr = AesWebUtil.jieMi(user);} catch (Exception e) {throw new SSError(GlobalCodeEnum.SystemLogicError, "非法登录!");}UserAll userAll = GsonUtil.jsonToObject(jiemiUserStr, UserAll.class);if (userAll != null && userAll.getLoginType() != null) {UserAll loginBack = null;if (userAll.getLoginType() == 1 && NotNullCheck.str(userAll.getUserLoginName())&& NotNullCheck.str(userAll.getUserPassword())) {loginBack = userMapper.getUserByLoginName(userAll.getUserLoginName());if(loginBack==null){throw new SSError(GlobalCodeEnum.SystemLogicError, "用户不存在");}else if(loginBack!=null&&!AesWebUtil.jiaMi(userAll.getUserPassword()).equals(loginBack.getUserPassword())){throw new SSError(GlobalCodeEnum.SystemLogicError, "密码不正确");}} else if (userAll.getLoginType() == 2 && NotNullCheck.str(userAll.getUserCard())) {loginBack = userMapper.getUserByUserCard(userAll);}if (loginBack == null) {throw new SSError(GlobalCodeEnum.SystemLogicError, "登录信息错误");} else {checkUserRightState(loginBack);try {loginBack.setUserPassword(JwtUtil.generateToken());} catch (Exception e) {e.printStackTrace();}
//                log.info("****************登录成功:" + loginBack);//埋点登录return AesWebUtil.jiaMi(GsonUtil.objectToJson(loginBack));}}throw new SSError(GlobalCodeEnum.SystemLogicError, "登录信息不完整");}

四、Vue 实现 AES 加密登陆

<template><common-layout><div class="top"><div class="header"><img alt="logo" class="logo" src="@/assets/img/logo.png" /><span class="title">{{ systemName }}</span></div><div class="desc"></div></div><div class="login"><a-form @submit.native="onSubmit" :form="form"><a-tabssize="large":tabBarStyle="{ textAlign: 'center' }"style="padding: 0 2px"@change="userLoginTypeChange"><a-tab-pane tab="账户密码登录" key="1"><a-alerttype="error":closable="true"v-show="error":message="error"showIconstyle="margin-bottom: 24px"/><a-form-item><a-inputref="userNameRef"autocomplete="autocomplete"size="large"allowClearplaceholder="登录用户名"v-decorator="['name',{rules: [{required: true,message: '请输入账户名',whitespace: true,},],},]"><a-icon slot="prefix" type="user" /></a-input></a-form-item><a-form-item><a-inputsize="large"placeholder="登录密码"autocomplete="autocomplete"type="password"allowClearv-decorator="['password',{rules: [{required: true,message: '请输入密码',whitespace: true,},],},]"><a-icon slot="prefix" type="lock" /></a-input></a-form-item></a-tab-pane><a-tab-pane tab="工号登录" key="2"><a-form-item><a-inputsize="large"placeholder="员工工号"v-model="userCard"ref="userCardRef"allowClear><a-icon slot="prefix" type="solution" /></a-input></a-form-item><!-- <a-form-item> --><!-- <a-row :gutter="8" style="margin: 0 -4px"><a-col :span="16"> --><!--   <a-input size="large" placeholder="captcha"><a-icon slot="prefix" type="lock" /></a-input> --><!-- </a-col> --><!-- <a-col :span="8" style="padding-left: 4px"><a-buttonstyle="width: 100%"class="captcha-button"size="large">获取验证码</a-button></a-col> --><!-- </a-row> --><!-- </a-form-item> --></a-tab-pane></a-tabs><!-- <div><a-checkbox :checked="true">自动登录</a-checkbox></div> --><a-form-item><a-button:loading="logging"style="width: 100%; margin-top: 24px"size="large"htmlType="submit"type="primary">登录</a-button></a-form-item></a-form></div></common-layout>
</template><script>
import CommonLayout from "@/layouts/CommonLayout";
// import { login, getRoutesConfig } from "@/services/user";
// import { setAuthorization } from "@/utils/request";
// import { loadRoutes } from "@/utils/routerUtil";import { mapMutations } from "vuex";
import { userLogin } from "@/api/user";import { aesJiami, aesJiemi } from "@/utils/aes";const timeList = ["早上好", "上午好", "中午好", "下午好", "晚上好"];export default {name: "Login",components: { CommonLayout },data() {return {logging: false,error: "",form: this.$form.createForm(this),userLgoinType: 1,userCard: "",};},computed: {systemName() {return this.$store.state.setting.systemName;},},mounted() {// 禁用浏览器返回键history.pushState(null, null, document.URL);window.addEventListener("popstate", this.disableBrowserBack);if (this.$refs.userNameRef) {this.$refs.userNameRef.focus();}},destroyed() {// 清除popstate事件 否则会影响到其他页面window.removeEventListener("popstate", this.disableBrowserBack, false);},methods: {...mapMutations("account", ["setUser", "setPermissions", "setRoles"]),disableBrowserBack() {history.pushState(null, null, document.URL);},userLoginTypeChange(key) {setTimeout(() => {if (key === "1") {this.$refs.userNameRef.focus();} else if (key === "2") {this.$refs.userCardRef.focus();}}, 100);this.userLgoinType = key;},onSubmit(e) {e.preventDefault();let checkUserLoginInput = false;if (this.userLgoinType === 1) {this.form.validateFields((err) => {if (!err) {checkUserLoginInput = true;}});} else {if (this.userCard &&this.userCard.replace(/↵/g, "").replace(/[/n/r]/g, "")) {checkUserLoginInput = true;}}if (!checkUserLoginInput) {return;}this.logging = true;const name = this.form.getFieldValue("name");const password = this.form.getFieldValue("password");// login(name, password).then(this.afterLogin);const userLoginInfo = {userLoginName: name,userPassword: password,userCard: this.userCard,loginType: this.userLgoinType,};userLogin(aesJiami(JSON.stringify(userLoginInfo))).then((res) => {if (!res) {return;}try {res = JSON.parse(aesJiemi(res));} catch (error) {this.$message.error("登录失败,服务器校验不通过");return;}let permissions = null;if (res) {permissions = [{ id: res.userAuth, operation: ["add", "edit"] }];if (!permissions) {this.$message.error("用户权限校验失败");return;}this.setPermissions(aesJiami(JSON.stringify(permissions)));this.$router.push({ name: "主页" });const time = new Date();const hour = time.getHours();const welcomeTime =hour < 9? timeList[0]: hour <= 11? timeList[1]: hour <= 13? timeList[2]: hour <= 17? timeList[3]: timeList[4];this.$message.success(welcomeTime + "," + res.userName);const roles = [{ id: res.userAuth, operation: ["add", "edit", "delete"] },];res.name = res.userName;this.setRoles(aesJiami(JSON.stringify(roles)));this.setUser(aesJiami(JSON.stringify(res)));}}).finally(() => {this.logging = false;});},/*  afterLogin(res) {this.logging = false;const loginRes = res.data;if (loginRes.code >= 0) {const { user, permissions, roles } = loginRes.data;this.setUser(user);this.setPermissions(permissions);this.setRoles(roles);setAuthorization({token: loginRes.data.token,expireAt: new Date(loginRes.data.expireAt),});// 获取路由配置getRoutesConfig().then((result) => {const routesConfig = result.data.data;loadRoutes(routesConfig);this.$router.push("/dashboard/workplace");this.$message.success(loginRes.message, 3);});} else {this.error = loginRes.message;}}, */},
};
</script><style lang="less" scoped>
.common-layout {.top {text-align: center;.header {height: 44px;line-height: 44px;a {text-decoration: none;}.logo {height: 44px;vertical-align: top;margin-right: 16px;}.title {font-size: 33px;color: @title-color;font-family: "Myriad Pro", "Helvetica Neue", Arial, Helvetica,sans-serif;font-weight: 600;position: relative;top: 2px;}}.desc {font-size: 14px;color: @text-color-second;margin-top: 12px;margin-bottom: 40px;}}.login {width: 368px;margin: 0 auto;@media screen and (max-width: 576px) {width: 95%;}@media screen and (max-width: 320px) {.captcha-button {font-size: 14px;}}.icon {font-size: 24px;color: @text-color-second;margin-left: 16px;vertical-align: middle;cursor: pointer;transition: color 0.3s;&:hover {color: @primary-color;}}}
}
</style>

五、前端AES工具类

import CryptoJS from "crypto-js";const KEY = CryptoJS.enc.Utf8.parse("kl9o56u98gvjhw9i");
const IV = CryptoJS.enc.Utf8.parse("grjei564389tj843");export const aesJiami = (word, keyStr, ivStr) => {let key = KEY;let iv = IV;if (keyStr) {key = CryptoJS.enc.Utf8.parse(keyStr);iv = CryptoJS.enc.Utf8.parse(ivStr);}let srcs = CryptoJS.enc.Utf8.parse(word);var encrypted = CryptoJS.AES.encrypt(srcs, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.ZeroPadding,});// console.log("-=-=-=-", encrypted.ciphertext)return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
};export const aesJiemi = (word, keyStr, ivStr) => {let key = KEY;let iv = IV;if (keyStr) {key = CryptoJS.enc.Utf8.parse(keyStr);iv = CryptoJS.enc.Utf8.parse(ivStr);}let base64 = CryptoJS.enc.Base64.parse(word);let src = CryptoJS.enc.Base64.stringify(base64);var decrypt = CryptoJS.AES.decrypt(src, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.ZeroPadding,});var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);return decryptedStr.toString();
};

 这段前端代码的逻辑是:

  1. 导入 CryptoJS 库:通过 import CryptoJS from "crypto-js"; 这行代码导入了 CryptoJS 库,用于进行加密和解密操作。

  2. 定义加密所需的密钥和向量:

    KEY 和 IV 分别是用于加密和解密的密钥和初始化向量。在这段代码中,它们被硬编码为固定值。
  3. 定义 aesJiami 函数:

    aesJiami 函数用于对传入的字符串进行加密操作。如果有自定义的密钥和向量参数,则使用传入的参数,否则使用预设的 KEY 和 IV。将传入的字符串转换为 UTF-8 编码格式。使用 AES 加密算法对字符串进行加密,加密模式为 CBC,填充方式为 ZeroPadding。将加密后的结果转换为 Base64 字符串并返回。
  4. 定义 aesJiemi 函数:

    aesJiemi 函数用于对传入的 Base64 加密字符串进行解密操作。如果有自定义的密钥和向量参数,则使用传入的参数,否则使用预设的 KEY 和 IV。将传入的 Base64 加密字符串解析为 Base64 对象。使用 AES 解密算法对 Base64 对象进行解密,解密模式为 CBC,填充方式为 ZeroPadding。将解密后的结果转换为 UTF-8 编码格式的字符串并返回。

        总的来说,这段代码实现了对字符串的 AES 加密和解密操作,使用了 CryptoJS 库提供的加密算法和相关函数。通过传入不同的参数,可以实现自定义密钥和向量进行加密解密的功能

六、实现结果

{"reqID": 1,"method": "","sender": "ss-smartdata-web-browser Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0","token": "Bearer eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE3MTg5MzkzNzl9.FcPMd60PZQJ8TBrkRZLf3gL76Vr1w9paSfgZPYZlDKNT0h74_zF8Wa8DwrB0Gciw-zneaBtUc1CBAa6yF2RmRQ","reqData": "cThk+vaRL/B41LkCUVrshuT0R8xfnKGh56D+NeqC6HC2PdfcWwFL5RU3gY/sjsc39e156rj29ryANn1LZ29pL5bfN6EIq2oVuqC34GQeu7g="
}

{result: 1, reqID: -1, respID: -1, sender: "", sendee: "", msg: "请求成功",…
}msg : "请求成功"
reqID : -1
respData:"nWOD3Sw2iLf1xevNYnHuHGvPFr/TAJpviyh/M22qLYuiaHoqvxhCn9OF2WGitiKr+LxTbEJvuBsbCmetAPCo7b48WG0PzsHz3fQxlOsQKeh629Z18gyBKho4zEAayHHjhP4rrHjSNNTwoZzAD0n6Cj2HTx+COXH9KtL905HZC3y0+mn1n72BCN2nxVExAu+8cBP+N66MJWVQLyj+7ENWJ0Euq22v3xWWoX2fFKe2XZr8Y7taMRkSNEyfYpgyq3Tl1az7A3I6+eYdpuYndBlxe0m7K6qOgckjni4l9ApIN16P7947Y5LXPY3wHsKVs1t0NKERnNzUTE/aD5einOv/pE3HdZAujtigOHwmihwrhHbTeumSYTC02kbtKUHNlR3lw+GsKR/727sCvkNhYnqz3uXjfJHYmghJJjL20XmPzpr5GJaohr3f4ZcoABv5G3dy"
respID : -1
result : 1
sendee : ""
sender: ""

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最新SCI算法:常青藤优化算法(IVY)原理及应用 Python代码

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类算法的家人&#xff0c;可关注我的VX公众号&#xff1a;python算法小当家&#xff0c;不定期会有很多免费代码分享~ 最新SCI算法&#xff1a;常青藤优化算法&#xff08;IVY&…

浏览器提升编译速度小技巧(一)- 防病毒排除

1.引言 在Chrome开发过程中&#xff0c;编译速度是影响开发效率的关键因素之一。编译一个大型项目如Chrome&#xff0c;往往需要处理大量的代码文件和依赖库&#xff0c;这个过程既复杂又耗时。因此&#xff0c;任何能够提升编译速度的技巧&#xff0c;都能显著提高开发效率&a…

如何使用Python和PaddleOCR轻松识别图片中的文字

在这个数字化时代&#xff0c;文本识别技术变得越来越重要&#xff0c;它广泛应用于文档自动化处理、内容审核、智能交互等场景。本文将引导你如何使用Python结合PaddleOCR库&#xff0c;轻松实现图片中的文字识别功能。 必备工具包安装 在开始编写代码之前&#xff0c;你需要…

Cephalo:专门用于仿生设计的多模态视觉大型语言模型

实时了解业内动态&#xff0c;论文是最好的桥梁&#xff0c;专栏精选论文重点解读热点论文&#xff0c;围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;…

什么是响应式编程

我们知道&#xff0c;当系统面对大流量、高并发的访问请求时&#xff0c;就可能会出现一系列性能问题&#xff0c;导致服务丧失了即时的响应性。如何时刻确保系统具有应对请求压力的能力&#xff0c;是架构设计的核心问题之一。 经典的服务隔离、限流、降级以及熔断等机制能够在…

2024全国各地高考录取分数线一览表(含一本、二本、专科)

2024年高考录取分数线陆续公布&#xff0c;上大学网(www.sdaxue.com)为大家整理全国31个省市高考录取分数线汇总&#xff0c;包括本科批、专科批和特殊类招生控制分数线汇总&#xff0c;来看看你的省份多少分能上大学吧。 一、2024年全国高考录取线一览表 1、宁夏 一本线&…

一文搞懂Linux命令行下载OneDrive分享文件

一文搞懂Linux命令行下载OneDrive分享文件 什么问题&#xff1f; 因为OneDrive有些坑&#xff0c;无法从分享界面获取真实下载链接&#xff0c;比如下面这个链接&#xff1a; https://connecthkuhk-my.sharepoint.com/:f:/g/personal/jhyang13_connect_hku_hk/EsEgHtGOWbJIm…

Golang逃逸分析

在Go语言中&#xff0c;逃逸分析(Escape Analysis)是一种编译器优化技术&#xff0c;用于确定变量是应该分配在堆上还是在栈上。这对程序的性能有显著的影响&#xff0c;因为栈上资源的分配速度和释放速度要比堆上快得多&#xff0c;同时堆上的内存管理也更加简单。 基本概念 …

C++并发之协程实例(四)(通过迭代器访问生成器序列)

目录 1 协程2 实例3 运行 1 协程 协程(Coroutines)是一个可以挂起执行以便稍后恢复的函数。协程是无堆栈的&#xff1a;它们通过返回到调用方来暂停执行&#xff0c;并且恢复执行所需的数据与堆栈分开存储。这允许异步执行的顺序代码&#xff08;例如&#xff0c;在没有显式回调…

零代码搭建AI应用-文心智能体的设计与实现

本教程旨在帮助你开发一个结合语音识别和信息查询技术的智能应用&#xff0c;为用户提供登山小技巧和心得体会&#xff0c;满足用户在户外运动中的需求。通过设计不同角色和场景&#xff0c;可以满足用户在不同生活领域的需求&#xff0c;例如在家庭、社交、职场等场景下提供不…

什么洗地机值得推荐?洗地机选购攻略,热门洗地机推荐

在家庭清洁领域&#xff0c;洗地机已成为越来越多家庭的首选设备。它不仅能轻松应对各种材质的地面&#xff0c;还能有效去除顽固污渍&#xff0c;使家居环境更加整洁。然而&#xff0c;面对市场上众多洗地机品牌&#xff0c;许多消费者都会产生“什么洗地机值得推荐”的疑问。…

算法常见手写代码

1.NMS def py_cpu_nms(dets, thresh):"""Pure Python NMS baseline."""#x1、y1、x2、y2、以及score赋值x1 dets[:, 0]y1 dets[:, 1]x2 dets[:, 2]y2 dets[:, 3]scores dets[:, 4]#每一个检测框的面积areas (x2 - x1 1) * (y2 - y1 1)#按…

2024年数据、自动化与智能计算国际学术会议(ICDAIC 2024)

全称&#xff1a;2024年数据、自动化与智能计算国际学术会议&#xff08;ICDAIC 2024&#xff09; 会议网址:http://www.icdaic.com 会议地点: 厦门 投稿邮箱&#xff1a;icdaicsub-conf.com投稿标题&#xff1a;ArticleTEL。投稿时请在邮件正文备注&#xff1a;学生投稿&#…

Linux安装minio及mc客户端(包含ARM处理器架构)

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

Ubuntu 18.04 安装低延时内核

下面记录在在Ubuntu 18.04系统下安装低延时内核的流程&#xff1a; Ubuntu 内核信息 ll /boot其中initrd.img为根文件系统&#xff0c;System.map为内核符号表&#xff08;将内核代码段中的地址映射到对应的函数名或者全局变量名&#xff09;&#xff0c;vmlinuz为内核镜像。…

论文翻译 | Active Retrieval Augmented Generation 主动检索增强生成

Zhengbao Jiang1∗ Frank F. Xu1∗ Luyu Gao1∗ Zhiqing Sun1∗ Qian Liu2 Jane Dwivedi-Yu3 Yiming Yang1 Jamie Callan1 Graham Neubig1 卡内基梅隆大学语言技术研究所&#xff1b;海洋人工智能研究室&#xff1b;FAIR, Meta EMNLP 2023 main &#xff08;Proceedings of t…

低成本创业新篇章:上门回收小程序的崛起与挑战

在当今这个快速变化的时代&#xff0c;低成本创业项目成为了许多创业者的首选。其中&#xff0c;上门回收小程序以其独特的商业模式和市场需求&#xff0c;成为了创业市场中的一股新势力。本文将深入探讨上门回收小程序作为低成本创业项目的崛起之路以及面临的挑战。 一、上门回…

【R语言】地理探测器模拟及分析(Geographical detector)

地理探测器模拟及分析 1. 写在前面2. R语言实现2.1 数据导入2.2 确定数据离散化的最优方法与最优分类2.3 分异及因子探测器&#xff08;factor detector&#xff09;2.4 生态探测器&#xff08;ecological detector&#xff09;2.5 交互因子探测器&#xff08;interaction dete…

HTML(14)——结构伪类选择器和伪元素选择器

结构伪类选择器 作用&#xff1a; 根据元素的结构关系查找元素 选择器说明E:first-child查找第一个E元素E:last-child查找最后一个E元素E:nth-child(N)查找第N个E元素(第一个元素N值为1) 例如&#xff1a;查找第一个li标签&#xff0c;将背景改为绿色 <style> li:fir…

超越招聘技术人才目标的最佳技术招聘统计数据

研究发现&#xff0c;难以找到的人才比以往任何时候都更难找到&#xff1a;根据新人才委员会招聘调查报告&#xff1a;2024年难以找到的人才的战略和战略&#xff0c;60%的受访者表示&#xff0c;熟练人才的招聘时间比一年前长。调查进一步揭示了以下关于招聘技术的关键事实&am…