基于SSM实现个人随笔分享平台:创作心灵,分享自我
项目简介
本文将对项目的功能及部分细节的实现进行介绍。个人随笔分享平台基于 SpringBoot + SpringMVC + MyBatis 实现。实现了用户的注册与登录、随笔主页、文章查询、个人随笔展示、个人随笔查询、写随笔、草稿箱、随笔修改、随笔删除、访问量及阅读量统计等功能。该项目登录模块对明文密码进行了加盐处理,并且将session使用Redis进行了持久化存储,为分布式的支持奠定了基础,同时,使用了统一功能处理与拦截器。
文章目录
- 项目简介
- 1 功能概览
- 2 主要功能展示
- 3 系统部分实现细节
- 3.1 草稿箱实现
- 3.2 分页查询
- 3.3 查询功能
- 3.4 随笔的修改与发布
- 3.5 随笔与草稿的删除
- 3.5 对随笔摘要的 markdown 标签处理
- 3.6 基于 MD5 的加盐算法处理明文密码
- 3.7 使用 Redis 持久化 Session
- 4 开发过程遇到的问题
- 4.1 Redis服务的远程连接问题与session持久化失败
- 4.2 查询功能url获取参数中文乱码问题
- 4.3 草稿箱内容出现在个人随笔页
- 写在最后
1 功能概览
以下是对个人随笔分享平台功能的表格整理:
功能 | 描述 |
---|---|
登录功能 | 用户可以使用用户名和密码登录到平台。 |
注册功能 | 用户可以注册新的账户来访问平台。 |
个人信息展示 | 可以查看个人信息: 头像、昵称、访问量、文章数等。 |
个人随笔列表展示 | 用户可以查看自己发布的随笔列表。 |
查询个人随笔 | 用户可以根据关键字查询自己发布的随笔。 |
随笔主页分页查询功能 | 用户可以在随笔主页浏览所有用户的随笔,系统将用户的文章进行分页展示 |
查询随笔 | 用户可以根据关键字查询其他用户发布的随笔。 |
发布随笔功能 | 用户可以发布新的随笔。 |
随笔草稿箱 | 用户可以保存随笔的草稿,并在需要时进行编辑和发布。 |
随笔或草稿编辑功能 | 用户可以编辑已发布的随笔或草稿。 |
随笔详情展示 | 用户可以查看随笔的详细内容和相关信息。 |
随笔或草稿删除功能 | 用户可以删除已发布的随笔或草稿。 |
访问量与阅读量统计 | 平台可以统计每篇随笔的访问量和阅读量,并显示给用户。 |
2 主要功能展示
随笔主页
无论用户是否登录,都可以使用随笔主页。在该界面中,您可以查阅所有作者发布的内容。
分页展示
在随笔主页,内容采用分页展示,默认每页展示的文章条数最大为5条,点击下一页等按钮可以进行页面内容切换。
“搜你想搜”
在随笔主页,你可以使用搜索框搜索你想要查询的内容,系统会根据你给定的字段进行模糊匹配,检索系统中符合条件的文章,并同样以分页展示的形式呈现给你。
登录与注册模块
与大多数为用户提供服务的系统一样,该平台同样包含了注册与登录功能。未注册的用户通过登记相关信息可以成为平台的用户,平台的用户可以使用用户名和密码进入自己的随笔主页,同时也拥有了体验该平台完整功能的权利。需要注意的是,该平台暂未提供手机登录等“生产”级别的业务,如有需要,可自行扩展–比如可以使用某某云之类提供的接口扩展短信验证码等模块。
个人随笔列表展示
在该页面中,将展示您发布的所有随笔(草稿除外),您可以在该页面查看自己的信息(包括自己的头像、文章数量及总访问量),搜索自己的内容,或者选择查看、编辑、删除自己的随笔。
搜索TA的内容
在用户随笔主页中,可以在搜索框中输入想要搜索的内容,系统将模糊匹配您发布的文章是否有包含该字段的文章,如果有,将以列表的方式呈现给你。
发布随笔与编辑随笔
你可以选择对应随笔进行编辑,或者点击写随笔按钮来新建一篇随笔。随笔的编辑与发布支持MarkDown语法。
草稿箱模块
由于并不是每个人都有连续的时间,能够将一篇随笔写完发布后再去处理其他事情。因此,本系统提供了草稿箱功能,您可以将你编辑的内容先保存到草稿箱,等到您需要的时候进行发布、编辑或者删除。
随笔详情展示
在随笔主页或者“我的随笔”页面,您可以通过点击查看全文按钮的方式查看随笔的全文内容。不仅如此,您还可以查阅本文的部分作者信息、文章的阅读量与发布时间修改时间等信息。
3 系统部分实现细节
3.1 草稿箱实现
本系统对于草稿箱的实现,实际是对文章的状态进行区分。在articleinfo文章表中,我们预留出了一个state字段,用于表示文章的状态:
- state = 1 : 正常的发布文章;
- state = 0 : 处于草稿箱的文章;
在进行个人随笔主页以及草稿箱页面展示文章信息,只需要对应展示该登录用户对应文章状态的文章即可。对于前端页面,对“发布文章”与“保存草稿”按钮的监听进行了区分:
- 点击发布文章按钮: 请求包含文章的标题、文章的内容和 state = 1;
- 点击保存草稿按钮: 请求同上,区别是 state = 0;
基于此构造 ajax 请求后端进行 insert 操作。
后端实现的核心代码:
/*** 发布文章 state = 1 与保存草稿箱 state = 0* 如果是保存草稿箱, 则请求的文章对象中 state = 0* 更新了传入 createtime 和 updatetime 解决数据库不兼容问题*/@RequestMapping("/add")public AjaxResult add(HttpServletRequest request, Articleinfo articleinfo) {// 非空校验if (articleinfo == null || !StringUtils.hasLength(articleinfo.getTitle()) ||!StringUtils.hasLength(articleinfo.getContent())) {return AjaxResult.fail(-1, "非法参数");}// 发布文章操作// 得到当前用户的 uidUserinfo userinfo = UserSessionUtils.getSessUser(request);if (userinfo == null || userinfo.getId() <= 0) {// 无效的登录用户return AjaxResult.fail(-2, "无效的登录用户");}articleinfo.setUid(userinfo.getId()); // 设置作者 id// 设置创建时间和更新时间, 解决数据库没有默认约束的情况articleinfo.setCreatetime(LocalDateTime.now());articleinfo.setUpdatetime(LocalDateTime.now());// 添加数据库并返回return AjaxResult.success(articleService.add(articleinfo));}
3.2 分页查询
分页查询的实现涉及几个重要的因素:
- pIndex: 当前页码;
- pSize: 每页最多显示的文章条数。
而分页功能在 SQL 中的实现基于如下的 SQL:
select xxx from articleinfo
where xxx
limit pIndex offset offsetSize;
经过推导,我们可以得出如下映射关系:
offsetSize = (pIndex - 1) / pSize
对于 where 子句的内容,我们使用 Mybatis 的动态 SQL 进行处理。
而总页数需要通过对 文章总数 / 每页最大文章数 的结果进行向上取整,比如: ceil()进行处理。
同时,在前端页面,该平台使用的是拼接跳转的方式,点击下一页就将pIndex ++(需要对范围进行判断,防止越界),而每页结果在构造 ajax 请求发送给后端请求响应哦时候,就从 location.search 中获取请求参数中的 pindex。
后端核心代码如下:
/*** 分页查询* @param pIndex 当前页码* @param pSize 每页最多显示的文章条数* @param key 检索的 title* @return 返回的 data 中包含一个 map, 含有当前页的文章列表与文章总数量*/@RequestMapping("/listbypage")public AjaxResult getListByPage(@RequestParam("pindex") Integer pIndex,@RequestParam("psize") Integer pSize,@RequestParam("key") String key) {// 参数校正if (pIndex == null || pIndex < 1) {pIndex = 1;}if (pSize == null || pSize <= 1) {pSize = 3;}// 分页查询int offSize = (pIndex - 1) * pSize;List<Articleinfo> articleInfoList = articleService.getListByPage(pSize, offSize, key);// 对摘要进行处理for (Articleinfo articleinfo : articleInfoList) {articleinfo.setContent(MarkdownUtils.removeMarkdownTags(articleinfo.getContent(), 256));}// 获取文章总数int totalArticleCount = articleService.getTotalArticleCount(key);HashMap<String, Object> map = new HashMap<>();map.put("articleInfoList", articleInfoList);map.put("totalArticleCount", totalArticleCount);return AjaxResult.success(map);}
}
3.3 查询功能
查询功能主要通过 Mybaties 的动态 SQL 实现,在 *mapper.xml 的相应 select 语句中使用了 if 标签。如果前端构造请求的时候没有 key (即搜索框中没有内容),则默认返回的是当前页应该展示的文章列表或者是当前登录用户的所有文章列表。注意,这里所说的列表指的是正常发布的文章,对于草稿箱的内容,需要在草稿箱中查看。
后端核心代码如下
/*** 加载用户的文章列表信息* key: 搜索 title* state: 0 草稿, 1 文章*/@RequestMapping("/mylist")public AjaxResult getMyList(HttpServletRequest request, Integer state, String key) {Userinfo userinfo = UserSessionUtils.getSessUser(request);if (userinfo == null) {return AjaxResult.fail(-1, "非法请求");}List<Articleinfo> list = articleService.getMyList(userinfo.getId(), state, key);// 将 list 中每个文章信息对象的正文进行处理, 去除 markdown 标签并最多显示 256 个字符for (Articleinfo articleinfo : list) {String content = articleinfo.getContent();content = MarkdownUtils.removeMarkdownTags(content,ApplicationVariable.THE_MAXIMUM_NUMBER_OF_CHARACTERS_IN_THE_DIGEST);articleinfo.setContent(content);}return AjaxResult.success(list);}
3.4 随笔的修改与发布
随笔的修改与发布与草稿箱的实现模块类似,修改会先将文章id作为请求,请求后端返回当前文章内容,往后点击发布文章进行 update 操作。而发布文章则是 insert 操作。与草稿箱不同的是,这里的修改与发布所更新的 state 字段都是 1。
后端实现核心代码如下
/*** 修改文章* 只有当前登录用户是作者的情况下才能进行修改(验权)*/@RequestMapping("/update")public AjaxResult update(HttpServletRequest request, Articleinfo articleinfo) {// 非空检验if (articleinfo == null || !StringUtils.hasLength(articleinfo.getTitle()) ||!StringUtils.hasLength(articleinfo.getContent()) ||articleinfo.getId() == null ||articleinfo.getId() <= 0) {return AjaxResult.fail(-1, "非法参数");}// 得到当前登录用户的 idUserinfo userinfo = UserSessionUtils.getSessUser(request);if (userinfo == null || userinfo.getId() == null || userinfo.getId() <= 0) {return AjaxResult.fail(-2, "无效用户");}// 设置文章对象的 uid 为当前用户的 id, 便于 mapper 验证是否为当前登录用户articleinfo.setUid(userinfo.getId());articleinfo.setUpdatetime(LocalDateTime.now());return AjaxResult.success(articleService.update(articleinfo));}
3.5 随笔与草稿的删除
对于随笔与草稿的删除都是通过传给后端当前文章或草稿的 id 请求删除操作。同时,后端需要对当前登录用户进行验权,即判断当前登录用户是否为文章的作者。以解决当前登录用户注销后忘记关闭页面而另一个人登录后,由于session存在导致的误删误改的情况。
后端实现的核心代码如下
/*** 删除文章* 只有当前登录的用户是文章的作者才能删除(验权)*/@RequestMapping("/del")public AjaxResult del(HttpServletRequest request, @RequestParam("aid") Integer id) {// 参数检验if (id == null || id <= 0) {return AjaxResult.fail(-1, "非法参数");}// 进行删除// 只有当前登录的用户同时是文章的作者的情况下才能删除Userinfo user = UserSessionUtils.getSessUser(request);if (user == null) {return AjaxResult.fail(-2, "用户未登录");}int delCount = articleService.del(id, user.getId());return AjaxResult.success(delCount);}
3.5 对随笔摘要的 markdown 标签处理
由于数据库存储的文章内容均为 markdown 字符,因此,需要对 markdown 标签进行处理。使得在随笔的列表展示中,摘要不显示形如 # 这样的符号。
笔者实现的方式是通过正则表达式匹配,从而进行处理,具体实现代码如下:
import java.util.regex.Pattern;/*** @author 兴趣使然黄小黄* @version 1.0* @date 2023/7/23 23:18* 用于处理文章列表的文章摘要信息* 1. 对摘要去除 markdown 标签处理* 2. 摘要只截取文章正文前 n 个字符*/
public class MarkdownUtils {// 匹配Markdown标签的正则表达式private static String regex = "\\*\\*|__|\\*|_|~~|`|\\[\\]|\\(|\\)|\\{|\\}|\\[|\\]|#|\\+|-|\\.|!";/*** 对摘要进行去 markdown 标签处理*/public static String removeMarkdownTags(String markdown, int n) {// 先对 markdown 字符串进行截取markdown = preprocessingString(markdown, n);// 使用空字符串替换Markdown标签并返回return Pattern.compile(regex).matcher(markdown).replaceAll("");}/*** 截取正文的前 n 个字符作为摘要*/private static String preprocessingString(String s, int n) {if (s == null || s == "" || n <= 0) {return "";}String result = "";if (n >= s.length()) {result = s.substring(0, s.length());} else {result = s.substring(0, n);}return result;}
}
3.6 基于 MD5 的加盐算法处理明文密码
若数据库存储的密码是形如: 11111 这样的明文形式,则是非常不安全的,若数据库泄露,用户的密码很容易被获取。因此,需要对密码进行处理。
单一的采用 md5 的方式进行加密也是不安全的,因为 md5 对固定字符的加密结果是相同的,比如对于111加密,加密结果是EF2类似这样,通过彩虹表就可以逆向查出来加密前的密码。
笔者采用的方式是通过“加盐”的方式进行处理,即将未加密的密码拼接一个随机值(盐值),然后再进行md5加密,这样就解决了固定密码加密结果相同的的问题。而在存储到数据库前,也需要将盐值一并存储,笔者采用的方式是使用$符号进行分割:
盐值\$加密的密码
。进行比对的时候,只需要从数据库中取出盐值,进行加密后与取出加密的密码进行比较。 具体实现如下:
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import org.springframework.util.StringUtils;/*** @author 兴趣使然黄小黄* @version 1.0* @date 2023/7/24 17:01* 密码明文基于 MD5 随机盐值加密处理*/
public class PasswordUtils {/*** 加密(加盐)* @param password 需要加密的密码* @return 盐值$加密的密码*/public static String encrypt(String password) {// 随机盐值String salt = IdUtil.simpleUUID();// 密码 md5(随机盐值 + 密码)String encryptPassword = SecureUtil.md5(salt + password);return salt + "$" + encryptPassword;}/*** 解密* @param password 要验证的密码(未加密)* @param securePassword 数据库中加了盐值的密码* @return 返回密码是否正确*/public static boolean decrypt(String password, String securePassword) {boolean result = false;if (StringUtils.hasLength(password) && StringUtils.hasLength(securePassword)) {if (securePassword.length() == 65 && securePassword.contains("$")) {String[] securePasswordArr = securePassword.split("\\$");// 盐值String salt = securePasswordArr[0];// 加密后的密码String encryptPassword = securePasswordArr[1];// 使用同样的 md5 与同样的盐值对 password 进行加密password = SecureUtil.md5(salt + password);// 比较是否相同return encryptPassword.equals(password);}}return result;}
}
3.7 使用 Redis 持久化 Session
首先,需要在 SpringBoot 项目中引入依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency>
在配置文件中添加上 redis 相关的配置:
spring:redis:host: xxx.xxx.xxx.xxxport: 6379session:store-type: redistimeout: 1800redis:flush-mode: on_savenamespace: spring:session
4 开发过程遇到的问题
4.1 Redis服务的远程连接问题与session持久化失败
笔者在开发过程中,使用 Xshell 连接云服务器的 redis 总是出现问题,在处理过程中发现服务器被劫持,最终只得重装系统。当然,也安装了一些工具来防止暴力破解。回到正题,启动了 redis 服务为什么关闭远程连接会话窗口后不久,服务器的 redis 进程就关闭了呢? 后面笔者采用 nohup 的方式启动服务,问题得到解决(需要在配置文件中先把 redis 配置后台运行):
正当我兴致慢慢去启动项目的时候,项目又出现了问题,大概就是在持久化 session 的过程中抛了异常,经查: 当对象需要进行网络传输的时候,需要实现序列化接口,而在项目中,当用户登录成功时,其 session 就是存储了 userinfo 对象。当实现了序列化接口后,问题得到解决。
4.2 查询功能url获取参数中文乱码问题
在实现随笔主页的查询过程中,笔者的思路是将查询的 key 通过点击按钮的方式构造到 url 上,这样每一页都可以通过自己写的方法获取到 search 上的指定参数。在功能完成时,测试英文搜索没问题,而当输入中文检索的时候,则显示不了预期结果。通过调试,发现后端的 sql 竟然传入了一段乱码的 key!!! 将前端对应的代码进行修改,使用decodeURIComponent()
进行解码,问题得到解决:
// 获取当前 url 的参数function getUrlValue(key) {var params = location.search; // '?xxx&xxx'if (params.length > 1) {// 截取params = params.substring(1);var paramArr = params.split("&");// 获取对应的 keyValuefor(var i = 0; i < paramArr.length; i++) {var kv = paramArr[i].split("=");if(kv[0]==key) {return decodeURIComponent(kv[1]); // 处理中文乱码}}}return "";}
4.3 草稿箱内容出现在个人随笔页
这个问题的出现实属不该,是笔者在迭代功能的过程中忘记给 sql 添加 where state = xxx 的子句。导致在随笔主页和个人随笔主页以及草稿箱均显示了草稿和已发布的文章。在生产环境中,很多企业都有自己的工具,对于忘记添加 where 语句的 sql 是会报错的!还好,笔者的该模块还仅仅是查询,如果是 insert 或者 update 就会出现数据污染问题了。
写在最后
本文被 JavaEE编程之路 收录点击订阅专栏 , 持续更新中。
以上便是本文的全部内容啦!创作不易,如果你有任何问题,欢迎私信,感谢您的支持!
相关文章:

基于SSM实现个人随笔分享平台:创作心灵,分享自我
项目简介 本文将对项目的功能及部分细节的实现进行介绍。个人随笔分享平台基于 SpringBoot SpringMVC MyBatis 实现。实现了用户的注册与登录、随笔主页、文章查询、个人随笔展示、个人随笔查询、写随笔、草稿箱、随笔修改、随笔删除、访问量及阅读量统计等功能。该项目登录模…...

从零开始学Docker(二):启动第一个Docker容器
宿主机环境:RockyLinux 9 这个章节不小心搞成命令学习了,后面在整理成原理吧 Docker生命周期 拉取并启动Nginx容器 # 查找镜像 例如:nginx [root192 ~]# docker search nginx 我们可以看到,第一个时官方认证构建的nginx # 拉…...
unity 鼠标事件
Input.GetMouseButtonDown(0)点击屏幕Input.mousePosition鼠标的坐标Input.GetKeyDown(KeyCode.Space)点击空格 1.2D游戏中鼠标触发事件 using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEditor; using Un…...
【ChatGPT】相关解读
ChatGPT 背后的“功臣”——RLHF 技术详解 Meta 发布开源可商用模型 Llama 2,实际体验效果如何? Llama 2线上试用地址:replicate.com/a16z-infr…...

【数据中台】DataX源码进行二开插件
参考官方 使用的离线数据同步工具/平台,实现不同数据库等各种异构数据源之间高效的数据同步功能 工具部署 https://github.com/alibaba/DataX/blob/master/userGuid.md 拉取下来的代码,pom.xml里面注释 <!--<module>tsdbreader</module&g…...

【数据结构与算法】基数排序
基数排序 基数排序(Radix Sort)属于“分配式排序”,又称“桶子法”或 bin sort,顾名思义,它是通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的作用。基数排序法是属于稳定性…...
Java基础一(队列和堆栈)
//示例 //添加新的元素 stack.push(Element e)queue.add(Element e) //满报IllegalStateException异常 queue.offer(Element e) //满成功true,否则false //删除 stack.pop()queue.remove() //移除头部元素,空报异常 queue.poll() //移除头部元素&…...

使用ansible playbook编写lnmp架构
使用ansible playbook编写lnmp架构 - name: nginx playgather_facts: falsehosts: lnmpremote_user: roottasks: - name: stop firewalldservice: namefirewalld statestopped- name: syslinuxcommand: /usr/sbin/setenforce 0ignore_errors: true- name: nginx.repocopy: src/…...
使用 TorchText 进行语言翻译
使用 TorchText 进行语言翻译 本教程说明如何使用torchtext的几个便捷类来预处理包含英语和德语句子的著名数据集的数据,并使用它来训练序列到序列模型,并注意将德语句子翻译成英语 。 它基于 PyTorch 社区成员 Ben Trevett 的本教程,并由 …...
SpringBoot整合SSMP小demo
创建项目 spring web,mybatis,mysql勾选 加入mp和druid,依赖见SpringBoot基础认识_阳光明媚UPUP的博客-CSDN博客 yml数据源 server:port: 81 spring:datasource:druid: #整合方式配置driver-class-name: com.mysql.jdbc.Driverurl: jdbc:m…...

51单片机--红外遥控
文章目录 红外遥控的介绍硬件电路NEC编码外部中断红外遥控实例代码 红外遥控的介绍 红外遥控是一种无线、非接触控制技术,通过使用红外线来传送控制信号。它具有抗干扰能力强、信息传输可靠、功耗低、成本低、易实现等显著优点,因此被广泛应用于各种电子…...

【图像分类】CNN+Transformer结合系列.2
介绍几篇利用CNNTransformer实现图像分类的论文:CMT(CVPR2022),MaxViT(ECCV2022),MaxViT(ECCV2022),MPViT(CVPR2022)。主要是说明Transformer的局限性&#x…...

用于毫米波天线的新型无卤素超低传输损耗多层电路板R-5410
3月3日消息,松下公司宣布,其工业解决方案公司已经实现了R-5410的商业化,这是一种无卤素、超低传输损耗的多层电路板(MLCB)材料,适用于毫米波天线。将于2021年3月开始量产。 毫米波雷达是汽车、通信等行业的…...
java数据算法-汉诺塔
1、有三根相邻的柱子,标号为A,B,C。 2、A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘。 3、现在把所有盘子一个一个移动到柱子C上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方。 题解步骤 1、当n1时; 将1号从A移动到C即…...
[QT编程系列-35]:数据存储 - JSON格式配置数据的存储与通知
目录 1. QJsonObject 2 QJsonDocument 3 JSON本文格式 4. JSON示例 5. JASON配置文件示例 1. QJsonObject QJsonObject 是Qt的类之一,用于表示 JSON 对象。 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式࿰…...

【Spring】Spring 中事务的实现
目录 1.编程式事务(手动编写代码)2.声明式事务(利用注解)2.1 Transactional作用范围2.2 Transactional参数说明2.3 Transactional工作原理 3.Spring 中设置事务隔离级别3.1 事务四大特性ACID3.2 事务的隔离级别3.2 Spring中设置事…...

Linux 学习记录60(ARM篇)
Linux 学习记录60(ARM篇) 本文目录 Linux 学习记录60(ARM篇)一、SPI总线1. 概念2. 硬件连接 二、SPI总线协议三、SPI总线通信模式四、对比IIC总线和SPI总线1. 相同点2. 不同点 思维导图 一、SPI总线 1. 概念 1、SPI总结是Motorola首先提出的全双工三线/四线同步串行总线 2、采…...

尚硅谷大数据项目《在线教育之采集系统》笔记002
视频地址:尚硅谷大数据项目《在线教育之采集系统》_哔哩哔哩_bilibili 目录 P032 P033 P033 P034 P035 P036 P032 P033 # 1、定义组件,为各组件命名 a1.sources r1 a1.channels c1 a1.sinks - k1# 2、配置sources,描述source a1.sour…...

校园跑腿小程序功能分享
提起校园跑腿小程序大家都不陌生,尤其是对上大学的伙伴们来说,更是熟悉得不能再熟悉了,和我们的生活息息相关,密不可分。 对于现在的年轻人来说,网购是非常简单和方便的一种购物方式,随之快递也会越来越多。在我们国家…...

PHP8的变量-PHP8知识详解
昨天我们讲解了PHP8的常量,今天讲解PHP8的变量。常量有定义常量和预定义常量,变量呢?那就没有定义变量了,那叫给变量赋值,但是还是有预定义变量的。下面就给大家讲解什么是变量、变量赋值及使用及预定义变量。 一、什么…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...

Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...

麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...

PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...