粤嵌实训医疗项目--day03(Vue + SpringBoot)

 往期回顾

粤嵌实训医疗项目day02(Vue + SpringBoot)-CSDN博客

粤嵌实训医疗项目--day01(Vue+SpringBoot)-CSDN博客

目录

一、SpringBoot AOP的使用

二、用户模块-注册功能(文件上传)

三、用户模块-注册实现

四、用户模块-登录-校验码


 

一、项目SpringBoot AOP的使用(增添日志输出等)

在vaccinum包下创建aspect包并输入以下代码

@Aspect
@Component
public class LogAspect {private final static Logger LOG = LoggerFactory.getLogger(LogAspect.class);/** 定义一个切点 */@Pointcut("execution(public * com.example.vaccinum.controller..*Controller.*(..))")public void controllerPointcut() {}@Resourceprivate SnowFlake snowFlake;@Before("controllerPointcut()")public void doBefore(JoinPoint joinPoint) throws Throwable {// 增加日志流水号MDC.put("LOG_ID", String.valueOf(snowFlake.nextId()));// 开始打印请求日志ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();Signature signature = joinPoint.getSignature();String name = signature.getName();// 打印请求信息LOG.info("------------- 开始 -------------");LOG.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());LOG.info("类名方法: {}.{}", signature.getDeclaringTypeName(), name);LOG.info("远程地址: {}", request.getRemoteAddr());RequestContext.setRemoteAddr(getRemoteIp(request));// 打印请求参数Object[] args = joinPoint.getArgs();// LOG.info("请求参数: {}", JSONObject.toJSONString(args));Object[] arguments  = new Object[args.length];for (int i = 0; i < args.length; i++) {if (args[i] instanceof ServletRequest|| args[i] instanceof ServletResponse|| args[i] instanceof MultipartFile) {continue;}arguments[i] = args[i];}// 排除字段,敏感字段或太长的字段不显示String[] excludeProperties = {"password", "file"};PropertyPreFilters filters = new PropertyPreFilters();PropertyPreFilters.MySimplePropertyPreFilter excludefilter = filters.addFilter();excludefilter.addExcludes(excludeProperties);LOG.info("请求参数: {}", JSONObject.toJSONString(arguments, excludefilter));}@Around("controllerPointcut()")public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {long startTime = System.currentTimeMillis();Object result = proceedingJoinPoint.proceed();// 排除字段,敏感字段或太长的字段不显示String[] excludeProperties = {"password", "file"};PropertyPreFilters filters = new PropertyPreFilters();PropertyPreFilters.MySimplePropertyPreFilter excludefilter = filters.addFilter();excludefilter.addExcludes(excludeProperties);LOG.info("返回结果: {}", JSONObject.toJSONString(result, excludefilter));LOG.info("------------- 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);return result;}/*** 使用nginx做反向代理,需要用该方法才能取到真实的远程IP* @param request* @return*/public String getRemoteIp(HttpServletRequest request) {String ip = request.getHeader("x-forwarded-for");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return ip;}}

再在vaccinum包下创建util包并引入两个类

1.用于存储和获取当前请求的远程地址类RequestContext

package com.example.vaccinum.util;import java.io.Serializable;public class RequestContext implements Serializable {private static ThreadLocal<String> remoteAddr = new ThreadLocal<>();public static String getRemoteAddr() {return remoteAddr.get();}public static void setRemoteAddr(String remoteAddr) {RequestContext.remoteAddr.set(remoteAddr);}}

2.雪花算法类SnowFlaske

package com.example.vaccinum.util;import org.springframework.stereotype.Component;import java.text.ParseException;/*** Twitter的分布式自增ID雪花算法**/
@Component
public class SnowFlake {/*** 起始的时间戳*/private final static long START_STMP = 1609459200000L; // 2021-01-01 00:00:00/*** 每一部分占用的位数*/private final static long SEQUENCE_BIT = 12; //序列号占用的位数private final static long MACHINE_BIT = 5;   //机器标识占用的位数private final static long DATACENTER_BIT = 5;//数据中心占用的位数/*** 每一部分的最大值*/private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);/*** 每一部分向左的位移*/private final static long MACHINE_LEFT = SEQUENCE_BIT;private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;private long datacenterId = 1;  //数据中心private long machineId = 1;     //机器标识private long sequence = 0L; //序列号private long lastStmp = -1L;//上一次时间戳public SnowFlake() {}public SnowFlake(long datacenterId, long machineId) {if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");}if (machineId > MAX_MACHINE_NUM || machineId < 0) {throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");}this.datacenterId = datacenterId;this.machineId = machineId;}/*** 产生下一个ID** @return*/public synchronized long nextId() {long currStmp = getNewstmp();if (currStmp < lastStmp) {throw new RuntimeException("Clock moved backwards.  Refusing to generate id");}if (currStmp == lastStmp) {//相同毫秒内,序列号自增sequence = (sequence + 1) & MAX_SEQUENCE;//同一毫秒的序列数已经达到最大if (sequence == 0L) {currStmp = getNextMill();}} else {//不同毫秒内,序列号置为0sequence = 0L;}lastStmp = currStmp;return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分| datacenterId << DATACENTER_LEFT       //数据中心部分| machineId << MACHINE_LEFT             //机器标识部分| sequence;                             //序列号部分}private long getNextMill() {long mill = getNewstmp();while (mill <= lastStmp) {mill = getNewstmp();}return mill;}private long getNewstmp() {return System.currentTimeMillis();}public static void main(String[] args) throws ParseException {// 时间戳// System.out.println(System.currentTimeMillis());// System.out.println(new Date().getTime());//// String dateTime = "2021-01-01 08:00:00";// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");// System.out.println(sdf.parse(dateTime).getTime());SnowFlake snowFlake = new SnowFlake(1, 1);long start = System.currentTimeMillis();for (int i = 0; i < 10; i++) {System.out.println(snowFlake.nextId());System.out.println(System.currentTimeMillis() - start);}}
}

还需要导入如下依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.70</version>
</dependency>
  1. spring-boot-starter-aop:这是Spring Boot提供的一个AOP(面向切面编程)模块的启动器,它包含了Spring AOP和AspectJ等AOP框架的依赖,可以方便地在Spring Boot应用中使用AOP。AOP可以通过切面(Aspect)来实现横向逻辑的复用,比如日志记录、事务管理、权限控制等。

