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

【个人博客系统网站】我的博客列表页 · 增删改我的博文 · 退出登录 · 博客详情页 · 多线程应用

【JavaEE】进阶 · 个人博客系统(4)

在这里插入图片描述

文章目录

  • 【JavaEE】进阶 · 个人博客系统(4)
    • 1. 增加博文
    • 1.1 预期效果
      • 1.1 约定前后端交互接口
      • 1.2 后端代码
      • 1.3 前端代码
      • 1.4 测试
    • 2. 我的博客列表页
      • 2.1 期待效果
      • 2.2 显示用户信息以及博客信息
        • 2.2.1 约定前后端交互接口
        • 2.2.2 后端代码
        • 2.2.3 前端代码
        • 2.2.4 测试
      • 2.3 删除文章
        • 2.3.1 约定前后端交互接口
        • 2.3.2 后端代码
        • 2.3.3 前端代码
        • 2.3.4 测试
      • 2.4 退出登录
        • 2.4.1 约定前后端交互接口
        • 2.4.2 后端代码
        • 2.4.3 前端代码
        • 2.4.4 测试
    • 3. 修改文章
      • 3.1 页面初始化
        • 3.1.1 约定前后端接口
        • 3.1.2 后端代码
        • 3.1.3 前端代码
        • 3.1.4 测试
      • 3.2 修改文章
        • 3.2.1 约定前后端交互接口
        • 3.2.2 后端代码
        • 3.2.3 前端代码
        • 3.2.4 测试
    • 4. 博客详情页
      • 4.1 期待效果
      • 4.2 约定前后端交换接口
      • 4.3 后端代码
      • 4.4 前端代码
      • 4.5 测试

【JavaEE】进阶 · 个人博客系统(4)

1. 增加博文

1.1 预期效果

a

用户在网页中编写标题和正文,点击提交,选择

  1. 输入摘要
  2. 取消,继续编写文章

提交成功后,选择

  1. 继续写文章
  2. 返回“我的博客列表页”

1.1 约定前后端交互接口

后端:

  1. /art/publish
  2. 将前端传递过来的数据保存到数据库
  3. 返回受影响行数

前端:

  1. /art/publish
  2. 标题,正文,摘要
  3. 当前登录用户sessionid

1.2 后端代码

在这里插入图片描述

  1. controller层

由于经常需要对字符串进行检查,我封装了一个方法:

  • 为什么前端检验完了,后端还检验呢?
    • 千万别相信“前端”,因为这个“前端”,可能不是浏览器正常的流程,也可能是通过postman等方式发送的请求,这个就可以绕开前端代码的校验~
    • 不用担心,因为
public class APPUtils {/*** 字符串全部都有长度才返回true* @param strings* @return*/public static boolean hasLength(String... strings) {for(String x : strings) {if(!StringUtils.hasLength(x)) {return false;}}return true;}
}

修改:

在这里插入图片描述

在这里插入图片描述

@RequestMapping("/publish")
public CommonResult publish(@RequestBody ArticleInfo articleInfo, HttpServletRequest request) {// 1. 获取当前用户详信息UserInfo userInfo = SessionUtils.getUser(request);articleInfo.setUid(userInfo.getId());articleInfo.setPhoto(userInfo.getPhoto());// 2. 校验参数if(!APPUtils.hasLength(articleInfo.getContent(), articleInfo.getSummary(), articleInfo.getTitle())) {return CommonResult.fail(-1, "非法参数!");}// 3. 提交到数据库中int rows = articleService.publish(articleInfo);// 4. 返回return CommonResult.success(rows);
}
  1. service层
@Autowired
private ArticleMapper articleMapper;public int publish(ArticleInfo articleInfo) {return articleMapper.insert(articleInfo);    
}
  1. mapper层
@Insert("insert into articleinfo (title, content, summary, uid, photo) values (#{title}, #{content}, #{summary}, #{uid}, #{photo})")
int insert(ArticleInfo articleInfo);
  1. 拦截器配置
    • 拦截,不排除此接口

