博客项目(Spring Boot)

1.需求分析

  1. 注册功能(添加用户操纵)
  2. 登录功能(查询操作)
  3. 我的文章列表页(查询我的文章|文章修改|文章详情|文章删除)
  4. 博客编辑页(添加文章操作)
  5. 所有人博客列表(带分页功能)
  6. 文章详情页(多个查询功能和一个修改功能)

2.设计数据库

用户表:id(主键),登录名,密码,头像,状态

文章表:主键,标题,正文,发表时间,更新时间,作者id,阅读量,状态。

3.创建项目所有框架

所用技术:Spring Boot + Spring MVC + MyBatis + MySQL

将前端代码添加到项目中,前端代码详情请看博客连接。

创建后端并进行项目分层:

  • 控制层
  • 服务层
  • 数据持久层
  • 实体类层
  • 配置层
  • 工具层

4.后端代码

4.1实体类层

用户类:

package com.example.demo.model;import lombok.Data;import java.time.LocalDateTime;/*** Describe:* User:lenovo* Date:2023-08-03* Time:18:02*/
@Data
public class Userinfo {private int id;private String username;private String password;private String photo;private LocalDateTime createtime;private LocalDateTime updatetime;private int state;
}

文章类:

package com.example.demo.model;import lombok.Data;import java.time.LocalDateTime;/*** Describe:* User:lenovo* Date:2023-08-03* Time:18:04*/
@Data
public class Articleinfo {private int id;private String title;private String content;private LocalDateTime createtime;private LocalDateTime updatetime;private int uid;private int rcount;private int state;
}

4.2注册功能

在common层编写ResultAjax类,为统一的返回类。

@Data
public class ResultAjax {private int code;private String msg;private Object data;//为了方便使用我们构造一个成功方法public static ResultAjax succ(Object data) {ResultAjax resultAjax = new ResultAjax();resultAjax.setCode(200);resultAjax.setData(data);return resultAjax;}//为了方便处理构造一个成功的方法public static ResultAjax succ(int code, String msg, Object data) {ResultAjax resultAjax = new ResultAjax();resultAjax.setData(code);resultAjax.setMsg(msg);resultAjax.setData(data);return resultAjax;}//为了方便,我们构造一个失败的方法public static ResultAjax fail(int code, String msg) {ResultAjax resultAjax = new ResultAjax();resultAjax.setCode(code);resultAjax.setMsg(msg);resultAjax.setData(null);return resultAjax;}//为了方便,我们构造一个失败的方法public static ResultAjax fail(int code, String msg, Object data) {ResultAjax resultAjax = new ResultAjax();resultAjax.setCode(code);resultAjax.setMsg(msg);resultAjax.setData(data);return resultAjax;}
}

编写UserMapper类:

@Mapper
public interface UserMapper {@Insert("insert into userinfo(username, password) values(#{username}, #{password})")int reg(String username, String password);
}

编写UserService类:

@Service
public class UserService {@AutowiredUserMapper userMapper;public int reg(String username, String password) {return userMapper.reg(username, password);}
}

编写UserController类:

@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/reg")public ResultAjax reg(Userinfo userinfo) {//1.参数校验if(userinfo.getUsername() == null || userinfo.getUsername().trim().equals("")) {return ResultAjax.fail(-1, "参数错误!");}if(userinfo.getPassword() == null || userinfo.getPassword().trim().equals("")) {return ResultAjax.fail(-1, "参数错误");}//2.处理数据int ret = userService.reg(userinfo.getUsername(), userinfo.getPassword());//3.返回结果return ResultAjax.succ(ret);}
}

4.3登录功能

VO实体对象类是实体对象类的一个扩展,主要包含数据表中不拥有,但是前后端可能会使用到的对象。比如登录的时候,我们需要验证码,这个验证码,必须后端接收,并且不存在于数据表中,我们可以使用扩展对象进行接收。

编写UserVO类(在此文章中作用不大,但是方便以后的更新):

