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

【SpringBoot3+Vue3】三【实战篇】-后端(优化)

目录

一、登录优化-redis

1、SpringBoot集成redis

1.1 pom

1.2 yml 

1.3 测试程序(非必须)

1.4 启动redis,执行测试程序 

2、令牌主动失效(代码优化)

2.1  UserController设置token到redis

2.2 登录拦截器LoginCheckInterceptor

2.3 UserController更新密码删除redis的token(jwt)

2.4 验证

2.4.1 调用登录接口

2.4.2 调用更新密码接口 ​编辑

二、SpringBoot项目部署

1、pom检查是否有打包插件

 2、打包

3、运行jar

4、测试

三、属性配置方式 

1、命令参数方式

2、环境变量方式

3、外部配置文件方式

 4、配置优先级

四、多环境开发-Profiles 

1、多环境开发-介绍

2、 多环境开发-Profiles(同一个yaml)

3、多环境开发-Profiles(不同yml)

4、多环境开发-Profiles(分组)


前言:针对【SpringBoot3+Vue3】二篇进行一些后端优化和一些实用的后端技术

一、登录优化-redis

1、SpringBoot集成redis

1.1 pom

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

1.2 yml 

spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/springbdfdfoot_vue?serverTimezone=UTCusername: rootpassword: ddfdfdfdmain:banner-mode: off  # 关闭控制台springboot的logodata:redis:host: localhostport: 6379

1.3 测试程序(非必须)

package com.bocai;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;import java.util.concurrent.TimeUnit;@SpringBootTest //如果在测试类上添加这个注解,那么将来单元测试方法执行之前,会先初始化Spring容器
public class RedisTest {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void testSet(){// 往redis中存储一个键值对  StringRedisTemplateValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.set("username","仓颉书");operations.set("woman","舒淇",15, TimeUnit.SECONDS); //设置有效时间}@Testpublic void testGet(){//从redis获取一个键值对ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();System.out.println(operations.get("username"));}
}

1.4 启动redis,执行测试程序 

2、令牌主动失效(代码优化)

2.1  UserController设置token到redis

登录完成生成token时,同时将token存储到redis,按键值对方式,注意设置了时效要与token生成时的时效一致性。

package com.bocai.controller;import com.bocai.common.Result;
import com.bocai.pojo.User;
import com.bocai.service.UserService;
import com.bocai.utils.JwtUtils;
import com.bocai.utils.Md5Util;
import com.bocai.utils.ThreadLocalUtil;
import jakarta.validation.constraints.Pattern;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.URL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;@RestController
@Slf4j
@Validated
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@Autowiredprivate StringRedisTemplate stringRedisTemplate;/*** 用户注册* @param username* @param password* @return*/@PostMapping("/register")public Result register(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$")String password){log.info("注册用户名:{},密码为:{}",username,password);// 查询用户User user = userService.queryUserByUsername(username);if (user == null){//没有占用,可以注册//注册用户userService.register(username,password);return Result.success();}else{return Result.error("用户名被占用");}}@PostMapping("/login")public Result login(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$")String password) {log.info("登录用户名:{},密码为:{}", username, password);// 查询用户User loginUser = userService.queryUserByUsername(username);// 判断用户是否存在if (loginUser == null) {return Result.error("用户名不存在");}// 判断密码是否正确,loginUser对象中的password是密文if(Md5Util.getMD5String(password).equals(loginUser.getPassword())){// 登录成功Map<String, Object> claims = new HashMap<>();claims.put("id", loginUser.getId());claims.put("username",loginUser.getUsername());String jwt = JwtUtils.generateJwt(claims); //让jwt包含了当前登录的员工信息// 把token存储到redisValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.set(jwt,jwt,12, TimeUnit.HOURS); //过期时间与jwt设置的时效要一致性return Result.success(jwt);}return Result.error("密码错误!");}/*** 查询用户信息(从线程获取)* @return*/@GetMapping("/userInfo")public Result userInfo(){// 从线程获取存储的jwt信息Map<String, Object> map = ThreadLocalUtil.get();String username = (String) map.get("username");log.info("查询用户全部信息,从token获取信息为:{}",username);//根据用户名查询用户User user = userService.queryUserByUsername(username);return Result.success(user);}//使用上面的的优化版本
//    /**
//     * 查询用户信息(从token获取)
//     * @param token
//     * @return
//     */
//    @GetMapping("/userInfo")
//    public Result userInfo(@RequestHeader(name = "Authorization")String token){
//        log.info("查询用户全部信息,从token获取信息为:{}",token);
//        //根据用户名查询用户
//        Map<String, Object> claims = JwtUtils.parseJWT(token);
//        String username = (String) claims.get("username");
//        User user = userService.queryUserByUsername(username);
//        return Result.success(user);
//    }/*** 更新用户* @param user* @return*/@PutMapping("/update")public Result update(@RequestBody @Validated  User user){log.info("修改的用户为:{}",user);userService.updateUser(user);return Result.success();}/*** 更新头像* @param avatarUrl* @return*/@PatchMapping("/updateAvatar")public Result updateAvatar(@RequestParam @URL String avatarUrl){log.info("头像地址是{}",avatarUrl);userService.updateAvatar(avatarUrl);return Result.success();}/*** 更新密码* @param params json数据包含old_pwd,new_pwd,re_pwd* @return*/@PatchMapping("/updatePwd")public Result updatePwd(@RequestBody Map<String, String> params){log.info("修改密码传过来数据是:{}",params);// 1、校验参数String old_pwd = params.get("old_pwd");String new_pwd = params.get("new_pwd");String re_pwd = params.get("re_pwd");if(!StringUtils.hasLength(old_pwd) || !StringUtils.hasLength(new_pwd) || !StringUtils.hasLength(re_pwd)){return Result.error("缺少必要参数!");}//原密码是否正确Map<String, Object> map = ThreadLocalUtil.get();String username = (String) map.get("username");User loginUser = userService.queryUserByUsername(username);if(!loginUser.getPassword().equals(Md5Util.getMD5String(old_pwd))){return Result.error("原密码不正确!");}//新、老密码是否一致if(old_pwd.equals(new_pwd)){return Result.error("新、老密码一样!!");}//新密码和确认密码不一致!if(!re_pwd.equals(new_pwd)){return Result.error("新密码和确认密码不一致!!");}// 2 、调用userServiceuserService.updatePwd(new_pwd);return Result.success();}
}