  2. fastjson:这是阿里巴巴开源的一个JSON序列化/反序列化框架,它可以将Java对象转换成JSON字符串,也可以将JSON字符串转换成Java对象。fastjson具有快速、稳定、高效的特点,广泛应用于Java应用的数据交换、RPC调用、消息队列等场景。在Spring Boot应用中,fastjson可以作为默认的JSON序列化/反序列化工具,也可以与其他JSON库一起使用。


二、用户模块-注册功能(文件上传)

--在controller层提供FileController文件上传的接口、在本地创建存储图片的文件夹

1.创建上传图片接口

@RestController
@RequestMapping("/file")
public class FileController {@RequestMapping("/upload")public String upload(MultipartFile file) throws IOException {String uuid = UUID.randomUUID().toString();
//        1.1获取文件真实名称   123.jpgString filename = file.getOriginalFilename();
//        2.图片名称修改
//        后缀String substring = filename.substring(filename.lastIndexOf("."));
//        拼接uuid和后缀名filename = uuid +substring;//        3.如何存到本地磁盘中 文件的上传file.transferTo(new File("E:\\实训\\upload\\"+filename));return "http://localhost:8085/" + filename;}
}

通过uuid类可以使得上传到本地磁盘文件名不会出现重复

--在Login.vue提供对话框、在data中提供form变量

找到Login.vue对应注册组件

<!-- 对话框 --><el-dialog :visible.sync="dialogVisible" title="注册账号" width="30%"><el-form :model="form" label-width="120px"><el-form-item label="名称"><el-input v-model="form.name" style="width: 80%"></el-input></el-form-item><el-form-item label="手机号码"><el-input v-model="form.phone" style="width: 80%"></el-input></el-form-item><el-form-item label="密码"><el-input v-model="form.password" style="width: 80%"></el-input></el-form-item><el-form-item label="头像"><!-- action表示为上传文件的url   --><el-uploadclass="avatar-uploader"action="http://localhost:8088/file/upload/":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeAvatarUpload"><img v-if="imageUrl" :src="imageUrl" class="avatar" /><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></el-form-item><el-form-item label="身份证号"><el-input v-model="form.code" style="width: 80%"></el-input></el-form-item><el-form-item label="邮箱"><el-input v-model="form.email" style="width: 80%"></el-input></el-form-item><el-form-item label="性别"><el-input v-model="form.sex" style="width: 80%"></el-input></el-form-item><el-form-item label="年龄"><el-input v-model="form.age" style="width: 80%"></el-input></el-form-item></el-form><template #footer><span class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="save()">确定</el-button></span></template></el-dialog>

--在methods中提供上传的处理函数