/*** Describe: userinfo的扩展类* User:lenovo* Date:2023-08-04* Time:19:03*/
@Data
public class UserinfoVO extends Userinfo {//这里可以放入验证码private String checkCode;
}

编写UserMapper类:

@Select("select * from userinfo where username=#{username}")Userinfo getUserByName(@Param("username")String username);

编写UserService类:

public Userinfo getUserByName(String username) {return userMapper.getUserByName(username);}

编写UserController类:

//登录接口:根据名字查找用户@RequestMapping("/login")public ResultAjax getUserByName(UserinfoVO userinfoVO, HttpServletRequest request) {// 1.校验参数if(userinfoVO == null || !StringUtils.hasLength(userinfoVO.getUsername()) ||!StringUtils.hasLength(userinfoVO.getPassword())) { //这里我们使用StringUtils.hasLength判断它是否为null或为空return ResultAjax.fail(-1, "非法参数!");}// 2.根据用户名查找对象Userinfo userinfo = userService.getUserByName(userinfoVO.getUsername());if(!userinfoVO.getPassword().equals(userinfo.getPassword())) {//密码错误return ResultAjax.fail(-2, "账号或密码错误!");}// 3.将对象存储到session中HttpSession session = request.getSession();session.setAttribute(AppVariable.SESSION_USERINFO_KEY, userinfo);// 4.将结果返回给前端return ResultAjax.succ(1);}

这里我们使用cookie-session才储存用户信息。

编写公共类(通过这个类,我们知道session通过什么关键字,来获取到用户的关键信息):

/*** Describe: 全局变量* User:lenovo* Date:2023-08-04* Time:19:12*/
public class AppVariable {//用户的session keypublic static final String SESSION_USERINFO_KEY = "SESSION_USERINFO";
}

4.4登录校验/统一异常处理/统一结果返回

登录校验:

/*** Describe:拦截器* User:lenovo* Date:2023-08-09* Time:19:06*/
public class LoginIntercept implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {HttpSession session = request.getSession(false);if(session == null || session.getAttribute(AppVariable.SESSION_USERINFO_KEY) == null) {response.sendRedirect("/login.html");return false;}return true;}
}
/*** Describe:系统配置文件* User:lenovo* Date:2023-08-09* Time:19:15*/
@Configuration
public class MyConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginIntercept()).addPathPatterns("/**").excludePathPatterns("/user/login").excludePathPatterns("/user/reg").excludePathPatterns("/art/getlistbypage").excludePathPatterns("/art/detail").excludePathPatterns("/editor.md/*").excludePathPatterns("/img/*").excludePathPatterns("/js/*").excludePathPatterns("/css/*").excludePathPatterns("/blog_list.html").excludePathPatterns("/blog_content.html").excludePathPatterns("/reg.html").excludePathPatterns("/login.html");}
}

统一结果返回:

/*** Describe:保底统一的返回值* User:lenovo* Date:2023-08-05* Time:10:00*/
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Autowiredprivate ObjectMapper objectMapper;@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {//判断类是否为标准的返回类型if(body instanceof ResultAjax) {return body;}if(body instanceof String) {ResultAjax resultAjax = ResultAjax.succ(body);try {return objectMapper.writeValueAsString(resultAjax);//如果是String类型,我们需要手动的转化为json对象} catch (JsonProcessingException e) {e.printStackTrace();}}return  ResultAjax.succ(body);}
}

统一异常的处理:

/*** Describe:统一异常的处理* User:lenovo* Date:2023-08-05* Time:10:33*/
//@RestControllerAdvice  //为了发现后续编程过程中的问题,我们可以先注释掉
public class ExceptionAdvice {@ExceptionHandler(Exception.class)public ResultAjax doException(Exception e) {return ResultAjax.fail(-1, e.getMessage());}
}

4.5查看我的文章列表页

Mapper:

@Mapper
public interface ArticleMapper {@Select("select * from articleinfo where uid = #{uid} order by id desc")List<Articleinfo> getListByUid(@Param("uid") int uid);
}

service:

@Service
public class ArticleService {@Autowiredprivate ArticleMapper articleMapper;public List<Articleinfo> getListByUid(@Param("uid") int uid) {return articleMapper.getListByUid(uid);}
}

controller: 

    //得到当前登录用户的文章列表@RequestMapping("/mylist")public ResultAjax myList(HttpServletRequest request) {// 1.等到当前登录的用户Userinfo userinfo = SessionUtils.getUser(request);if(userinfo == null) {return ResultAjax.fail(-1, "请先登录!");}// 2.根据用户的id查询你次用户发表的所有文章List<Articleinfo> list = articleService.getListByUid(userinfo.getId());//处理list->将文章正文变成简介if(list != null && list.size() > 0) {//并发的处理文章的内容,然后处理集合中每一个元素list.stream().parallel().forEach((art) -> {if(art.getContent().length() > _DESC_LENGTH) {//这是简介内容,我们取前120个字符art.setContent(art.getContent().substring(0, _DESC_LENGTH));}});}return ResultAjax.succ(list);}

4.6添加博客

Mapper:

@Select("select * from userinfo where username=#{username}")Userinfo getUserByName(@Param("username")String username);

service:

 public int add(Articleinfo articleinfo) {return articleMapper.add(articleinfo);}

controller:

//添加文章@RequestMapping("/add")public ResultAjax add(Articleinfo articleinfo, HttpServletRequest request) {// 1.校验参数if(articleinfo == null || !StringUtils.hasLength(articleinfo.getTitle()) ||!StringUtils.hasLength(articleinfo.getContent())) {return ResultAjax.fail(-1, "非法参数!");}// 2.组装数据Userinfo userinfo = SessionUtils.getUser(request);if(userinfo == null) {return ResultAjax.fail(-2, "请先登录");}articleinfo.setUid(userinfo.getId());int ret = articleService.add(articleinfo);// 3.将结果返回给前端return ResultAjax.succ(ret);}

4.7删除博客

Mapper:

@Delete("delete from articleinfo where id = #{aid} and uid = uid")int del(@Param("aid") Integer aid, int uid);

Service:

public int del(Integer aid, int uid) {return articleMapper.del(aid, uid);}

Controller:

//删除文章@RequestMapping("/del")public ResultAjax del(Integer aid, HttpServletRequest request) {// 1.参数校验if(aid == null || aid <= 0) {return ResultAjax.fail(-1, "参数错误");}// 2.获取登录的用户Userinfo userinfo = SessionUtils.getUser(request);if(userinfo == null) {return ResultAjax.fail(-1, "请先登录");}// 3.执行删除操作// 执行删除操作,我们有很多的方式,这里采用 aid和uid 的方法int ret = articleService.del(aid, userinfo.getId());if(ret == 0) {return ResultAjax.fail(-1, "你不是文章的归属人");}return ResultAjax.succ(ret);}

4.8查看文章详情

查看文章主要包含三个功能:

  • 查询文章的内容
  • 查询相应的作者信息
  • 查询文章总数

最后两点我们可以使用多线程的方式来实现,提高查询的效率,同时三个功能使用一个HTTP请求,以减少多次连接和断开的次数,减少资源的消耗.

ArticleMapper:

    @Select("select * from articleinfo where id = #{aid}")Articleinfo getDetailById(@Param("aid") int aid);@Select("select count(*) from articleinfo where uid = #{uid}")int getArtCountByUid(@Param("uid") int uid);

UserMapper:

    @Select("select * from userinfo where id = #{uid}")UserinfoVO getUseById(@Param("uid") int uid);

ArticleService:

    public Articleinfo getDetail(int aid) {return articleMapper.getDetailById(aid);}public int getArtCountByUid(int uid) {return articleMapper.getArtCountByUid(uid);}

UserService:

public UserinfoVO getUserById(int uid) {return userMapper.getUseById(uid);}

ArticleController:

//获取文章详情@RequestMapping("/detail")public ResultAjax detail(Integer aid) throws ExecutionException, InterruptedException {// 1.参数校验if(aid == null || aid <= 0) {return ResultAjax.fail(-1, "参数错误!");}// 2.查看文章详情Articleinfo articleinfo = articleService.getDetail(aid);if(articleinfo == null) {return ResultAjax.fail(-2, "查询文章不存在");}// 3.根据uid查询作者的详情信息FutureTask<UserinfoVO> userTask = new FutureTask<>(() -> {return userService.getUserById(articleinfo.getUid());});// 4.查询uid查询用户发表的文章总数FutureTask<Integer> artCountTask = new FutureTask<>(() -> {return articleService.getArtCountByUid(articleinfo.getUid());});taskExecutor.submit(artCountTask);taskExecutor.submit(userTask);// 5.组装数据UserinfoVO userinfoVO = userTask.get(); //等待任务执行完成int artCount = artCountTask.get(); //等待任务执行完成userinfoVO.setArtCount(artCount);HashMap<String, Object> result = new HashMap<>();result.put("user", userinfoVO);result.put("art", articleinfo);// 6.返回结果给前端return ResultAjax.succ(result);}

增加阅读量:

Mapper:

 @Update("update articleinfo set rcount = rcount + 1 where id = #{aid}")int incrementRCount(@Param("aid") int aid);

Service:

public int incrementRCount(int aid) {return articleMapper.incrementRCount(aid);}

Controller:

//文章阅读量加1@RequestMapping("/increment_rcount")public ResultAjax incrementRCount(Integer aid) {// 1.参数校验if(aid == null || aid <= 0) {return ResultAjax.fail(-1, "参数错误");}// 2.更改数据库int result = articleService.incrementRCount(aid);// 3.返回结果return ResultAjax.succ(result);}

4.9修改文章

Mapper:

    @Select("select * from articleinfo where id = #{aid} and uid = #{uid}")Articleinfo getArticleByIdAndUid(int aid, int uid);@Update("update articleinfo set title=#{title}, content=#{content} where id = #{id} and uid = #{uid}")int update(Articleinfo articleinfo);

service:

    public Articleinfo getArticleByIdAndUid(int aid, int uid) {return articleMapper.getArticleByIdAndUid(aid, uid);}public int update(Articleinfo articleinfo) {return articleMapper.update(articleinfo);}

controller:

//修改文章//更新文章@RequestMapping("/update")public ResultAjax update(Articleinfo articleinfo, HttpServletRequest request) {// 1.参数校验if(articleinfo == null || articleinfo.getId() <= 0 ||!StringUtils.hasLength(articleinfo.getTitle()) ||!StringUtils.hasLength(articleinfo.getContent())) {return ResultAjax.fail(-1, "参数错误!");}// 2.获取登录的用户Userinfo userinfo = SessionUtils.getUser(request);if(userinfo == null) {return ResultAjax.fail(-2, "请登录!");}// 3.操作数据库articleinfo.setUid(userinfo.getId());int ret = articleService.update(articleinfo);return ResultAjax.succ(ret);}//修改文章//获取文章@RequestMapping("/update_init")public ResultAjax updateInit(Integer aid, HttpServletRequest request) {// 1.参数校验if(aid == null || aid <= 0) {return ResultAjax.fail(-1, "参数错误!");}// 2.操作数据库Userinfo userinfo = SessionUtils.getUser(request);if(userinfo == null) {return ResultAjax.fail(-2, "请登录");}//我们利用where id = #{aid} and uid = #{uid}的操作校验文章所有者Articleinfo articleinfo = articleService.getArticleByIdAndUid(aid, userinfo.getId());// 3.返回结果return ResultAjax.succ(articleinfo);}

4.10文章列表页

文章列表页,主要包含两部分:

  1. 文章的获取
  2. 分页功能

mapper:

    @Select("select * from articleinfo order by id desc limit #{psize} offset #{offset}")List<Articleinfo> getListByPage(@Param("psize") int psize, @Param("offset") int offset);@Select("select count(*) from articleinfo")int getCount();

service:

    public List<Articleinfo> getListByPage(int psize, int offset) {return articleMapper.getListByPage(psize, offset);}public int getCount() {return articleMapper.getCount();}