2.2 登录拦截器LoginCheckInterceptor

登录拦截器当中查询redis当中是否存在相同token(jwt),如果不存在所有失效了。抛出异常

package com.bocai.interceptor;import com.alibaba.fastjson.JSONObject;
import com.bocai.common.Result;
import com.bocai.utils.JwtUtils;
import com.bocai.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import java.util.Map;/***   =========================LoginCheckInterceptor 拦截器 interceptor========================*/
@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Override //目标资源方法运行前运行, 返回true: 放行, 放回false, 不放行public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {//1.获取请求url。String url = req.getRequestURL().toString();log.info("请求的url: {}",url);//2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。if(url.contains("login")){log.info("登录操作, 放行...");return true;}//3.获取请求头中的令牌( Authorization)。String jwt = req.getHeader("Authorization");//4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。if(!StringUtils.hasLength(jwt)){log.info("请求头Authorization为空,返回未登录的信息");Result error = Result.error("NOT_LOGIN");//手动转换 对象--json --------> 阿里巴巴fastJSONString notLogin = JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return false;}//5.解析token,如果解析失败,返回错误结果(未登录)。try {// 从redis中获取获取相同的token(jwt)ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();String redisJwt = operations.get(jwt);if(redisJwt == null){// token 已经失效throw new RuntimeException();}//解析jwtMap<String, Object> claims = JwtUtils.parseJWT(jwt);//6.把业务数据存储到ThreadLocal中ThreadLocalUtil.set(claims);//7.放行。log.info("令牌合法, 放行");return true;} catch (Exception e) {//jwt解析失败e.printStackTrace();log.info("解析令牌失败, 返回未登录错误信息");Result error = Result.error("NOT_LOGIN");//手动转换 对象--json --------> 阿里巴巴fastJSONString notLogin = JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return false;}}@Override //目标资源方法运行后运行public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle ...");}@Override //视图渲染完毕后运行, 最后运行public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 清空ThreadLocal中的数据,防止内存泄漏ThreadLocalUtil.remove();System.out.println("afterCompletion...");}
}

2.3 UserController更新密码删除redis的token(jwt)