 测试功能:

可以看到成功上传成功并且展示出存放到磁盘中的图片


三、用户模块-注册实现

--在用户实体中提供主键字段

在vaccinum架构下创建userInfo表单

DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info`  (`user_id` bigint(20) NOT NULL COMMENT '用户id',`code` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '身份证',`email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',`sex` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别',`age` int(11) NULL DEFAULT NULL COMMENT '年龄',`job` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '职位',`status` int(11) NULL DEFAULT 0 COMMENT '用户通行码-0绿码-1黄码-2红码',PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户信息' ROW_FORMAT = DYNAMIC;-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES (2, '456379865132485', '752963252@qq.com', '男', 45, '', 2);
INSERT INTO `user_info` VALUES (3, '123465789651', '5689562@qq.com', '男', 16, NULL, 1);
INSERT INTO `user_info` VALUES (9, '阿斯顿', 'asd', '女', 12, 'asd', 0);
INSERT INTO `user_info` VALUES (10, '34', '34', '女', 3, '4', 0);
INSERT INTO `user_info` VALUES (12, 'asd', 'asd', '男', 23, 'ghf', 0);
INSERT INTO `user_info` VALUES (16, 'asd', 'asd', '男', 12, 'asd', 0);

通过插件mbatisx使用逆向,自动创建对应三层架构的代码

idea实现数据库连接

下载完对应驱动后进行配置

使用mybatisx插件

mybatisx逆向配置

创建完后对应userInfo实体类,需要进行修改

@Data
@EqualsAndHashCode(callSuper = false)
public class UserInfo implements Serializable {private static final long serialVersionUID = 1L;/*** 用户id INPUT设置为手动输入id*/@TableId(value = "user_id", type = IdType.INPUT)private Long userId;/*** username*/@TableField(exist = false)private String userName;/*** 身份证*/private String code;/*** 邮箱*/private String email;/*** 性别*/private String sex;/*** 年龄*/private Integer age;/*** 职位*/private String job;/*** 用户通行码-0绿码-1黄码-2红码*/private Integer status;@TableField(exist = false)private User user;}

在启动类中添加扫描mapper的注解

--在用户controller中提供注册接口

@Autowired
UserInfoService userInfoService;   //定义一个请求接口来实现用户的注册 user、userinfo@RequestMapping("/register")public String register(User user,UserInfo userInfo) throws JsonProcessingException {
//        1.创建json解析工具ObjectMapper json = new ObjectMapper();
//       2.返回的结果集HashMap map = new HashMap<>();
//        3.调用方法添加数据boolean save = userService.save(user);
//        4.添加userInfo的数据  需要设置 user的id主键 为 userinfo id的值userInfo.setUserId(user.getId());boolean save1 = userInfoService.save(userInfo);
//        响应结果map.put("flag",save&&save1);
//        返回解析好的json数据return json.writeValueAsString(map);}

前端设置好请求

--在文件上传成功后,把服务器响应的图片url赋值到form.image

--修改页面提供save函数和异步请求操作 

//注册的函数save() {//发起一个异步请求,查询分类的数据request// post 请求方式.post("/gec/user/register", this.form)// then表示请求后的回调函数.then((res) => {//判断操作是否成功if (res.ok == true) {//消息提示this.$message({message: "注册成功",type: "success",});//把form的数据清空this.form = {name: "",phone: "",password: "",image: "",code: "",email: "",sex: "",age: "",};//关闭对话框this.dialogVisible = false;} else {this.$message.error("注册失败");}});},

功能展示:

前端展示:

数据库展示:


四、用户模块-登录-校验码

在项目中的resource下创建lib包并设置为库,放入以下两个jar包

检测是否变成库

--在项目中提供验证码的controller接口【注意使用:jdk8】

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
//sun.misc.BASE64Encoder jdk8提供
import sun.misc.BASE64Encoder;import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Properties;@RestController
@RequestMapping("/captcha")
public class CaptchaController {//返回验证码@RequestMapping("/getCaptcha")public void getCaptcha(HttpServletRequest request, HttpServletResponse response) throws Exception {//验证码生成器DefaultKaptcha defaultKaptcha = new DefaultKaptcha();//配置Properties properties = new Properties();//是否有边框properties.setProperty("kaptcha.border", "yes");//设置边框颜色properties.setProperty("kaptcha.border.color", "105,179,90");//边框粗细度,默认为1// properties.setProperty("kaptcha.border.thickness","1");//验证码properties.setProperty("kaptcha.session.key", "code");//验证码文本字符颜色 默认为黑色properties.setProperty("kaptcha.textproducer.font.color", "blue");//设置字体样式properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅 黑");//字体大小,默认40properties.setProperty("kaptcha.textproducer.font.size", "30");//验证码文本字符内容范围 默认为abced2345678gfynmnpwx// properties.setProperty("kaptcha.textproducer.char.string", "");//字符长度,默认为5properties.setProperty("kaptcha.textproducer.char.length", "4");//字符间距 默认为2properties.setProperty("kaptcha.textproducer.char.space", "4");//验证码图片宽度 默认为200properties.setProperty("kaptcha.image.width", "100");//验证码图片高度 默认为40properties.setProperty("kaptcha.image.height", "40");Config config = new Config(properties); //当前对象包引用路径 为 googledefaultKaptcha.setConfig(config);//定义response输出类型为image/jpegresponse.setDateHeader("Expires", 0);response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");response.addHeader("Cache-Control", "post-check=0, pre-check=0");response.setHeader("Pragma", "no-cache");response.setContentType("image/jpeg");//---------------------------生成验证码----------------------//获取验证码文本内容String text = defaultKaptcha.createText();System.out.println("验证码:  " + text);//captcha作为key,将验证码放到session中request.getSession().setAttribute("captcha", text);//根据文本内容创建图形验证码BufferedImage image = defaultKaptcha.createImage(text);//创建IO流ByteArrayOutputStream baos = new ByteArrayOutputStream();try {//输出流输出图片,格式为jpgImageIO.write(image, "jpg", baos);} catch (IOException e) {e.printStackTrace();}byte[] bytes = baos.toByteArray();//把流转换成字节数组BASE64Encoder encoder = new BASE64Encoder();String imgStr = encoder.encodeBuffer(bytes).trim();System.out.println(imgStr);HashMap<String, Object> map = new HashMap<>();map.put("code", 200);map.put("imgStr", imgStr);ObjectMapper objectMapper = new ObjectMapper();String json = objectMapper.writeValueAsString(map);response.getWriter().println(json);}}

--在用户controller中修改登录请求

//定义一个请求接口来实现用户登录
@RequestMapping("login")
public String login(String phone, String password, String code, HttpSession session) throws JsonProcessingException {//定义json解析工具ObjectMapper objectMapper = new ObjectMapper();//key-value集合结果HashMap result = new HashMap();//获取正确的验证码String captcha = (String) session.getAttribute("captcha");// 进行验证码判断if(!code.equals(captcha)){//保存到map中result.put("ok", false);result.put("message", "验证码错误");//返回解析的json数据return objectMapper.writeValueAsString(result);}//调用业务层的方法进行登录查询  【手机号码、密码】QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();userQueryWrapper.eq("phone", phone);userQueryWrapper.eq("password", password);//根据条件进行查询User user = userService.getOne(userQueryWrapper);//判断if (user != null) {//登录成功//保存到map中result.put("ok", true);result.put("user", user);} else {result.put("ok", false);result.put("message", "用户名或密码错误");}//返回解析的json数据return objectMapper.writeValueAsString(result);
}

--在script中提供生命周期、及获取验证码的函数