1.3 前端代码

在这里插入图片描述

function publish() {var title = jQuery("#text");var content = jQuery("#content");// 1. 参数校验if (title.val().trim() == "") {alert("标题不能为空!");title.focus();return false;}if (content.val().trim() == "") {alert("正文不能为空!");content.focus();return false;}// 2. 输入摘要var summary = prompt("请输入摘要:");if(summary == "") {return false;}// 3. 发送请求jQuery.ajax({url: "/art/publish",method: "POST",contentType: "application/json; charset=utf8",data: JSON.stringify({title: title.val().trim(),content: content.val().trim(),summary: summary.val().trim(),}),// 3. 处理响应success: function (body) {if (body.code == 200 && body.data == 1) {if(confirm("发布成功!请问是否继续创作?")) {location.href = location.href;}else {location.href = "myblog_lists.html";}} else {alert("发布失败:" + body.msg);}},});
}

1.4 测试

在这里插入图片描述

在这里插入图片描述

为了避免写文章过程中session过去,我将session设置为永不过期:

在这里插入图片描述

2. 我的博客列表页

2.1 期待效果

在这里插入图片描述

  1. 左侧窗口显示用户信息
  2. 右侧窗口显示用户创作的博文简介
    1. 标题
    2. 时间以及阅读量
    3. 摘要
    4. 查看正文,修改文章,删除文章按钮
  3. 右上角
    1. 点击主页跳转到所有人的博客列表页
    2. 点击写博客跳转到博客创作页
    3. 点击退出登录,后端删除登录记录,跳转到登录页面

2.2 显示用户信息以及博客信息

2.2.1 约定前后端交互接口

后端:

  1. /article/get_mylist
  2. 通过当前登录用户查询博客
  3. 返回用户信息以及博客信息的组合

前端:

  1. /article/get_mylist
  2. get
  3. 接受响应,投喂给页面

2.2.2 后端代码

  1. controller层
@RequestMapping("/get_mylist")
public CommonResult getMylist(HttpServletRequest request) {// 1. 获取当前登录用户UserInfo userInfo = SessionUtils.getUser(request);// 2. 通过此用户发布的所有文章List<ArticleInfo> list = articleService.getListByUid(userInfo.getId());// 3. 标题 / 正文太长 处理ArticleUtils.substringList(list);// 4. 返回给前端Map<String, Object> map = new HashMap<>();map.put("user", userInfo);map.put("list", list);return CommonResult.success(map);
}
// 文章工具类
public class ArticleUtils {//标题截取长度private static final int _TITLE_LENGTH = 40;//摘要截取长度private static final int _SUMMARY_LENGTH = 160;public static void substringList(List<ArticleInfo> list) {if(list != null && list.size() != 0) {// 并发处理 list 集合list.stream().parallel().forEach((art) -> {//标题截取if(art.getTitle().length() > _TITLE_LENGTH) {art.setTitle(art.getTitle().substring(0, _TITLE_LENGTH) + "...");}//摘要截取if(art.getSummary().length() > _SUMMARY_LENGTH) {art.setSummary(art.getSummary().substring(0, _SUMMARY_LENGTH) + "...");}});}}
}
  1. service层
public List<ArticleInfo> getListByUid(int uid) {return articleMapper.getListByUid(uid);
}
  1. mapper层
@Select("select * from articleinfo where uid = #{uid} order by id desc")
List<ArticleInfo> getListByUid(@Param("uid") int uid); //越晚发布排在越前
  1. 拦截器配置
    • 不排除此接口
  2. 时间格式配置

可以接受数据库时间的类型一般是:

  1. Date
  2. LocalDataTime
  3. TimeStamp

网络资料