更新密码的时候同时需要将redis存储的jwt删除掉。这里在更新密码方法上面使用从请求头当中获取Authorization

package com.bocai.controller;import com.bocai.common.Result;
import com.bocai.pojo.User;
import com.bocai.service.UserService;
import com.bocai.utils.JwtUtils;
import com.bocai.utils.Md5Util;
import com.bocai.utils.ThreadLocalUtil;
import jakarta.validation.constraints.Pattern;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.URL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;@RestController
@Slf4j
@Validated
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@Autowiredprivate StringRedisTemplate stringRedisTemplate;/*** 用户注册* @param username* @param password* @return*/@PostMapping("/register")public Result register(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$")String password){log.info("注册用户名:{},密码为:{}",username,password);// 查询用户User user = userService.queryUserByUsername(username);if (user == null){//没有占用,可以注册//注册用户userService.register(username,password);return Result.success();}else{return Result.error("用户名被占用");}}@PostMapping("/login")public Result login(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$")String password) {log.info("登录用户名:{},密码为:{}", username, password);// 查询用户User loginUser = userService.queryUserByUsername(username);// 判断用户是否存在if (loginUser == null) {return Result.error("用户名不存在");}// 判断密码是否正确,loginUser对象中的password是密文if(Md5Util.getMD5String(password).equals(loginUser.getPassword())){// 登录成功Map<String, Object> claims = new HashMap<>();claims.put("id", loginUser.getId());claims.put("username",loginUser.getUsername());String jwt = JwtUtils.generateJwt(claims); //让jwt包含了当前登录的员工信息// 把token存储到redisValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.set(jwt,jwt,12, TimeUnit.HOURS); //过期时间与jwt设置的时效要一致性return Result.success(jwt);}return Result.error("密码错误!");}/*** 查询用户信息(从线程获取)* @return*/@GetMapping("/userInfo")public Result userInfo(){// 从线程获取存储的jwt信息Map<String, Object> map = ThreadLocalUtil.get();String username = (String) map.get("username");log.info("查询用户全部信息,从token获取信息为:{}",username);//根据用户名查询用户User user = userService.queryUserByUsername(username);return Result.success(user);}//使用上面的的优化版本
//    /**
//     * 查询用户信息(从token获取)
//     * @param token
//     * @return
//     */
//    @GetMapping("/userInfo")
//    public Result userInfo(@RequestHeader(name = "Authorization")String token){
//        log.info("查询用户全部信息,从token获取信息为:{}",token);
//        //根据用户名查询用户
//        Map<String, Object> claims = JwtUtils.parseJWT(token);
//        String username = (String) claims.get("username");
//        User user = userService.queryUserByUsername(username);
//        return Result.success(user);
//    }/*** 更新用户* @param user* @return*/@PutMapping("/update")public Result update(@RequestBody @Validated  User user){log.info("修改的用户为:{}",user);userService.updateUser(user);return Result.success();}/*** 更新头像* @param avatarUrl* @return*/@PatchMapping("/updateAvatar")public Result updateAvatar(@RequestParam @URL String avatarUrl){log.info("头像地址是{}",avatarUrl);userService.updateAvatar(avatarUrl);return Result.success();}/*** 更新密码* @param params json数据包含old_pwd,new_pwd,re_pwd* @param jwt 从请求头中获取Authorization赋值给jwt参数* @return*/@PatchMapping("/updatePwd")public Result updatePwd(@RequestBody Map<String, String> params,@RequestHeader("Authorization") String jwt){log.info("修改密码传过来数据是:{}",params);// 1、校验参数String old_pwd = params.get("old_pwd");String new_pwd = params.get("new_pwd");String re_pwd = params.get("re_pwd");if(!StringUtils.hasLength(old_pwd) || !StringUtils.hasLength(new_pwd) || !StringUtils.hasLength(re_pwd)){return Result.error("缺少必要参数!");}//原密码是否正确Map<String, Object> map = ThreadLocalUtil.get();String username = (String) map.get("username");User loginUser = userService.queryUserByUsername(username);if(!loginUser.getPassword().equals(Md5Util.getMD5String(old_pwd))){return Result.error("原密码不正确!");}//新、老密码是否一致if(old_pwd.equals(new_pwd)){return Result.error("新、老密码一样!!");}//新密码和确认密码不一致!if(!re_pwd.equals(new_pwd)){return Result.error("新密码和确认密码不一致!!");}// 2 、调用userServiceuserService.updatePwd(new_pwd);// 更新密码之后,删除redis中对应的token(jwt)ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.getOperations().delete(jwt);return Result.success();}
}

