博客文档续更
十、 博客前台模块-异常处理
目前我们的项目在认证出错或者权限不足的时候响应回来的Json,默认是使用Security官方提供的响应的格式,但是这种响应的格式肯定是不符合我们项目的接口规范的。所以需要自定义异常处理
我们需要去实现AuthenticationEntryPoint(官方提供的认证失败处理器)类、AccessDeniedHandler(官方提供的授权失败处理器)类,然后配置给Security

由于我们前台和后台的异常处理是一样的,所以我们在framework包下创建异常处理类
1. 认证的异常处理
在keke-framework工程的src/main/java/com.keke目录新建handler.security.AuthenticationEntryPointImpl类,写入如下
package com.keke.handler.security;import com.alibaba.fastjson.JSON;
import com.keke.domain.ResponseResult;
import com.keke.enums.AppHttpCodeEnum;
import com.keke.utils.WebUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException authException) throws IOException, ServletException {authException.printStackTrace();ResponseResult result = null;//BadCredentialsException 这个是我们测试输入错误账号密码出现的异常if(authException instanceof BadCredentialsException){result = ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_ERROR.getCode(),authException.getMessage());} else if (authException instanceof InsufficientAuthenticationException) {//InsufficientAuthenticationException 这个是我们测试不携带token出现的异常result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);}else {result = ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR,"认证或者授权失败");}//响应给前端WebUtils.renderString(httpServletResponse, JSON.toJSONString(result));}
}
2. 授权的异常处理
在keke-framework工程的src/main/java/com.keke目录新建handler.security.AccessDeniedHandlerImpl类,写入如下
package com.keke.handler.security;import com.alibaba.fastjson.JSON;
import com.keke.domain.ResponseResult;
import com.keke.enums.AppHttpCodeEnum;
import com.keke.utils.WebUtils;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Component
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException accessDeniedException) throws IOException, ServletException {accessDeniedException.printStackTrace();ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);//响应给前端WebUtils.renderString(httpServletResponse, JSON.toJSONString(result));}
}
3. 认证授权异常处理配置到框架
把keke-blog工程的SecurityConfig类修改为如下
package com.keke.config;import com.keke.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@Configuration
//WebSecurityConfigurerAdapter是Security官方提供的类
public class SecurityConfig extends WebSecurityConfigurerAdapter {//注入我们在keke-blog工程写的JwtAuthenticationTokenFilter过滤器@Autowiredprivate JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;@AutowiredAuthenticationEntryPoint authenticationEntryPoint;@AutowiredAccessDeniedHandler accessDeniedHandler;@Override@Beanpublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Bean//把官方的PasswordEncoder密码加密方式替换成BCryptPasswordEncoderpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()// 对于登录接口 允许匿名访问.antMatchers("/login").anonymous()//为方便测试认证过滤器,我们把查询友链的接口设置为需要登录才能访问。然后我们去访问的时候就能测试登录认证功能了.antMatchers("/link/getAllLink").authenticated()// 除上面外的所有请求全部不需要认证即可访问.anyRequest().permitAll();//配置我们自己写的认证和授权的异常处理http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler);http.logout().disable();//将自定义filter加入security过滤器链中http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);//允许跨域http.cors();}}
4. 测试自定义异常处理
第一步:打开redis,启动工程
第二步:向login接口发送用户名或者密码错误的post请求

第三步:向link/getAllLink接口发送不携带token的get请求

5. 统一异常处理
实际我们在开发过程中可能需要做很多的判断校验,如果出现了非法情况我们是期望响应对应的提示的。但是如果我们每次都自己手动去处理就会非常麻烦。我们可以选择直接抛出异常的方式,然后对异常进行统一处理。把异常中的信息封装成ResponseResult响应给前端
5.1 自定义异常
在keke-framework工程的src/main/java/com.keke目录新建exception.SystemException类,写入如下
package com.keke.exception;import com.keke.enums.AppHttpCodeEnum;//统一异常处理
public class SystemException extends RuntimeException{private int code;private String msg;public int getCode() {return code;}public String getMsg() {return msg;}//定义一个构造方法,接收的参数是枚举类型,AppHttpCodeEnum是我们在huanf-framework工程定义的枚举类public SystemException(AppHttpCodeEnum httpCodeEnum) {super(httpCodeEnum.getMsg());//把某个枚举类里面的code和msg赋值给异常对象this.code = httpCodeEnum.getCode();this.msg = httpCodeEnum.getMsg();}
}
5.2 全局异常处理
在keke-framework的com.keke包下新建handler.exception.GlobalExceptionHandler 写入如下,登录和其他地方出现的异常都会被这里捕获,然后响应返回
package com.keke.handler.exception;import com.keke.domain.ResponseResult;
import com.keke.enums.AppHttpCodeEnum;
import com.keke.exception.SystemException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;//@ControllerAdvice //对controller层的增强
//@ResponseBody//或者用下面一个注解代替上面的两个注解
@RestControllerAdvice
//使用Lombok提供的Slf4j注解,实现日志功能
@Slf4j
//全局异常处理。最终都会在这个类进行处理异常
public class GlobalExceptionHandler {//SystemException是我们写的类。用户登录的异常交给这里处理@ExceptionHandler(SystemException.class)public ResponseResult systemExceptionHandler(SystemException e){//打印异常信息,方便我们追溯问题的原因。{}是占位符,具体值由e决定log.error("出现了异常! {}",e);//从异常对象中获取提示信息封装,然后返回。ResponseResult是我们写的类return ResponseResult.errorResult(e.getCode(),e.getMsg());}//其它异常交给这里处理@ExceptionHandler(Exception.class)public ResponseResult exceptionHandler(Exception e){//打印异常信息,方便我们追溯问题的原因。{}是占位符,具体值由e决定log.error("出现了异常! {}",e);//从异常对象中获取提示信息封装,然后返回。ResponseResult、AppHttpCodeEnum是我们写的类return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),e.getMessage());//枚举值是500}
}
5.3 Controller层逻辑
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.entity.User;
import com.keke.enums.AppHttpCodeEnum;
import com.keke.exception.SystemException;
import com.keke.service.BlogLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;@RestController
public class BlogLoginController {@Autowiredprivate BlogLoginService blogLoginService;@PostMapping("/login")public ResponseResult login(@RequestBody User user){if(!StringUtils.hasText(user.getUserName())){//提示必须要传用户名throw new SystemException(AppHttpCodeEnum.REQUIRE_USERNAME);}return blogLoginService.login(user);}
}
5.3 测试
向login接口发送一个没有用户名只有密码的post,响应如下

可以看到,响应回来的信息是正确的
5.4 总结
首相前端发送请求,controller层先判断是否携带用户名,如果没有携带,抛出SystemException异常,并把响应的枚举信息传给异常对象,然后全局异常类中的systemExceptionHandler处理器处理就会捕获到该异常,然后在这个位置去封装响应体返回
其他异常则是由exceptionHandler处理
这就是异常统一处理
十一、博客前台模块-退出登录
1. 接口分析
| 请求方式 | 请求地址 | 请求头 |
| POST | /logout | 需要token请求头 |
响应格式
{"code": 200,"msg": "操作成功"
}
2. 思路分析
获取token解析出userId
删除redis中的用户信息
3. 代码实现
第一步: 把keke-blog工程的BlogLoginController类修改为如下,新增了退出登录的接口
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.entity.User;
import com.keke.enums.AppHttpCodeEnum;
import com.keke.exception.SystemException;
import com.keke.service.BlogLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;@RestController
public class BlogLoginController {@Autowiredprivate BlogLoginService blogLoginService;@PostMapping("/login")public ResponseResult login(@RequestBody User user){if(!StringUtils.hasText(user.getUserName())){//提示必须要传用户名throw new SystemException(AppHttpCodeEnum.REQUIRE_USERNAME);}return blogLoginService.login(user);}@PostMapping("/logout")public ResponseResult logout(){return blogLoginService.logout();}
}
第二步: 把keke-framework工程的BlogLoginService接口修改为如下,新增了退出登录的方法
package com.keke.service;import com.keke.domain.ResponseResult;
import com.keke.domain.entity.User;public interface BlogLoginService {ResponseResult login(User user);ResponseResult logout();}
第三步: 把keke-framework工程的BlogLoginServiceImpl类修改为如下,新增了退出登录的核心代码
package com.keke.service.impl;import com.keke.domain.ResponseResult;
import com.keke.domain.entity.LoginUser;
import com.keke.domain.entity.User;
import com.keke.domain.vo.BlogLoginUserVo;
import com.keke.domain.vo.UserInfoVo;
import com.keke.service.BlogLoginService;
import com.keke.utils.BeanCopyUtils;
import com.keke.utils.JwtUtil;
import com.keke.utils.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import java.util.Objects;@Service
public class BlogLoginServiceImpl implements BlogLoginService {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate RedisCache redisCache;@Overridepublic ResponseResult login(User user) {UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());Authentication authenticate = authenticationManager.authenticate(authenticationToken);//authenticationManager会默认调用UserDetailsService从内存中进行用户认证,我们实际需求是从数据库,因此我们要重新创建一个UserDetailsService的实现类//判断是否认证通过if(Objects.isNull(authenticate)){throw new RuntimeException("用户名或者密码错误");}//获取Userid,生成tokenLoginUser loginUser = (LoginUser) authenticate.getPrincipal();String userId = loginUser.getUser().getId().toString();String jwt = JwtUtil.createJWT(userId);//把用户信息存入redisredisCache.setCacheObject("bloglogin:" + userId,loginUser);//把token和userInfo封装返回,因为响应回去的data有这两个属性,所以要封装VoUserInfoVo userInfoVo = BeanCopyUtils.copyBean(loginUser.getUser(), UserInfoVo.class);BlogLoginUserVo blogLoginUserVo = new BlogLoginUserVo(jwt,userInfoVo);return ResponseResult.okResult(blogLoginUserVo);}@Overridepublic ResponseResult logout() {//获取token解析获取userIdAuthentication authentication = SecurityContextHolder.getContext().getAuthentication();LoginUser loginUser = (LoginUser) authentication.getPrincipal();Long userId = loginUser.getUser().getId();//删除redis中的信息(根据key删除)redisCache.deleteObject("bloglogin:" + userId);return ResponseResult.okResult();}
}
第四步: 把keke-blog工程的SecurityConfig类修改为如下,增加了需要有登录状态才能执行退出登录,否则就报'401 需要登录后操作'
package com.keke.config;import com.keke.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@Configuration
//WebSecurityConfigurerAdapter是Security官方提供的类
public class SecurityConfig extends WebSecurityConfigurerAdapter {//注入我们在keke-blog工程写的JwtAuthenticationTokenFilter过滤器@Autowiredprivate JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;@AutowiredAuthenticationEntryPoint authenticationEntryPoint;@AutowiredAccessDeniedHandler accessDeniedHandler;@Override@Beanpublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Bean//把官方的PasswordEncoder密码加密方式替换成BCryptPasswordEncoderpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()// 对于登录接口 允许匿名访问.antMatchers("/login").anonymous()
//这里新增必须要是登录状态才能访问退出登录的接口,即是认证过的状态.antMatchers("/logout").authenticated()//为方便测试认证过滤器,我们把查询友链的接口设置为需要登录才能访问。然后我们去访问的时候就能测试登录认证功能了.antMatchers("/link/getAllLink").authenticated()// 除上面外的所有请求全部不需要认证即可访问.anyRequest().permitAll();//配置我们自己写的认证和授权的异常处理http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler);http.logout().disable();//将自定义filter加入security过滤器链中http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);//允许跨域http.cors();}}
4. 测试
首先测试logout是否真的实现了退出登录的效果,即删除了token在redis中的缓存,使得携带原token的请求失效
第一步,先登录 JSON格式的body可复制如下代码,登录成功
{"userName":"sg","password":"1234"
}

第二步,拿着登录成功的token,去访问getAllLink接口,访问成功,到这里一切正常

第三步:携带该token向logout接口发送post请求,为什么要携带token呢,因为我们之前在SecurityConfig中配置过了,必须是已认证的状态,已认证的状态意味着必须是请求头携带token

postman结果如下,操作成功意味着退出登录成功

第四步:拿token再次访问getAllLink接口,发现已经不能访问

并且我们可以看到redis中也没有缓存的信息了

十二、博客前台模块-评论列表
1. 评论表的字段


2. 接口分析
| 请求方式 | 请求地址 | 请求头 |
| GET | /comment/commentList | 不需要token请求头(未登录也能看到评论信息) |
请求格式为query格式,参数如下
articleId:文章id
pageNum:页码
pageSize:每页条数
响应格式如下
{"code": 200,"data": {"rows": [{"articleId": "1","children": [{"articleId": "1","content": "评论内容(子评论)","createBy": "1","createTime": "2022-01-30 10:06:21","id": "20","rootId": "1","toCommentId": "1","toCommentUserId": "1","toCommentUserName": "这条评论(子评论)回复的是哪个人","username": "发这条评论(子评论)的人"}],"content": "评论内容(根评论)","createBy": "1","createTime": "2022-01-29 07:59:22","id": "1","rootId": "-1","toCommentId": "-1","toCommentUserId": "-1","username": "发这条评论(根评论)的人"}],"total": "15"},"msg": "操作成功"
}
3. 准备代码
第一步:实体类Comment创建在keke-framework的com.keke.domain.entity下
package com.keke.domain.entity;import java.util.Date;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.baomidou.mybatisplus.annotation.TableName;/*** 评论表(Comment)表实体类** @author makejava* @since 2023-10-12 20:20:14*/
@SuppressWarnings("serial")
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("ke_comment")
public class Comment {private Long id;//评论类型(0代表文章评论,1代表友链评论)private String type;//文章idprivate Long articleId;//根评论idprivate Long rootId;//评论内容private String content;//所回复的目标评论的useridprivate Long toCommentUserId;//回复目标评论idprivate Long toCommentId;private Long createBy;private Date createTime;private Long updateBy;private Date updateTime;//删除标志(0代表未删除,1代表已删除)private Integer delFlag;}
第二步:创建CommentMapper
package com.keke.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.keke.domain.entity.Comment;/*** 评论表(Comment)表数据库访问层** @author makejava* @since 2023-10-12 20:20:41*/
public interface CommentMapper extends BaseMapper<Comment> {}
第三步:创建CommentService
package com.keke.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.keke.domain.entity.Comment;/*** 评论表(Comment)表服务接口** @author makejava* @since 2023-10-12 20:20:41*/
public interface CommentService extends IService<Comment> {}
第四步:创建CommentServiceImpl
package com.keke.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keke.domain.entity.Comment;
import com.keke.mapper.CommentMapper;
import com.keke.service.CommentService;
import org.springframework.stereotype.Service;/*** 评论表(Comment)表服务实现类** @author makejava* @since 2023-10-12 20:20:41*/
@Service("commentService")
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {}
4. 代码实现-不考虑子评论
相关文章:
博客文档续更
十、 博客前台模块-异常处理 目前我们的项目在认证出错或者权限不足的时候响应回来的Json,默认是使用Security官方提供的响应的格式,但是这种响应的格式肯定是不符合我们项目的接口规范的。所以需要自定义异常处理 我们需要去实现AuthenticationEntryP…...
OCR让点读笔如虎添翼
点读笔是一种智能学习工具,它可以通过识别文字来提供相应的语音或图像反馈。在实现文字识别功能时,点读笔通常会借助OCR(Optical Character Recognition,光学字符识别)技术。下面将详细介绍点读笔如何利用OCR技术实现文…...
棱镜七彩参编!开源领域4项团体标准正式发布
近日,中电标2023年第27号团体标准公告正式发布,《T/CESA 1270.2-2023 信息技术 开源治理 第 2 部分:企业治理评估模型》、《T/CESA 1270.3-2023 信息技术 开源治理 第 3 部分:社区治理框架》、《T/CESA 1270.5-2023 信息技术 开源…...
轻量级Composition
MEF,全称Managed Extensibility Framework(托管可扩展框架)。MEF是专门致力于解决扩展性问题的框架。MEF 位于 ComponentModel.Composition 程序集中,添加 System.ComponentModel.Composition 和 System.ComponentModel.Compositi…...
Vxlan网络和flannel记录
Vxlan 大二层网络,在三层网络中构建逻辑的2层网络 数据包经过vxlan隧道 用vni标识不同的vxlan网络(类似于vlan的vid) 通过vtep来封装和解封装,通过UDP传输 Flannel 分配子网和IP地址:Flannel为每个容器或虚拟机分配唯一…...
【已解决】微信小程序-苹果手机日期解析异常
在开发微信小程序时,使用了 uView 的 CountDown倒计时 组件和 uni.$u.timeFrom Api,后台传递了一个时间字符串,前台计算时间戳的差值,来显示还有多久开始,这个功能在模拟器和我自己手机(iphon13)…...
Avalonia如何更改全局背景色
1.项目下载地址:https://gitee.com/confusedkitten/avalonia-demo 2.UI库Semi.Avalonia,项目地址 https://github.com/irihitech/Semi.Avalonia 3.ColorView,使用Semi.Avalonia.ColorPicker,Nuget获取就行 4.样式预览 以下是…...
万界星空科技低代码平台云MES系统功能场景
1、 工艺管理 生产工艺规程、岗位操作法、工艺卡片的编制。 生产过程的工艺条件、产品质量指标以及原材料消耗的执行检查、相关数据的统计分析。 2、 工序管理 对人、机、料、法控制,规定产品质量标准及有关完成方法的各项规程,并明确各道工序的管理负责…...
运维大数据平台的建设与实践探索
随着企业数字化转型的推进,运维管理面临着前所未有的挑战和机遇。为应对日益复杂且严峻的挑战,数字免疫系统和智能运维等概念应运而生。数字免疫系统和智能运维作为新兴技术,正引领着运维管理的新趋势。数字免疫系统和智能运维都借助大数据运…...
【Java 进阶篇】创建 HTML 注册页面
在这篇博客中,我们将介绍如何创建一个简单的 HTML 注册页面。HTML(Hypertext Markup Language)是一种标记语言,用于构建网页的结构和内容。创建一个注册页面是网页开发的常见任务之一,它允许用户提供个人信息并注册成为…...
【JVM系列】- 启航·JVM概论学习
启航JVM概论 😄生命不息,写作不止 🔥 继续踏上学习之路,学之分享笔记 👊 总有一天我也能像各位大佬一样 🏆 博客首页 怒放吧德德 To记录领地 🌝分享学习心得,欢迎指正,…...
Windows技巧
Windows应用 Windows应用无限延长Windows10 自动更新时间管理员身份打开cmd输入以下代码设置暂停更新时间 Windows应用 无限延长Windows10 自动更新时间 管理员身份打开cmd 输入以下代码 这里设置的是3000天,需要恢复更新可以将其设置为1天 reg add “HKEY_LOCA…...
Git 应用小记
常用命令 git reset 3种模式 --soft:将HEAD引用指向给定提交,索引(暂存区)和工作目录的内容不变 --mixed(默认,可不写):将HEAD引用指向给定提交,索引(暂存区…...
APT攻击与零日漏洞
APT攻击 当谈到网络安全时,APT(高级持续性威胁)攻击是最为复杂和难以检测的攻击类型之一。APT攻击通常涉及到高度的技术和策略性,而且它们的目标是深入地渗透和长时间地隐藏在目标网络中。 1. 什么是APT攻击? 高级持续…...
leetCode 1143.最长公共子序列 动态规划 + 滚动数组
1143. 最长公共子序列 - 力扣(LeetCode) 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。 一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串…...
【C++ Miscellany】继承体系非尾端类设计为抽象类
部分赋值问题 用软件来处理两种动物:蜥蜴和鸡 class Animal { public:Animal& operator (const Animal& rhs);... };class Lizard: public Animal { public:Lizard& operator (const Lizard& rhs);... };class Chicken: public Animal {Chicken…...
Leetcode236. 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖…...
Swift SwiftUI CoreData 过滤数据 2
预览 Code import SwiftUI import CoreDatastruct HomeSearchView: View {Environment(\.dismiss) var dismissState private var search_value ""FetchRequest(entity: Bill.entity(),sortDescriptors: [NSSortDescriptor(keyPath: \Bill.c_at, ascending: false)…...
解决maven骨架加载慢问题(亲测解决)
1、下载archetype-catalog.xml 网站 : https://repo.maven.apache.org/maven2/ 2、放在这个文件夹下面 3、setting–>build–>Runner : -DarchetypeCataloglocal...
Android---java内存模型与线程
Java 内存模型翻译自 Java Memory Model,简称 JMM。它所描述的是多线程并发、CPU 缓存等方面的内容。 在每一个线程中,都会有一块内部的工作内存,这块内存保存了主内存共享数据的拷贝副本。但在 Java 线程中并不存在所谓的工作内存࿰…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...
若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...