controller:

//查询分页功能@RequestMapping("/getlistbypage")public ResultAjax getListByPage(Integer pindex, Integer psize) throws ExecutionException, InterruptedException {// 1.参数校验if(pindex == null) {pindex = 1;}if(psize == null) {psize = 2;}// 2.并发执行文章列表和总页数的查询int finalOffset = psize * (pindex - 1); // 分页公式int finalPSize = psize;FutureTask<List<Articleinfo>> listTask = new FutureTask<>(() -> {return articleService.getListByPage(finalPSize, finalOffset);});FutureTask<Integer> sizeTask = new FutureTask<Integer>(() -> {int totalCount = articleService.getCount();if(totalCount % finalPSize != 0) {return totalCount / finalPSize + 1;}return totalCount/ finalPSize;});taskExecutor.submit(listTask);taskExecutor.submit(sizeTask);// 3.组装数据List<Articleinfo> list = listTask.get();int size = sizeTask.get();HashMap<String, Object> map = new HashMap<>();map.put("list", list);map.put("size", size);// 4.将结果返回给前端return ResultAjax.succ(map);}

4.11注销功能

Controller:

//注销功能@RequestMapping("/logout")public ResultAjax logout(HttpServletRequest request) {HttpSession session = request.getSession(false);if(session != null && session.getAttribute(AppVariable.SESSION_USERINFO_KEY) != null) {session.removeAttribute(AppVariable.SESSION_USERINFO_KEY);}return ResultAjax.succ(1);}

5.加盐算法