 created() {this.getCode();//this.getCookie();},
getCode() {request.get("/captcha/getCaptcha").then((res) => {console.log("res:", res);if (res.code == "200") {this.codeUrl = "data:image/jpg;base64," + res.imgStr;}});},

效果展示 :

验证码判断

正确验证码与正确账号密码下正常登陆。


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

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

相关文章

【Unity】RenderFeature应用(简单场景扫描效果)

【Unity】RenderFeature应用&#xff08;简单场景扫描效果&#xff09; RenderFeature 是一个用于渲染图形的概念&#xff0c;通常在图形引擎或游戏引擎中使用。它是一个模块化的组件&#xff0c;负责处理特定的渲染功能&#xff0c;例如阴影、光照、粒子效果等。 点击地面生成…

【考研数学】数学“背诵”手册 | 需要记忆且容易遗忘的知识点

文章目录 引言一、高数常见泰勒展开 n n n 阶导数公式多元微分函数连续、可微、连续可偏导之间的关系多元函数极值无条件极值条件极值 三角函数的积分性质华里士公式&#xff08; “点火”公式 &#xff09;特殊性质 原函数与被积函数的奇偶性结论球坐标变换公式 二、线代施密特…

CondaError: Downloaded bytes did not match Content-Length

问题 使用anaconda下载包文件时&#xff0c;出现了CondaError: Downloaded bytes did not match Content-Length的错误 CondaError: Downloaded bytes did not match Content-Lengthurl: https://conda.anaconda.org/pytorch/win-64/pytorch-2.1.0-py3.11_cuda11.8_cudnn8_0.…

npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本。

1、在vscode终端执行 get-ExecutionPolicy &#xff0c;显示Restricted&#xff0c;说明状态是禁止的。 2、更改状态: set-ExecutionPolicy RemoteSigned 出现需要管理员权限提示&#xff0c;可选择执行 Set-ExecutionPolicy -Scope CurrentUser 出现的ExecutionPolicy参数后输…

H5游戏源码分享-色块选择游戏

H5游戏源码分享-色块选择游戏 玩到后面色块越来越小&#xff0c;越来越难找出 <!DOCTYPE html><html><head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"><meta charset"UTF-8"><meta na…

bitlocker 加密锁定的固态硬盘,更换到别的电脑上,怎么把原密钥写进新电脑TPM芯片内,开启无需手动填密钥

环境: Win11 专业版 联想E14笔记本 512G ssd 问题描述: 一台笔记本因充电故障,需要拿去维修,不想重装系统,将bitlocker 加密锁定的固态硬盘拆下更换到别的笔记本电脑上,现在开机要手动填密钥,怎么把原密钥写进新电脑TPM芯片内,开启无需手动填密钥和之前那台电脑一…

C的自定义类型

目录 1. 结构体 1.1. 结构体类型的声明 1.1.1. 特殊声明 2. 结构的自引用 3. 结构体变量的定义和初始化 4. 结构体内存对齐 4.1. 结构体内存对齐 4.2. 修改默认对齐数 5. 结构体传参 6. 结构体实现位段&#xff08;位段的填充&可移植性&#xff09; 6.1. 什么是位…

Glide原理

本文基于Carson整理 1.简介 相比其他几种图片加载框架&#xff0c;Glide性能最好。这得益于其高效的图片缓存策略 其还有多样化的媒体格式加载&#xff1a;如GIF、Video&#xff0c;对于商城首页需展示丰富样式、信息的页面需求来说&#xff0c;也是必不可少的。 2.加载原理…

nodejs+vue+elementui+express酒店管理系统

登录&#xff1a;运行系统后&#xff0c;进行登录&#xff0c;可使用本系统。 客房预定&#xff1a;此界面先通过条件查询客房信息&#xff0c;然后进行客房预定。对预定的客房还可以取消和支付操作。 信息查询&#xff1a;可查询所有的公告信息&#xff0c;点击公告名称&#…

[量化投资-学习笔记003]Python+TDengine从零开始搭建量化分析平台-Grafana画K线图

在前面两个笔记&#xff1a; PythonTDengine从零开始搭建量化分析平台-数据存储 PythonTDengine从零开始搭建量化分析平台-MA均线的多种实现方式 中有提到使用 Grafana 画图&#xff0c;不过画的都是均线。除了均线&#xff0c;Grafana 非常人性的提供了 K线图模块 搭配 TDeng…

基于群居蜘蛛算法的无人机航迹规划

基于群居蜘蛛算法的无人机航迹规划 文章目录 基于群居蜘蛛算法的无人机航迹规划1.群居蜘蛛搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用群居蜘蛛算法来优化无人机航迹规划。 …

Photoshop(PS)安装教程(2023最新最详细图文教程)

目录 一.简介 二.安装步骤 软件&#xff1a;PS版本&#xff1a;2023语言&#xff1a;简体中文大小&#xff1a;3.20G系统要求&#xff1a;Win10&#xff08;1903&#xff09;及以上版本&#xff0c;64位操作系统硬件要求&#xff1a;CPU2.0GHz 内存8G(或更高&#xff0c;不支持…

5G 3GPP全球频谱介绍

所谓 “频谱”&#xff0c;是指特定类型的无线通信所在的射频范围。不同的无线技术使用不同的频谱&#xff0c;因此互不干扰。由于一项技术的频谱是有限的&#xff0c;因此频谱空间存在大量竞争&#xff0c;并且人们也在不断开发和增强全新的、高效率的频谱使用方式。 介绍5G …

Vue echarts 折线图 背景颜色渐变 (两种实现方式)

需求 实现方式 两种方法 方法一&#xff1a;color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{}&#xff0c;{}&#xff0c;{}]) 方法二&#xff1a;避开new echarts&#xff0c;color: {x: 0, y: 0, x2: 0, y2: 1,colorStops: [{}&#xff0c;{}&#xff0c;{}]} …

Linux(Centos7)操作记录

1、nginx -t #Nginx配置文件检查 上述截图代表检查没问题 上述截图检查配置文件配置错误&#xff0c;并提示错误文件位置 2、systemctl restart nginx #重启Nginx 重启Nginx失败 3、systemctl status nginx.service #查看Nginx服务状态 80端口被占导致服务启动失败 4、n…

k8s 金丝雀发布与声明式管理

Deployment控制器支持自定义控制更新过程中的滚动节奏&#xff0c;如“暂停(pause)”或“继续(resume)”更新操作。比如等待第一批新的Pod资源创建完成后立即暂停更新过程&#xff0c;此时&#xff0c;仅存在一部分新版本的应用&#xff0c;主体部分还是旧的版本。然后&#xf…

基于水循环算法的无人机航迹规划-附代码

基于水循环算法的无人机航迹规划 文章目录 基于水循环算法的无人机航迹规划1.水循环搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用水循环算法来优化无人机航迹规划。 1.水循环…

【赠书活动】从瀑布模式到水母模式:ChatGPT如何赋能软件研发全流程

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

YOLOv5算法 | 万字长文带你深度解析yolov5s.yaml配置文件

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。配置文件yolov5s.yaml在YOLOv5模型训练过程中发挥着至关重要的作用&#xff0c;属于初学者必知必会的文件&#xff01;在YOLOv5-6.0版本源码中&#xff0c;配置了5种不同大小的网络模型&#xff0c;分别是YOLOv5n、YOLOv5s…

使用GoQuery实现头条新闻采集

概述 在本文中&#xff0c;我们将介绍如何使用Go语言和GoQuery库实现一个简单的爬虫程序&#xff0c;用于抓取头条新闻的网页内容。我们还将使用爬虫代理服务&#xff0c;提高爬虫程序的性能和安全性。我们将使用多线程技术&#xff0c;提高采集效率。最后&#xff0c;我们将展…