LocalDateTime和Date是Java中表示日期和时间的两种不同的类,它们有一些区别和特点。

  1. 类型:LocalDateTime是Java 8引入的新类型,属于Java 8日期时间API(java.time包)。而Date是旧版Java日期时间API(java.util包)中的类。

  2. 不可变性:LocalDateTime是不可变的类型,一旦创建后,其值是不可变的。而Date是可变的类型,可以通过方法修改其值。

  3. 线程安全性:LocalDateTime是线程安全的,多个线程可以同时访问和操作不同的LocalDateTime实例。而Date是非线程安全的,如果多个线程同时访问和修改同一个Date实例,可能会导致不可预期的结果。

  4. 时间精度:LocalDateTime提供了纳秒级别的时间精度,可以表示更加精确的时间。而Date只能表示毫秒级别的时间精度。

  5. 时区处理:LocalDateTime默认不包含时区信息,表示的是本地日期和时间。而Date则包含时区信息,它的实际值会受到系统默认时区的影响。

而TimeStamp就是long类型的时间戳的包装~

对于时间格式的控制:

  1. json的构造本身是通过getter去获取的,所以可以重写getter来控制显示效果

  2. 全局配置:

    在这里插入图片描述

    但是这只适合jdk8之前的Date类型

  3. 局部配置:

    • 对于时间类型的属性,是可以通过注解@JsonFormat来配置的:

    在这里插入图片描述

2.2.3 前端代码

左:

在这里插入图片描述

右:

在这里插入图片描述