/*** Describe: 密码工具类* User:lenovo* Date:2023-08-10* Time:10:45*/
public class PasswordUtils {/*** 加盐加密*/public static String encrypt(String password) {// 1.盐值String salt = UUID.randomUUID().toString().replace("-", "");// 2.将盐值+密码进行md5得到最终密码String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes(StandardCharsets.UTF_8));// 3.将盐值和最终密码进行返回return salt + "$" + finalPassword;}/*** 加盐验证*/public static boolean decrypt(String password, String dbpassword) {if(!StringUtils.hasLength(password) || !StringUtils.hasLength(dbpassword) ||dbpassword.length() != 65) {return false;}// 1.得到盐值String[] dbPasswordArray = dbpassword.split("\\$");if(dbPasswordArray.length != 2) {return false;}// 盐值String salt = dbPasswordArray[0];// 最终密码String dbFinalPassword = dbPasswordArray[1];// 2.加密待验证的密码String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes(StandardCharsets.UTF_8));// 3.对比return finalPassword.equals(dbFinalPassword);}
}

修改原来的UserController:

//注册功能:添加用户@RequestMapping("/reg")public ResultAjax reg(Userinfo userinfo) {//1.参数校验if(userinfo.getUsername() == null || userinfo.getUsername().trim().equals("")) {return ResultAjax.fail(-1, "参数错误!");}if(userinfo.getPassword() == null || userinfo.getPassword().trim().equals("")) {return ResultAjax.fail(-1, "参数错误");}//2.处理数据int ret = userService.reg(userinfo.getUsername(), PasswordUtils.encrypt(userinfo.getPassword()));//3.返回结果return ResultAjax.succ(ret);}//登录接口:根据名字查找用户@RequestMapping("/login")public ResultAjax getUserByName(UserinfoVO userinfoVO, HttpServletRequest request) {// 1.校验参数if(userinfoVO == null || !StringUtils.hasLength(userinfoVO.getUsername()) ||!StringUtils.hasLength(userinfoVO.getPassword())) { //这里我们使用StringUtils.hasLength判断它是否为null或为空return ResultAjax.fail(-1, "非法参数!");}// 2.根据用户名查找对象Userinfo userinfo = userService.getUserByName(userinfoVO.getUsername());if(!PasswordUtils.decrypt(userinfoVO.getPassword(), userinfo.getPassword())) {//密码错误return ResultAjax.fail(-2, "账号或密码错误!");}// 3.将对象存储到session中HttpSession session = request.getSession();session.setAttribute(AppVariable.SESSION_USERINFO_KEY, userinfo);// 4.将结果返回给前端return ResultAjax.succ(1);}

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

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

相关文章

(el-switch)操作(不使用 ts):Element-plus 中 Switch 将默认值修改为 “true“ 与 “false“(字符串)来控制开关

Ⅰ、Element-plus 提供的 Switch 开关组件与想要目标情况的对比&#xff1a; 1、Element-plus 提供 Switch 组件情况&#xff1a; 其一、Element-ui 自提供的 Switch 代码情况为(示例的代码)&#xff1a; // Element-plus 自提供的代码&#xff1a; // 此时是使用了 ts 语言环…

Flutter BottomSheet 三段式拖拽

BottomSheetBehavior 追踪 BottomSheet系统默认实现效果准备要实现的功能点&#xff1a;定义三段式状态&#xff1a;BottomSheetBehavoir阀值定义1. 未达到滚动阀值&#xff0c;恢复状态2. 达到滚动阀值&#xff0c;更新状态 前面倒是有讲过Android原生的BottomSheetBehavior&a…

Zorin OS 16.3 发布:无缝升级和卓越改进!

导读Zorin OS 团队自豪地宣布了备受期待的 Zorin OS 16.3 版本的发布&#xff0c;这是这个受欢迎的 Linux 发行版的一个里程碑版本。自首次发布以来不到两年时间&#xff0c;Zorin OS 已经获得了庞大的用户群体&#xff0c;截至目前已经有 530 万次下载&#xff0c;而 16.3 版本…

Centos7.9安装lrzsz进行文件传输---Linux工作笔记059

这里咱们lrzsz命令,需要用来进行文件传输,因为如果不安装这个命令的话,那么 传输安装包什么的就不方便因为只有少数传输工具,才支持,直接拖拽的.没有的时候就可以用这个工具,用命令来传输 直接就是: sz 文件名 就可以把文件下载下来 rz 选择一个文件, 就可以把文件上传到当…

ppt压缩文件怎么压缩最小?文件压缩技巧分享

在日常的工作和学习中&#xff0c;难免会遇到PPT太大&#xff0c;需要将其压缩变小的情况&#xff0c;但很多朋友还不知道怎么压缩PPT文件&#xff0c;下面就给大家分享几个简单的方法&#xff0c;分分钟缩小过大的PPT文件。 一、PowerPoint PowerPoint就是微软公司的演示文稿…

数据结构-1

1.2 线性结构树状结构网状结构&#xff08;表 数 图&#xff09; 数据&#xff1a;数值型 非数值型 1.2.3数据类型和抽象数据类型 1.3抽象数据类型 概念小结&#xff1a; 线性表: 如果在独立函数实现的 .c 文件中需要包含 stdlib.h 头文件&#xff0c;而主函数也需要包含 st…

2023年“云舟杯”视频孪生演讲大赛总决赛完美收官

8月4日&#xff0c;智汇云舟举办的2023年“云舟杯”视频孪生演讲大赛总决赛以直播形式完美收官。来自全国近200家合作伙伴代表齐聚线上&#xff0c;共同观摩比赛。在巅峰之战中&#xff0c;参赛学员们充分展示了各自对行业数字化转型的敏锐洞察、对智汇云舟视频孪生技术与产品的…

AttentionFreeTransformer 源码解析(一):AFTFull、AFTSimple、AFTLocal

我觉得源码写的很好懂&#xff0c;我就不加注释了&#xff0c;直接上计算流程图。 AFTFull class AFTFull(nn.Module):def __init__(self, max_seqlen, dim, hidden_dim64):super().__init__()max_seqlen: the maximum number of timesteps (sequence length) to be fed indim…

ChatGLM2-6B在windows下的部署

2023-08-10 ChatGLM2-6B在windows下的部署 一、部署环境 1、Windows 10 专业版&#xff0c; 64位&#xff0c;版本号&#xff1a;22H2&#xff0c;内存&#xff1a;32GB 2、已安装CUDA11.3 3、已安装Anaconda3 64bit版本 4、有显卡NVIDIA GeForce RTX 3060 Laptop GPU …

【EI复现】考虑区域多能源系统集群协同优化的联合需求侧响应模型(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

编程小白必看!Visual Studio 2022详细安装使用教程(C/C++编译器)

目录 【前言】 一、Visual Studio 2022简介 二、Visual Studio 2022下载安装 1.Visual Studio 2022下载地址 2.Visual Studio 2022安装 2.1下载完成后点击打开安装 2.2安装完毕以后需要重启软件&#xff0c;点击确定。 三、Visual Studio 2022使用教程 【最后】 &#x…

Soundpad解决自动键失效的问题

这里给出解决方法&#xff0c;具体原因我也不太懂&#xff0c;因为我也是做实验得出某些操作可能会导致自动键不起作用。 首先打开首选项&#xff0c;配置如下图所示&#xff0c;这里只改了特殊热键的五个键位和自动键 我之前犯的错误&#xff0c;我相信大部分跟我一样&#…

23、springboot日志使用入门-- SLF4J+Logback 实现(springboot默认的日志实现),日志打印到控制台及日志输出到指定文件

springboot日志使用入门 ★ 典型的Spring Boot日志依赖&#xff1a; spring-boot-start.jar -- spring-boot-starter-logging.jar (Spring Boot的日志包&#xff09;-- logback&#xff08;core、classic&#xff09;-- log4j-to-slf4j.jar-- jul-to-slf4j.jar就是springboo…

多维时序 | MATLAB实现CNN-BiGRU-Attention多变量时间序列预测

多维时序 | MATLAB实现CNN-BiGRU-Attention多变量时间序列预测 目录 多维时序 | MATLAB实现CNN-BiGRU-Attention多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现CNN-BiGRU-Attention多变量时间序列预测&#xff0c;CNN-BiGRU-Attent…

微信小程序备案流程

微信小程序备案流程 &#x1f4d4; 千寻简笔记介绍 千寻简笔记已开源&#xff0c;Gitee与GitHub搜索chihiro-notes&#xff0c;包含笔记源文件.md&#xff0c;以及PDF版本方便阅读&#xff0c;且是用了精美主题&#xff0c;阅读体验更佳&#xff0c;如果文章对你有帮助请帮我…

Nginx负载均衡(重点)

正向代理 部署正向代理 server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; proxy_pass http://20.0.0.60:80…

UNIX基础知识:UNIX体系结构、登录、文件和目录、输入和输出、程序和进程、出错处理、用户标识、信号、时间值、系统调用和库函数

引言&#xff1a; 所有的操作系统都为运行在其上的程序提供服务&#xff0c;比如&#xff1a;执行新程序、打开文件、读写文件、分配存储区、获得系统当前时间等等 1. UNIX体系结构 从严格意义上来说&#xff0c;操作系统可被定义为一种软件&#xff0c;它控制计算机硬件资源&…

试卷擦除答案的工具,几个步骤轻松搞定

在学生的学习生活中&#xff0c;考试是必不可少的一部分。然而&#xff0c;有时候我们在做完试卷后发现自己填错了答案&#xff0c;或者想要更改答案&#xff0c;但是试卷上已经有了痕迹。这时候&#xff0c;我们就需要一些工具来擦除答案。以下是几个简单的步骤&#xff0c;让…

geoserver编辑样式 【开发工具QGis的初次使用】

geoserver编辑样式 开发工具配置中文语言 geoserver样式的更改 开发工具 链接: geoserver样式style的更改 链接: QGis开发工具的安装及使用 配置中文语言 setting > options > general > 中文 geoserver样式的更改 链接: geoserver样式style的更改 利用QGIs Q…

Oracle 知识篇+分区表上的索引由global改为local注意事项

★ 知识点 二、知识点 Local型索引有如下优点 1.Only one index partition must be rebuilt when a maintenance operation other than SPLIT PARTITION or ADD PARTITION is performed on an underlying table partition. 2.The duration of a partition maintenance opera…