2.4 验证

2.4.1 调用登录接口

2.4.2 调用更新密码接口 

二、SpringBoot项目部署

1、pom检查是否有打包插件

  <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>              
   </plugin>

 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><image><builder>paketobuildpacks/builder-jammy-base:latest</builder></image><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>

 2、打包

插曲:

1、无效的标记: --release 

这里要与你得jdk版本一致性

2、注意test当中的case

3、运行jar

java -jar SS.jar

4、测试

三、属性配置方式 

1、命令参数方式

2、环境变量方式

 

3、外部配置文件方式

 4、配置优先级

四、多环境开发-Profiles 

1、多环境开发-介绍

2、 多环境开发-Profiles(同一个yaml)

3、多环境开发-Profiles(不同yml)

4、多环境开发-Profiles(分组)

分组实现

相关文章:

【SpringBoot3+Vue3】三【实战篇】-后端(优化)

目录 一、登录优化-redis 1、SpringBoot集成redis 1.1 pom 1.2 yml 1.3 测试程序&#xff08;非必须&#xff09; 1.4 启动redis&#xff0c;执行测试程序 2、令牌主动失效&#xff08;代码优化&#xff09; 2.1 UserController设置token到redis 2.2 登录拦截器Log…...

DevExpress中文教程 - 如何在macOS和Linux (CTP)上创建、修改报表(上)

DevExpress Reporting是.NET Framework下功能完善的报表平台&#xff0c;它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集&#xff0c;包括数据透视表、图表&#xff0c;因此您可以构建无与伦比、信息清晰的报表。 DevExpress Reports — 跨平台报表组件&#x…...

一个iOS tableView 滚动标题联动效果的实现

效果图 情景 tableview 是从屏幕顶部开始的&#xff0c;现在有导航栏&#xff0c;和栏目标题视图将tableView的顶部覆盖了 分析 我们为了达到滚动到某个分区选中标题的效果&#xff0c;就得知道 展示最顶部的cell或者区头在哪个分区范围内 所以我们必须首先获取顶部的位置 …...

代码执行相关函数以及简单例题

代码/命令 执行系列 相关函数 &#xff08;代码注入&#xff09;...

大数据爬虫分析基于Python+Django旅游大数据分析系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 基于Python和Django的旅游大数据分析系统是一种使用Python编程语言和Django框架开发的系统&#xff0c;用于处理和分…...

C# 结构体介绍

文章目录 定义结构体实例化结构体结构体的值类型特性结构体和类的区别限制 C# 中的结构体&#xff08;Struct&#xff09;是一种值类型数据结构&#xff0c;用于封装不同或相同类型的数据成一个单一的实体。结构体非常适合用来表示轻量级的对象&#xff0c;比如坐标点、颜色值或…...

【机器学习】特征工程:特征预处理,归一化、标准化、处理缺失值

特征预处理采用的是特定的统计方法&#xff08;数学方法&#xff09;将数据转化为算法要求的数字 1. 数值型数据 归一化&#xff0c;将原始数据变换到[0,1]之间 标准化&#xff0c;数据转化到均值为0&#xff0c;方差为1的范围内 缺失值&#xff0c;缺失值处理成均值、中…...

Pytorch torch.norm函数详解用法

torch.norm参数定义 torch版本1.6 def norm(input, p"fro", dimNone, keepdimFalse, outNone, dtypeNone)input input (Tensor): the input tensor 输入为tensorp p (int, float, inf, -inf, fro, nuc, optional): the order of norm. Default: froThe following …...

【DevOps】Git 图文详解(二):Git 安装及配置

Git 图文详解&#xff08;二&#xff09;&#xff1a;Git 安装及配置 1.Git 的配置文件2.配置 - 初始化用户3.配置 - 忽略.gitignore Git 官网&#xff1a;https://www.git-scm.com/ 下载安装包进行安装。Git 的使用有两种方式&#xff1a; 命令行&#xff1a;Git 的命令通过系…...

亚马逊美国站CPC认证ASTM F963测试项目要求有哪些?

