Spring Boot + Vue3前后端分离实战wiki知识库系统<十三>--单点登录开发二
接着Spring Boot + Vue3前后端分离实战wiki知识库系统<十二>--用户管理&单点登录开发一继续往下。
登录功能开发:
接下来则来开发用户的登录功能,先准备后端的接口。
后端增加登录接口:
1、UserLoginReq:
先来准备用户登录的请求实体:

package com.cexo.wiki.req;import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;public class UserLoginReq {@NotEmpty(message = "【用户名】不能为空")private String loginName;@NotEmpty(message = "【密码】不能为空")// @Length(min = 6, max = 20, message = "【密码】6~20位")@Pattern(regexp = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,32}$", message = "【密码】规则不正确")private String password;public String getLoginName() {return loginName;}public void setLoginName(String loginName) {this.loginName = loginName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {StringBuilder sb = new StringBuilder();sb.append(getClass().getSimpleName());sb.append(" [");sb.append("Hash = ").append(hashCode());sb.append(", loginName=").append(loginName);sb.append(", password=").append(password);sb.append("]");return sb.toString();}
}
对于用户登录,只需要用户名和密码既可,其中有一个小细节需要说明一下,就是对于之前后台实现的用户管理保存的实体其密码是做了非常详细的规则提示的:

而这里对于用户登录的密码规则校验,则不能提示这么详情了,因为提示这么详情容易被人根据规则来进行密码破解,所以这里就提示了一个比较模糊的校验提示:

2、UserLoginResp:
再来准备登录的response实体:

package com.cexo.wiki.resp;public class UserLoginResp {private Long id;private String loginName;private String name;private String token;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getLoginName() {return loginName;}public void setLoginName(String loginName) {this.loginName = loginName;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getToken() {return token;}public void setToken(String token) {this.token = token;}@Overridepublic String toString() {return "UserLoginResp{" +"id=" + id +", loginName='" + loginName + '\'' +", name='" + name + '\'' +", token='" + token + '\'' +'}';}
}
3、Controller增加登录接口:

4、Service实现登录逻辑:

那接下来咱们是直接来校验用户名和密码的正确性么?其实应该先校验用户名是否存在,如果不存在,则密码都没密要校验了,所以先来查一下:

而处理异常可以采用在之前用户管理保存时的方式,抛出异常:

这里咱们先定义一个用户名不存在的异常码:

这里提示语貌似写错了吧。。其实这里是故意写一个模糊的提示的,因为给用户提示得越详细,越容易被攻击,所以这种风险意识在做项目时是很重要的。好,接下来就可以抛出这个异常了:

接下来再来判断密码的正确性:

最后,还有一个细节,就是目前这两块给用户提示了一个一模一样的提示:

很明显这对于后端排错不太好,所以有必要针对这俩加点日志:

前端增加登录模态框:
效果:
先来看一下登录的效果:

实现:
1、增加登录入口:
接下来则先在前端页面中增加一个用户登录的入口,这里很明显是应该在头部区域加,也就是:


此时的效果:

另外这里既然改了头部区域,左上角这块的logo也顺带改一下,目前这里是一个色块,没有什么实际意义,这里改一下:

控制它的css在这:

这里将这个logo的css先去掉,在头部组件里来定义就成:


然后修改为:

此时效果:

2、 点击弹出模态登录窗口:
先来给登录这个a标签增加点击事件:

而模态框的处理在之前的页面中已经多次用到了,所以这里就不过多解释了,直接准备一个登录的模态框:

其中提交的时候得请求接口,需要耗时,交互上肯定需要有loading等待效果,所以先提前把响应式的变量定义好:

此时运行看一下:

3、登录点击事件添加:
接下来给模拟框增加一个提交事件:


这里为了使用方便,给表单输一个默认值,如下:


此时运行:

4、发起登录请求:
最后发起登录请求,这块的网络请求代码也没啥好说的,直接copy原来的逻辑改下接口就可以了,如下:

其中需要导两个组件:

好,此时运行看一下效果:

成功登录。
登录成功处理并集成vuex:
目前我们已经登录成功,但是登录成功之后,其实就给了一个提示,没有做登录成功之后的逻辑处理,接下来咱们则来完善它。
后端保存用户信息:
1、集成Redis:
由于需要将用户登录成功的信息以token形式存到Redis当中,所以先在工程中集成它:

而关于Redis的环境的配置这里就不说明了,当时在前后端接口设计与配置中心系统<二十六>-------后端-DAU超千万的移动端接口设计实现2【整合与优化Swagger2文档Api、登录功能实现与Response设计、基于Redis实现高速的用户信息缓存、基于注解拦截器实现接口访问控制与登录态处理】这篇已经详细学习过了,这块网上资料也比较多,我本机装好之后,先使用此命令启动一下它:
redis-server

然后再用可视化的图形工具RDM连接看一下:


目前里面没有存任何信息,所以数量都是0,然后再配置一下redis的数据源,类似于mysql一样:

2、登录时生成token并存入Redis中:
此时我们就需要修改一下登录的逻辑时,在登录成功之后,需要生成一个token,这里就用之前使用的雪花算法来生成,如下:

此时则需要将token存入到Redis当中,此时需要这么来做:

其中有个细节需要注意,我们目前存放到Redis中是将实体转换成了一个json串了:

如果想直接保存实体,注意需要让实体实现序列化的接口,不然保存的时候会报如下异常:

另外此token信息也需要返回给前端,因为之后前端也需要将此token信息在请求时携带上进行身份的识别,所以:

其中为了调试方便,将这块加个日志输出:


3、测试:
接下来咱们来登录测试一下是否写入成功了:

显示是成功了,到RDM可视化工具中刷新查看一下:

貌似是有了,不过看了是一串乱码,为了验证这个token写入到Redis是没有问题的,下面在TestController中增加测试方法,如下:

然后咱们就可以这样来测试了:

咱们运行一下:


那对于这里的登录时,生成这么一个token:

此时借助这个测试能查出存在redis中的用户信息么?

木问题。
前端显示登录用户:
接下来在用户登录成功之后,则需要显示出用户的昵称,修改页面:

其中user是一个响应式的变量,定义一下:

另外由于数据库中用户test的密码是test123,所以这里改一下:

然后在登录成功之后则给它进行赋值,如下:

接下来在登录入口处增加显示与隐藏的控制:

接下来运行看一下:

集成vuex:
说明:
接下来说明一个问题,就是目前我们登录后信息是在头部组件中来保存的:

那如果我想在底部组件里也能拿到用户的登录信息该怎么办呢?

很明显是拿不到的,因为定义的头部的响应式变量不能在其它页面使用,此时就得声明一个全局的变量来进行存储,这里就需要使用到vuex了,度娘先了了解一下它:

哦,就是来解决多组件数据通信的问题的,刚好符合我们目前的使用场景,而使用它的位置就在这块:

接下来咱们则来使用一下它。
实现:
1、定义一个全局的变量:

2、定义操作变量的函数:
光定义变量还不行,得定义操作它的行为,这里则会涉及到如下两处:

其中mutations是同步函数,而actions是支持异步的,这里我们在mutations中来进行定义:

3、返回store:
最后需要将这个store返回出去,以便可以在其它界面进行使用:

4、使用store保存用户信息:
接下来我们回到头部组件中,在登录成功之后使用store来保存一下用户信息,写法如下:


5、底部组件中获取用户信息:
接下来咱们就可以使用这个全局的数据了:

其中computed的含义是:如果一个响应式变量是要根据某个变量的变化而计算得来,就可以使用computed。
其中这里有个代码可以简化一下,就是它:


6、运行:

所以vuex其实就是全局响应式的变量,单纯的组件里面的响应式变量是做不到这种效果的。
最后更改一个文案:

而它应该受登录状态的控制,所以加一个显隐逻辑:

再来运行一下:

使用sessionStorage解决刷新数据丢失的问题:
说明:
接下来再来看一个问题:

刷新之后,登录态就没有了,这也反应出vuex有问题,浏览器一刷新就没有了,而要解决这个问题就需要使用sessionStorage了,度娘又来了解一下它:

其中标红的是一些关于它值得关注的,它会随着浏览器页面的存在而存在,如果关闭页面了则数据就不存在了,在搜它的概念时,还搜到了一个在前端经常会提及的话题cookie 、sessionstorage 、localstorage三者的区别_夜晚收集者的博客-CSDN博客:

关于这块自己网上了解一下既可。
实现:
1、拷一个工具类:
为了使用sessionStorage,拷一个工具类进来:

SessionStorage = {get: function (key) {var v = sessionStorage.getItem(key);if (v && typeof (v) !== "undefined" && v !== "undefined") {return JSON.parse(v);}},set: function (key, data) {sessionStorage.setItem(key, JSON.stringify(data));},remove: function (key) {sessionStorage.removeItem(key);},clearAll: function () {sessionStorage.clear();}
};
为啥要封装一下呢,因为默认的sessionStorage只支持存string,这里扩展保存一个object类型,其实也就是最终会将object转换成Json字符串再保存:

2、引入工具类:

3、使用sessionStorage:
接下来我们在保存user信息时,除了使用vuex保存在全局响应式的变量当中之外,还需要保存到sessionStorage,所以好的做法就是在vuex这个文件中进行处理,先来引入工具类,引入的方法还记得不,其实在之前md5工具方法时已经使用过了,回忆一下:

所以定义一下:

其中let后面的名称取的是js中定义的它:

然后在获取用户信息时加上从sessionStorage来取的逻辑:

另外在设置user信息时,则需要将其存到SessionStorage当中:

其中有个代码可以优化一下:

都是常量,可以将其提取一下,提高维护性:

接下来运行看一下:

其中可以看到footer下的用户登录信息在浏览器刷新之后是能够被保留的,而关闭浏览器当前窗口就清空了,符合SessionStorage的定义场景,只是右上角的header用户信息在浏览器刷新时没有保留住,是因为header页面的user变量没有改成computed,如footer页面报写的这样:

所以咱们将header的代码改成这样:

将其改为:

这样就会去监听store中user的变化,不过这样改之后有个报错:

这里就没必要了,直接将user保存到store中就可以了:

接下来运行看一下效果:

成功修复浏览器刷新用户信息被清空的问题。
增加退出登录功能:
1、UserController.logout():
对于退出登录的接口其实只需要传一个token参数既可,所以定义接口如下:

其实也就是根据token将redis对应的信息给删除既可。
2、前端增加退出按钮:

而通常退出操作是需要给用户一个确认提示的,所以在它外层再包装一层:

3、调用退出登录接口:
接下来咱们就可以处理退出登录的点击事件,如下:

4、运行:
接下来运行看一下效果,发现后台报错了:

这是因为登出接口是一个get请求,而我们在后台声明的是:

修改一下:

再运行:

这里貌似界面上看着有点别扭,就是退出登录一般是在用户登录信息的右侧的,现在在左侧:

更改一下顺序:

因为login-menu的样式是:

最上面的元素就在最右侧边了,最后的样子:

增加登录校验:
有了用户登录之后, 对于页面中的功能则需要进行登录的校验了,对于管理类的入口都是需要登录之后才能预览,而对于文章查看是不需要的,所以,接下来进行登录校验的处理。
后端增加拦截器,校验token有效性:
1、 新建一个拦截器LoginInterceptor:
对于拦截器在之前已经有使用过了:

同样的,对于这个登录拦截器写法也差不多,关于这块的代码就不过多解释了,比较好理解:
package com.jiawa.wiki.interceptor;import com.alibaba.fastjson.JSON;
import com.jiawa.wiki.resp.UserLoginResp;
import com.jiawa.wiki.util.LoginUserContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** 拦截器:Spring框架特有的,常用于登录校验,权限校验,请求日志打印*/
@Component
public class LoginInterceptor implements HandlerInterceptor {private static final Logger LOG = LoggerFactory.getLogger(LoginInterceptor.class);@Resourceprivate RedisTemplate redisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 打印请求信息LOG.info("------------- LoginInterceptor 开始 -------------");long startTime = System.currentTimeMillis();request.setAttribute("requestStartTime", startTime);// OPTIONS请求不做校验,// 前后端分离的架构, 前端会发一个OPTIONS请求先做预检, 对预检请求不做校验if (request.getMethod().toUpperCase().equals("OPTIONS")) {return true;}String path = request.getRequestURL().toString();LOG.info("接口登录拦截:,path:{}", path);//获取header的token参数String token = request.getHeader("token");LOG.info("登录校验开始,token:{}", token);if (token == null || token.isEmpty()) {LOG.info("token为空,请求被拦截");response.setStatus(HttpStatus.UNAUTHORIZED.value());return false;}Object object = redisTemplate.opsForValue().get(token);if (object == null) {LOG.warn("token无效,请求被拦截");response.setStatus(HttpStatus.UNAUTHORIZED.value());return false;} else {LOG.info("已登录:{}", object);return true;}}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {long startTime = (Long) request.getAttribute("requestStartTime");LOG.info("------------- LoginInterceptor 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// LOG.info("LogInterceptor 结束");}
}
逻辑简单来说的话就是先来判断token是否为空,如果不为空,则再到redis中来获取一下。其中校验不通过时,返回一个401:

2、配置拦截器:
接下来要想拦截器生效,则需要到这来配置一下:

然后接下来得进行一下配置,因为有些接口是需要进行登录拦截的,如下:

package com.cexo.wiki.config;import com.cexo.wiki.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import javax.annotation.Resource;@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {// @Resource
// LogInterceptor logInterceptor;//配置拦截器@ResourceLoginInterceptor loginInterceptor;public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(logInterceptor)
// .addPathPatterns("/**");registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/test/**","/redis/**","/user/login","/category/all","/ebook/list","/doc/all/**","/doc/vote/**","/doc/find-content/**","/ebook-snapshot/**");}
}
其中这里用到了“**”:

则表示是任意值,好,加了拦截器之后咱们再来访问一下页面:

首页查看电子书都正常,但是点击用户管理时,页面的数据加载不出来了,查看一下后台日志,其实就是这个登录拦截器给拦了:

前端请求增加token参数:
目前后端加了token校验之后,在前端则需要在请求头中增加token信息了,很显然也需要在统一接口拦截器中来进行处理,那vue中是如何处理的呢?其实使用的网络组件axios就有相应的处理办法,这块其实在之前https://www.cnblogs.com/webor2006/p/17182186.html已经使用过了:

所以在这里加上token信息的逻辑:

此时再运行你会发现用户管理模块在登录之后内容还是出不来,这里就有一个坑需要说明一下,就是这块:

但是在用户登录时往Redis写入时:

这样类型就不匹配了,所以需要这样改一下:

此时再运行看一下效果:

可以看到在登录之后再查询用户管理的列表就出来了,可见现在的token的校验已经是好使了。
前端页面增加登录校验:
未登录时,管理菜单要隐藏:
现在对于管理界面在用户没有登录时也能被看到,很显然是不合理的,所以接下来处理一下它:

根据之前的经验,对于元素的显隐可以用它:

挺简单,但是你运行发现不好使,反而是把这个v-show加到<router-link>中可以:


但是还是有瑕疵,就是隐藏时这个会占用宽度:

此时就需要自己来写css样式了,如下处理:

解释一下:

而如果没登录,则需要将元素给隐藏,注意这里的style里面是需要定义一个json的,好,再运行看一下:

对路由做判断,防止用户通过手敲url访问管理页面:
现在还有个问题,就是虽说已经在登录菜单上已经根据登录状态进行显隐控制了,但是用户还是可以直接通过管理的路由地址来访问到,比如:

所以接下来处理它。
1、路由中增加meta信息:
为了要处理需要登录的路由地址,这里需要在路由配置中增加一个meta信息,如下:

2、路由登录拦截:
接下来咱们则需要进行路由跳转的一个拦截处理,这块的写法也比较固定,写一次就明白了:

然后接下来就是要判断路由地址中有木有这个mate信息,如下:

而条件体里面的写法如下:

3、运行:
下面来运行看一下效果:

成功进行路由的登录拦截了。
总结:
好了,花了很长的篇幅就将用户登录相关的给学习完了,还是收获很多的,比如密码的双层加层,登录的拦截等等,下次继续。
关注个人公众号,获得实时推送

相关文章:
Spring Boot + Vue3前后端分离实战wiki知识库系统<十三>--单点登录开发二
接着Spring Boot Vue3前后端分离实战wiki知识库系统<十二>--用户管理&单点登录开发一继续往下。 登录功能开发: 接下来则来开发用户的登录功能,先准备后端的接口。 后端增加登录接口: 1、UserLoginReq: 先来准备…...
基于Java的高校科研信息管理系统设计与实现(亮点:完整严谨的科研项目审批流程、多文件上传、多角色)
高校科研信息管理系统 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序(小蔡coding)2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 主要功能描述 五、系统实现5.1…...
【uniapp】Dcloud的uni手机号一键登录,具体实现及踩过的坑,调用uniCloud.getPhoneNumber(),uni.login()等
一键登录Dcloud官网请戳这里,感兴趣的可以看看官网,有很详细的示例,选择App一键登录,可以看到一些常用的概述 比如: 1、调用uni.login就能弹出一键登录的页面 2、一键登录的流程,可以选择先预登录uni.prelo…...
Qt Quick Layouts Overview
Qt快速布局概述 #【中秋征文】程序人生,中秋共享# Qt快速布局是用于在用户界面中排列项目的项目。由于Qt快速布局还可以调整其项目的大小,因此它们非常适合可调整大小的用户界面。 开始 可以使用文件中的以下导入语句将 QML 类型导入到应用程序中。.qml…...
星臾计划 | 第六期优秀实习生访谈合集
此处划重点:优秀实习生评比活动将每三个月进行一次,获评同学可获得优秀实习生证书和丰厚的奖励 —— 是心动的感觉! 作为实习生培养计划,星臾计划不但能帮助在校生提前了解企业、熟悉工作环境,还能提前锁定正式 Offer…...
《数字图像处理-OpenCV/Python》连载(7)视频文件的读取与保存
《数字图像处理-OpenCV/Python》连载(7)视频文件的读取与保存 本书京东优惠购书链接:https://item.jd.com/14098452.html 本书CSDN独家连载专栏:https://blog.csdn.net/youcans/category_12418787.html 第1章 图像的基本操作 为…...
安防监控/视频汇聚/云存储/AI智能视频分析平台EasyCVR显示CPU过载,该如何解决?
视频云存储/安防监控/视频汇聚平台EasyCVR基于云边端智能协同,支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。安防视频监控系统EasyCVR拓展性强,视频能力丰富,具体可实现视频监控直播、视频轮播、视频录像、云…...
如何彻底卸载mysql
要彻底卸载 MySQL,您可以按照以下步骤进行操作。这些步骤适用于大多数 Linux 发行版,如 Ubuntu、CentOS、Debian 等。请注意,这些步骤可能会删除您的 MySQL 数据库和配置文件,所以请务必备份您的数据。 注意:在执行这些…...
【深度学习实验】线性模型(二):使用NumPy实现线性模型:梯度下降法
目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入库 1. 初始化参数 2. 线性模型 linear_model 3. 损失函数loss_function 4. 梯度计算函数compute_gradients 5. 梯度下降函数gradient_descent 6. 调用函数 一、实验介绍 使用Nu…...
带你熟练使用list
🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻强烈推荐优质专栏: 🍔🍟🌯C的世界(持续更新中) 🐻推荐专栏1: 🍔🍟🌯C语言初阶 🐻推荐专栏2: 🍔…...
排序——希尔排序
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、希尔排序二、希尔排序动态图三、希尔排序程序代码四、希尔排序习题总结 前言 希尔排序定义希尔排序算法分析希尔排序程序代码希尔排序练习题 一、希尔排序…...
为什么文件夹里的文件看不到?了解原因及应对措施
无论是在个人电脑中还是在其他存储介质上,我们经常会遇到文件夹中的文件突然不可见的情况。这种问题给我们的工作和生活带来了不便,并可能导致数据丢失。本文将分析文件夹中文件看不见的原因,并介绍相应的解决方法,以帮助大家更好…...
KVM嵌套虚拟化实现
KVM嵌套虚拟化实现 理论 Libvirt主要支持三种 CPU mode host-passthrough: libvirt 令 KVM 把宿主机的 CPU 指令集全部透传给虚拟机。因此虚拟机能够最大限度的使用宿主机 CPU 指令集,故性能是最好的。但是在热迁移时,它要求目的节点的 CPU 和源节点的…...
驱动开发,IO模型,信号驱动IO实现过程
1.信号驱动IO框架图 分析: 信号驱动IO是一种异步IO方式。linux预留了一个信号SIGIO用于进行信号驱动IO。进程主程序注册一个SIGIO信号的信号处理函数,当硬件数据准备就绪后会发起一个硬件中断,在中断的处理函数中向当前进程发送一个SIGIO信号…...
左神高级进阶班3(TreeMap顺序表记录线性数据的使用, 滑动窗口的使用,前缀和记录结构, 可能性的舍弃)
目录 【案例1】 【题目描述】 【思路解析】 【代码实现】 【案例2】 【题目描述】 【思路解析】 【代码实现】 【案例3】 【题目描述】 【思路解析】 【代码实现】 【案例4】 【题目描述】 【思路解析】 【代码实现】 【案例1】 【题目描述】 【思路解析】 这里…...
Linux线程
1.进程是资源管理的最小单位,线程是程序执行的最小单位。 2.每个进程有自己的数据段、代码段和堆栈段。线程通常叫做轻型的进程,它包含独立的栈和CPU寄存器状态,线程是进程的一条执行路径,每个线程共享其所附属进程的所有资源,包括…...
C++ 太卷,转 Java?
最近看到知乎、牛客等论坛上关于 C 很多帖子,比如: 2023年大量劝入C 2023年还建议走C方向吗? 看了一圈,基本上都是说 C 这个领域唯一共同点就是都使用 C 语言,其它几乎没有相关性。 的确是这样,比如量化交…...
《Java并发编程实战》第2章-线程安全性
0.概念理解 对象状态:存储在状态变量(例如实例或静态域)中的数据; 线程安全性:当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的; 竞态条件&…...
二蛋赠书三期:《C#入门经典(第9版)》
文章目录 前言活动规则参与方式本期赠送书籍介绍作者介绍内容简介读者对象获奖名单 结语 前言 大家好!我是二蛋,一个热爱技术、乐于分享的工程师。在过去的几年里,我一直通过各种渠道与大家分享技术知识和经验。我深知,每一位技术…...
Augmented Large Language Models with Parametric Knowledge Guiding
本文是LLM系列文章,针对《Augmented Large Language Models with Parametric Knowledge Guiding》的翻译。 参数知识引导下的增强大型语言模型 摘要1 引言2 相关工作3 LLM的参数化知识引导4 实验5 结论 摘要 大型语言模型(LLM)凭借其令人印…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