jQuery.ajax({type: "get",url: "/art/get_mylist",success: function (body) {if (body.code == 200) {// 1. 改变左侧窗口jQuery(".card img").attr("src", body.data.user.photo);jQuery(".card h3").text(body.data.user.name);if(body.data.user.git.trim() != "") {jQuery(".card a").attr("href", body.data.user.git);}jQuery("#count").text(body.data.list.length);// 2. 显示文章,构造博客html元素for (var blog of body.data.list) {console.log(body.title);var art ='<div class="blog"><div class="title">' + blog.title + "</div>";art +='<div class="date">' +blog.createtime +" 阅读量:" +blog.rcount +"</div>";art += '<div class="content">' + blog.summary + "</div>";art += '<div class="thing">';art +='<a href="blog_detail.html?aid=' + blog.id + '">查看正文</a>';art +='<a href="myblog_update.html?aid=' + blog.id + '">修改文章</a>';art +='<div id="del" style="background-color: rgba(255, 0, 0, 0.6)" οnclick="del(' +blog.id +')">删除文章</div>';art += "</div></div>";// 3. 追加到div.articlejQuery(".article").append(jQuery(art));}}},
});

你也可以,以标签为单位去设置属性以及嵌套,这有逻辑的构建;而我这里是单纯的拼接字符串,用jQuery(str),构造html元素

2.2.4 测试

在这里插入图片描述

2.3 删除文章

2.3.1 约定前后端交互接口

后端:

  1. /art/delete
  2. 根据当前登录用户id,和删除文章对应的作者id,判断是否有权限删除,有才能删除
  3. 返回受影响行数

前端:

  1. /art/delete
  2. post
  3. JSON:id(文章id)
  4. 如果受影响行数为1,刷新页面

2.3.2 后端代码

  1. controller层
@RequestMapping("/delete")
public CommonResult delete(@RequestBody ArticleInfo articleInfo, HttpServletRequest request) {// 1. 获取当前登录用户的idint uid = SessionUtils.getUser(request).getId();// 2. 设置到文章对象里articleInfo.setUid(uid);// 3. 删除int rows = articleService.delete(articleInfo);// 4. 返回return CommonResult.success(rows);
}
  1. service层
public int delete(ArticleInfo articleInfo) {return articleMapper.delete(articleInfo);
}
  1. mapper层
@Delete("delete from articleinfo where id = #{id} and uid = #{uid}")
// 查找文章和检测权限在一步搞定
int delete(ArticleInfo articleInfo);
  1. 拦截器配置
    • 拦截,不排除

2.3.3 前端代码

function del(aid) {// 0. 参数校验if (parseInt(aid) == NaN || aid <= 0) {return false;}jQuery.ajax({method: "post",url: "/art/delete",contentType: "application/json; charset=utf8",data: JSON.stringify({id: aid,}),success: function (body) {if (body.code == 200 && body.data == 1) {location.href = location.href;} else {alert("删除失败!\n");}},});
}

2.3.4 测试

在这里插入图片描述

2.4 退出登录

2.4.1 约定前后端交互接口

后端:

  1. /user/logout
  2. 根据当前用户进行删session操作
  3. 无返回值

前端:

  1. /user/logout
  2. a标签的get

2.4.2 后端代码

  1. controller层
@RequestMapping("/logout")
public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException {// 设置为null也可以,但这是因为我们的判断原理的原因//SessionUtils.setUser(request, null);// 调用工具类里的注销方法SessionUtils.remove(request);response.sendRedirect("blog_login.html");
}
/*** 注销* @param request*/
public static void remove(HttpServletRequest request) {HttpSession session = request.getSession(false);if(session != null && session.getAttribute(ApplicationVariable.SESSION_KEY) != null) {session.removeAttribute(ApplicationVariable.SESSION_KEY);}
}
  1. 拦截器配置
    • 拦截,不排除

2.4.3 前端代码

<a href="/user/logout">退出登录</a>

2.4.4 测试

在这里插入图片描述

3. 修改文章

在这里插入图片描述
在这里插入图片描述

预期效果就是:原有数据显示出来,供用户修改

3.1 页面初始化

3.1.1 约定前后端接口

后端:

  1. /art/get_art
  2. 根据uid和aid查询文章
  3. 返回文章信息

前端:

  1. /art/get_art
  2. post,json,aid
  3. 将数据投喂到网页

3.1.2 后端代码

  1. controller层
@RequestMapping("/get_art")
public CommonResult getArt(@RequestBody ArticleInfo articleInfo, HttpServletRequest request) {// 1. 获取当前登录用户的idint uid = SessionUtils.getUser(request).getId();// 2. 设置到文章对象里articleInfo.setUid(uid);// 3. 查询文章ArticleInfo art = articleService.getArt(articleInfo);// 4. 返回(查询不到一个对象,是null;如果查询不到对象集合,返回的是空集合)return art == null ? CommonResult.fail(-1, "查询不到!") : CommonResult.success(art);
}
  1. service层
public ArticleInfo getArt(ArticleInfo articleInfo) {return articleMapper.getArticleCheck(articleInfo);
}
  1. mapper层
@Select("select * from articleinfo where id = #{id} and uid = #{uid}")
ArticleInfo getArticleCheck(ArticleInfo articleInfo);//检查权限的查询文章@Select("select * from articleinfo where id = #{id}")
ArticleInfo getArticle(ArticleInfo articleInfo);
  1. 拦截器配置
    • 拦截,不排除

3.1.3 前端代码

<script>var aid = getParamValue("aid");// 1. 校验参数function init() {if (aid == null || aid <= 0) {alert("非法参数!");location.href = "myblog_lists.html";return false;}// 2. 查询文章jQuery.ajax({url: "/art/get_art",method: "post",contentType: "application/json; charset=utf8",data: JSON.stringify({id: aid,}),success: function (body) {if (body.code == 302) {location.href = body.msg;return false;}if (body.code == 200) {jQuery("#text").val(body.data.title);jQuery("#content").val(body.data.content);jQuery("#summary").val(body.data.summary);//用隐藏输入框保存摘要信息} else {alert("发布失败:" + body.msg);}},});}init();
</script>

在这里插入图片描述

注意:

  1. 如果直接写代码的话,而不是调用方法,默认页面跟代码一起加载,而调用方法是页面加载后调用此init方法
    • 如果不采取这种方式的话,会导致请求返回的页面,被拦截器拦下
  2. 为什么还是用json而不是用querystring直接发送请求
    • 习惯吧,因为json比较通用,如果还需要其他信息,querystring不方便
  3. 修改页跟添加页是一样的,为什么不重用?
    • 重用会导致一些没有必要的判断,不符合单一设计原则,麻烦/乱/开发不舒适,耦合度高…

3.1.4 测试

在这里插入图片描述

3.2 修改文章

3.2.1 约定前后端交互接口

后端:

  1. /art/update
  2. 接受文章数据
  3. 返回受影响行数

前端:

  1. /art/update
  2. post,json,上传文章数据
  3. 成功则跳转到我的博客列表页

3.2.2 后端代码

  1. controller层
@RequestMapping("/update")
public CommonResult update(@RequestBody ArticleInfo articleInfo, HttpServletRequest request) {// 0. 确认用户int uid = SessionUtils.getUser(request).getId();articleInfo.setUid(uid);// 1. 校验参数if(!APPUtils.hasLength(articleInfo.getContent(), articleInfo.getSummary(), articleInfo.getTitle())) {return CommonResult.fail(-1, "非法参数!");}// 2. 修改int rows = articleService.update(articleInfo);// 3. 返回return CommonResult.success(rows);
}
  1. service层
public int update(ArticleInfo articleInfo) {return articleMapper.updateArticle(articleInfo);
}
  1. mapper层
    • 必须是有权限才能修改
    • 更新时间修改为当下
@Update("update articleinfo set content = #{content}, title = #{title}, summary = #{summary}, updatetime = now() where id = #{id} and uid = #{uid}")
int updateArticle(ArticleInfo articleInfo);
  1. 拦截器配置
    • 拦截,不排除

3.2.3 前端代码

在这里插入图片描述

function update() {if (aid == null || aid <= 0) {alert("非法参数!");location.href = "myblog_lists.html";return false;}var title = jQuery("#text");var content = jQuery("#content");// 1. 参数校验if (title.val().trim() == "") {alert("标题不能为空!");title.focus();return false;}if (content.val().trim() == "") {alert("正文不能为空!");content.focus();return false;}// 2. 输入摘要var summary = prompt("请输入摘要:", jQuery("#summary").val());if (summary.trim() == "") {return false;}jQuery("#summary").val(summary);// 3. 发送请求jQuery.ajax({url: "/art/update",method: "POST",contentType: "application/json; charset=utf8",data: JSON.stringify({id: aid,title: title.val().trim(),content: content.val().trim(),summary: summary.trim(),}),// 3. 处理响应success: function (body) {if (body.code == 302) {location.href = body.msg;return false;}if (body.code == 200 && body.data == 1) {location.href = "myblog_lists.html";} else {alert("修改失败:" + body.msg);}},});
}

3.2.4 测试

4. 博客详情页

4.1 期待效果

在这里插入图片描述

  1. 根据是否登录,改变导航栏
  2. 根据querystring中的aid,显示对应的博文,和作者信息
  3. 每次访问成功,阅读量加1(本次显示是加1之前)
  4. 作者的文章总数通过后端计算
  5. 正文以html的样式渲染出来

这样的复杂查询可以用到并发编程:

  • 【JavaEE】Callable接口(NO.6线程创建方法)-JUC的常见类-与线程安全有关集合类_s:103的博客-CSDN博客
  • 用有返回值的线程创建方式(获取的时候若未结束,等待…)

4.2 约定前后端交换接口

后端:

  1. /art/detail
  2. 通过aid,找到文章
  3. 通过文章,uid找到作者,查询总文章数,通过aid修改文章阅读量
  4. 返回:
    1. “login”,true/false,true代表登录中
    2. “count”,文章数
    3. “user”,用户
    4. “art”,文章

前端:

  1. /art/detail
  2. json,aid
  3. 接受响应,投喂给代码

4.3 后端代码

  1. controller层
    1. 查询文章信息
    2. 校验文章是否存在
    3. 根据uid查询用户总文章数的任务
    4. 根据uid查询用户信息的任务
    5. 根据aid更新阅读量的任务
    6. 线程池执行任务
    7. 构造响应数据,并返回
@Autowired
private ArticleService articleService;
@Autowired
private UserService userService;
@RequestMapping("/detail")
public CommonResult detail(@RequestBody ArticleInfo articleInfo, HttpServletRequest request) throws ExecutionException, InterruptedException {// 1. 查询文章信息ArticleInfo art = articleService.getArtByAid(articleInfo);// 2. 校验文章是否存在if(art == null) {return CommonResult.fail(-1, "非法参数!");}// 3. 根据uid查询用户总文章数的任务FutureTask<Integer> task1 = new FutureTask<Integer>(() -> {return articleService.getArtNumberByUid(art.getUid());});// 4. 根据uid查询用户信息的任务FutureTask<UserInfo> task2 = new FutureTask<UserInfo>(() -> {return userService.getUserByUid(art.getUid());});// 5. 根据aid更新阅读量的任务FutureTask<Integer> task3 = new FutureTask<Integer>(() -> {return articleService.incrementRCount(art.getId());});// 6. 线程池执行任务APPUtils.THREAD_POOL.submit(task1);APPUtils.THREAD_POOL.submit(task2);APPUtils.THREAD_POOL.submit(task3);// 7. 构造响应数据,并返回Map<String, Object> map = new HashMap<>();map.put("login", SessionUtils.getUser(request) != null);map.put("count", task1.get());map.put("user", task2.get());map.put("art", art);return CommonResult.success(map);
}

在这里插入图片描述

  1. service层

ArticleService:

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

UserService:

public UserInfo getUserByUid(int uid) {return userMapper.getUserByUid(uid);
}
  1. mapper层

ArticleMapper:

@Select("select count(*) from articleinfo where uid=#{uid}")
int getArtNumberByUid(@Param("uid") int uid);@Update("update articleinfo set rcount = rcount + 1 where id = #{aid}")
int incrementRCount(@Param("aid") int aid);

UserMapper:

@Select("select * from userinfo where id = #{uid}")
UserInfo getUserByUid(@Param("uid") int uid);
  1. 拦截器配置
    • 排除拦截
    • editor.md是个目录,要排除整个目录才对,不然后面渲染不上去,之前可以渲染是因为我们处于登录状态~
    • 因为详情页不需要登录~

在这里插入图片描述

4.4 前端代码

  1. 导航栏

在这里插入图片描述

  • 网页图标

在这里插入图片描述

  1. 右侧用户卡片

在这里插入图片描述

  1. 右侧文章信息

在这里插入图片描述

var aid = getParamValue("aid");
function init() {if (aid == null || aid <= 0) {alert("非法参数!");return false;}jQuery.ajax({method: "post",url: "/art/detail",contentType: "application/json; charset=utf8",data: JSON.stringify({id: aid,}),success: function (body) {if (body.code == 200) {// 1. 导航栏显示if (body.data.login == false) {jQuery("#icon").attr("href", "img/logo2.png");jQuery(".navigation img").attr("src", " img/logo2.png");jQuery(".navigation .space").css("width", "75%");jQuery(".title").text("未登录");jQuery("#add").hide();jQuery("#logout").text("登录");jQuery("#logout").attr("href", "blog_login.html");}// 2. 文章数显示jQuery("#count").text(body.data.count);// 3. 用户信息显示jQuery(".card img").attr("src", body.data.user.photo);jQuery(".card h3").text(body.data.user.name);if (body.data.user.git.trim() != "") {jQuery(".card a").attr("href", body.data.user.git);}// 4. 文章信息显示jQuery(".article h3").text(body.data.art.title);jQuery(".article .date").text(body.data.art.createtime + " 阅读量:" + body.data.art.rcount);editormd.markdownToHTML("pc", {markdown: body.data.art.content,});} else {alert("查看失败:" + body.msg);}},});
}
init();

4.5 测试

在这里插入图片描述


文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆

代码:myblog_system/src · 游离态/马拉圈2023年9月 - 码云 - 开源中国 (gitee.com)


相关文章:

【个人博客系统网站】我的博客列表页 · 增删改我的博文 · 退出登录 · 博客详情页 · 多线程应用

【JavaEE】进阶 个人博客系统&#xff08;4&#xff09; 文章目录 【JavaEE】进阶 个人博客系统&#xff08;4&#xff09;1. 增加博文1.1 预期效果1.1 约定前后端交互接口1.2 后端代码1.3 前端代码1.4 测试 2. 我的博客列表页2.1 期待效果2.2 显示用户信息以及博客信息2.2.1…...

安全狗陈奋:数据安全需要建立在传统网络安全基础之上

8月22日-23日&#xff0c;由创业邦主办的“2023 DEMO WORLD 企业开放式创新大会”在上海顺利举行。 作为国内云原生安全领导厂商&#xff0c;安全狗受邀出席此次活动。 本次大会以“拥抱开放”为主题&#xff0c;聚焦开放式创新&#xff0c;通过演讲分享、专场对接、需求发布…...

【Redis】深入探索 Redis 的数据类型 —— 哈希表 hash

文章目录 前言一、hash 类型相关命令1.1 HSET 和 HSETNX1.2 HGET 和 HMGET1.3 HKEYS、HVALS 和 HGETALL1.4 HEXISTS 和 HDEL1.5 HLEN1.6 HINCRBY 和 HINCRBYFLOAT1.7 哈希相关命令总结 二、hash 类型内部编码三、hash 类型的应用场景四、原生&#xff0c;序列化&#xff0c;哈希…...

网络安全应急响应典型案例-(DDOS类、僵尸网络类、数据泄露类)

一、DDOS类事件典型案例 DDOS攻击&#xff0c;即分布式拒绝服务攻击&#xff0c;其目的在于使目标电脑的网络或系统资源耗尽&#xff0c;使服务暂时中断或停止&#xff0c;导致其正常用户无法访问。CC攻击使用代理服务器向受害服务器发送大量貌似合法的请求&#xff08;通常…...

【测试开发】Mq消息重复如何测试?

本篇文章主要讲述重复消费的原因&#xff0c;以及如何去测试这个场景&#xff0c;最后也会告诉大家&#xff0c;目前互联网项目关于如何避免重复消费的解决方案。 Mq为什么会有重复消费的问题? Mq 常见的缺点之一就是消息重复消费问题&#xff0c;产生这种问题的原因是什么呢…...

C++和C#程序语言的区别

一直学习C++和C#,两者之间的区别总结一下 目录 一、两种语言概述 C++语言 C#语言 二、两种语言对比 2.1运行依赖...

CentOS配置Java环境报错-bash: /usr/local/jdk1.8.0_381/bin/java: 无法执行二进制文件

CentOS配置Java环境后执行java -version时报错&#xff1a; -bash: /usr/local/jdk1.8.0_381/bin/java: 无法执行二进制文件原因是所使用的jdk的版本和Linux内核架构匹配不上 使用以下命令查看Linux架构&#xff1a; [rootlocalhost ~]# cat /proc/version Linux version 3.1…...

MySQL进阶 —— 超详细操作演示!!!(上)

MySQL进阶 —— 超详细操作演示&#xff01;&#xff01;&#xff01;&#xff08;上&#xff09; 一、存储引擎1.1 MySQL 体系结构1.2 存储引擎介绍1.3 存储引擎特点1.4 存储引擎选择 二、索引2.1 索引概述2.2 索引结构2.3 索引分类2.4 索引语法2.5 SQL 性能分析2.6 索引使用2…...

一条爬虫抓取一个小网站所有数据

一条爬虫抓取一个小网站所有数据 ​ 今天闲来无事&#xff0c;写一个爬虫来玩玩。在网上冲浪的时候发现了一个搞笑的段子网&#xff0c;发现里面的内容还是比较有意思的&#xff0c;于是心血来潮&#xff0c;就想着能不能写一个Python程序&#xff0c;抓取几条数据下来看看&am…...

八大排序——快速排序

Hello&#xff0c;大家好&#xff0c;今天分享的八大排序里的快速排序&#xff0c;所谓快速排序是一个叫霍尔的人发明&#xff0c;有很多人可能会觉得为什么不叫霍尔排序&#xff0c;其中原因就是因为它快&#xff0c;快速则体现了它的特点&#xff0c;今天我们就来讲一下快速排…...

【ES】笔记-Class类剖析

Class Class介绍与初体验ES5 通过构造函数实例化对象ES6 通过Class中的constructor实列化对象 Class 静态成员实例对象与函数对象的属性不相通实例对象与函数对象原型上的属性是相通的Class中对于static 标注的对象和方法不属于实列对象&#xff0c;属于类。 ES5构造函数继承Cl…...

数学建模--Seaborn库绘图基础的Python实现

目录 1.绘图数据导入 2. sns.scatterplot绘制散点图 3.sns.barplot绘制条形图 4.sns.lineplot绘制线性图 5.sns.heatmap绘制热力图 6.sns.distplot绘制直方图 7.sns.pairplot绘制散图 8.sns.catplot绘制直方图 9.sns.countplot绘制直方图 10.sns.lmplot绘回归图 1.绘图数…...

lv3 嵌入式开发-2 linux软件包管理

目录 1 软件包管理 1.1流行的软件包管理机制 1.2软件包的类型 1.3软件包的命名 2 在线软件包管理 2.1APT工作原理 2.2更新软件源 2.3APT相关命令 3 离线软件包管理 1 软件包管理 1.1流行的软件包管理机制 Debian Linux首先提出“软件包”的管理机制---Deb软件包 …...

智能小区与无线网络技术

1&#xff0e;1 智能小区 智能小区指的是具有小区智能化系统的小区。所谓小区智能化系统&#xff0c;指的是在 现代计算机网络和通信技术的基础上&#xff0c;将传统的土木建筑技术与计算机技术、自动 控制技术、通信与信息处理技术、多媒体技术等先进技术相结合的自动化和综…...

如何传输文件流给前端

通过链接下载图片&#xff0c;直接http请求然后将文件流返回 注&#xff1a;music.ly是一个下载tiktok视频的免费接口 https://api19-core-c-useast1a.musical.ly/aweme/v1/feed/?aweme_idxxx func (m *FileBiz) DownloadFileV2(ctx *ctrl.Context, fileLink, fileName strin…...

Spring Security OAuth2 远程命令执行漏洞

文章目录 一、搭建环境二、漏洞验证三、准备payload四、执行payload五、变形payload 一、搭建环境 cd vulhub/spring/CVE-2016-4977/ docker-compose up -d 二、漏洞验证 访问 http://192.168.10.171:8080/oauth/authorize?response_type${233*233}&client_idacme&s…...

Python之并发编程介绍

一、并发编程介绍 1.1、串行、并行与并发的区别 串行(serial)&#xff1a;一个CPU上&#xff0c;按顺序完成多个任务并行(parallelism)&#xff1a;指的是任务数小于等于cpu核数&#xff0c;即任务真的是一起执行的并发(concurrency)&#xff1a;一个CPU采用时间片管理方式&am…...

GO语言网络编程(并发编程)并发介绍,Goroutine

GO语言网络编程&#xff08;并发编程&#xff09;并发介绍&#xff0c;Goroutine 1、并发介绍 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。 B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更…...

英语连词总结

前言 总结一些常用的英语连词&#xff0c;以下用法只是我希望我自己这么用。分类我可能分的不好&#xff0c;慢慢积累&#xff0c;慢慢改进。 1&#xff09;表递进: firstly、secondly、thirdly、finally、af first、at the beginning、in the end、to begin with&#xff0…...

LeetCode 92. Reverse Linked List II【链表,头插法】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

ubuntu22.04 安装docker 和docker-compose

首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

【深度学习新浪潮】什么是credit assignment problem?

Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...