ASTM F963是美国材料和试验联合会&#xff08;ASTM&#xff09;制定的儿童玩具安全性的标准规范&#xff0c;专门针对儿童玩具产品的安全性进行了规定和要求。 ASTM F963标准的内容和要求包括&#xff1a; 1、物理机械性能&#xff1a;规定了玩具的物理机械性能要求&#xff0…...

通付盾Web3专题 | KYT/AML:Web3合规展业的必要条件

与传统证券一样&#xff0c;基于区块链技术发展出来的虚拟资产交易所经历了快速发展而缺乏有效监管的行业早期。除了科技光环加持的各种区块链项目方、造富神话之外&#xff0c;交易所遭到黑客攻击、内部偷窃作恶、甚至经营主体异常而致使投资人血本无归的案例亦令人触目惊心。…...

Centos8配置Zabbix5.0中文汉化

1.点击【Sign in】按钮&#xff0c;输入用户名和密码进入Zabbix的首页&#xff0c;结果如图。 2.点击左边导航栏的【User settings】链接&#xff0c;进入用户个性化设置界面&#xff0c;结果如图。 3.在搭建Zabbix的虚拟机上使用yum命令下载中文包。 yum install glibc-langpa…...

元数据管理,数字化时代企业的基础建设

随着新一代信息化、数字化技术的应用&#xff0c;众多领域通过科技革命和产业革命实现了深度化的数字改造&#xff0c;进入到以数据为核心驱动力的&#xff0c;全新的数据处理时代&#xff0c;并通过业务系统、商业智能BI等数字化技术和应用实现了数据价值&#xff0c;从数字经…...

大数据之Hive:regexp_extract函数案例

目录 一、正则的通配符简介1、正则表达式的符号及意义2、各种操作符的运算优先级&#xff1a; 二、案例数据要求分析实现输出结果实现2实现3 总结 一、正则的通配符简介 1、正则表达式的符号及意义 符号含义实列/做为转意&#xff0c;即通常在"/"后面的字符不按原来…...

tsconfig.json无法写入文件“XXXX“因为它会覆盖输入文件

在开发ts项目的时候&#xff0c;包错提示无法写入文件&#xff1a; tsconfig.json无法写入文件"XXXX"因为它会覆盖输入文件 这是tsconfig.json文件配置问题&#xff0c;需要加入下面的配置就好了&#xff1a; {"compilerOptions": {"outDir": …...

本周Github有趣项目:draw-a-ui等

有趣的项目、工具和库 gpt-crawler 抓取网站以生成知识文件&#xff0c;从而从 URL 创建您自己的自定义 GPT。 需要步骤&#xff1a; 配置运行爬虫、 将您的数据上传到 OpenAI&#xff1a;使用此选项通过 UI 访问您生成的知识&#xff0c;您可以轻松与他人共享 创建自定义助…...

VBA如何快速识别Excel单元格中的文本数字

Excel中一种非常特殊的数字&#xff0c;这些数字看似数字&#xff0c;其实是文本格式&#xff08;下文简称为文本数字&#xff09;&#xff0c;在单元格的左上角会有一个绿色小三角作为标志&#xff0c;如B1:B3单元格。 在编程时为什么需要区分普通数字和文本数字呢&#xff…...

Mysql数据库 16.SQL语言 数据库事务

一、数据库事务 数据库事务介绍——要么全部成功要么全部失败 我们把完成特定的业务的多个数据库DML操作步骤称之为一个事务 事务——就是完成同一个业务的多个DML操作 例&#xff1a; 数据库事务四大特性 原子性&#xff08;A&#xff09;&#xff1a;一个事务中的多个D…...

docker 部署Redis集群(三主三从,以及扩容、缩容)

1&#xff1a;创建6个redis容器 docker run -d --name redis01 --net host --privilegedtrue -v /opt/redis/redis01:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381 docker run -d --name redis02 --net host --privilegedtrue -v /opt/redis/redis0…...

JavaScript 浮点数运算的精度问题及解决

JavaScript 浮点数运算的精度问题及解决 在 JavaScript 中整数和浮点数都属于 Number 数据类型&#xff0c;当浮点数做数学运算的时候&#xff0c;你经常会发现一些问题&#xff0c;举几个例子&#xff1a; 0.1 0.2 0.30000000000000004 console.log(0.1 0.2) 0.3000000…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

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

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

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...