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

AOP操作日志记录

AOP操作日志记录
1.创建注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PassportLog {String operatePage();String operateType();ClassTypEnum classType();}

2.创建切面
对于字典,可以通过注解属性去转换,枚举也可以注解属性去转换,但是需要if else判断;对于数组类型的传值,需要if else特殊处理;另外需注意反射获取不到子类的属性private

@Slf4j
@Aspect
@Component
@AllArgsConstructor
public class PassportLogAop {/*** 修改记录-字段的分割符号*/private static final String SEPARATOR = ";";@Resourceprivate PassportMapper passportMapper;@Resourceprivate PassportCardFillMapper passportCardFillMapper;@Resourceprivate PassportFamilyMembersMapper passportFamilyMembersMapper;@Resourceprivate PassportEmergencyContactMapper passportEmergencyContactMapper;@Resourceprivate PassportOperateRecordService passportOperateRecordService;@Resourceprivate SysFeign sysFeign;@Resourceprivate SystemDictService systemDictService;@Before("@annotation(passportLog)")public void before(JoinPoint point, PassportLog passportLog) {try {saveLog(point, passportLog);} catch (Exception e) {log.error(e.getMessage());}}/*** 操作日志记录** @param point* @param passportLog* @throws IntrospectionException* @throws InvocationTargetException* @throws IllegalAccessException*/public void saveLog(JoinPoint point, PassportLog passportLog) throws IntrospectionException, InvocationTargetException, IllegalAccessException {ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();if (requestAttributes == null) {return;}PassportOperateRecord record = new PassportOperateRecord();record.setDelFlag(PassportCommonConstant.NOT_DELETE);HttpServletRequest request = Objects.requireNonNull(requestAttributes).getRequest();if (ObjUtil.isNotNull(request)) {record.setOperateIp(IpUtil.getIp(request));record.setUrl(StrUtil.sub(URLUtil.getPath(request.getRequestURI()), 0, 255));record.setMethod(StrUtil.sub(point.getTarget().getClass().getName() + "." + point.getSignature().getName() + "()", 0, 255));record.setRequestMethod(request.getMethod());}record.setOperateTime(LocalDateTime.now());record.setOperatePerson(BaseUserEntity.getName());record.setOperateOffice(BaseUserEntity.getDeptName());record.setOperateRole(sysFeign.queryRoleName(new ArrayList<>(BaseUserEntity.getRoleCode())).getData());record.setOperatePage(passportLog.operatePage());record.setOperateType(passportLog.operateType());Object[] args = point.getArgs();String s = JSONUtil.toJsonStr(args[0]);ClassTypEnum classType = passportLog.classType();String prefix = "";String content = "";if (classType.equals(ClassTypEnum.PASSPORT_ACCEPT_INFO)) {//预约办理PassportAcceptInfoDTO newObj = JSONObject.parseObject(s, PassportAcceptInfoDTO.class);String requestNo = newObj.getRequestNo();record.setRequestNo(requestNo);PassportAcceptInfoDTO oldObj = new PassportAcceptInfoDTO();BeanUtil.copyProperties(passportMapper.selectById(newObj.getId()), oldObj);content = this.compare(oldObj, newObj, requestNo, prefix, content);record.setOperateContent(content);//操作类型Integer status = newObj.getStatus();if (ApplyStatusEnum.UN_ACCEPTED.getCode().equals(status)) {record.setOperateType(PassportOperateTypeConstant.QXSL);} else if (ApplyStatusEnum.PENDING_AUDITING.getCode().equals(status)) {record.setOperateType(PassportOperateTypeConstant.SLBDY);}passportOperateRecordService.save(record);} else if (classType.equals(ClassTypEnum.PASSPORT_ACCEPT_INFO_DRAFT)) {//预约办理草稿箱PassportAcceptInfoDraftDTO newObj = JSONObject.parseObject(s, PassportAcceptInfoDraftDTO.class);String requestNo = newObj.getRequestNo();record.setRequestNo(requestNo);PassportAcceptInfoDraftDTO oldObj = new PassportAcceptInfoDraftDTO();BeanUtil.copyProperties(passportMapper.selectById(newObj.getId()), oldObj);record.setOperateContent(this.compare(oldObj, newObj, requestNo, prefix, content));passportOperateRecordService.save(record);} else if (classType.equals(ClassTypEnum.TODAY_APPLY)) {//申请今日受理TodayApplyDTO newObj = JSONObject.parseObject(s, TodayApplyDTO.class);String requestNo = newObj.getRequestNo();record.setRequestNo(requestNo);record.setOperateContent("申请说明:" + newObj.getReason());passportOperateRecordService.save(record);} else if (classType.equals(ClassTypEnum.PASSPORT_SIDE_HANDLE)) {//现场办理PassportSiteHandleDTO newObj = JSONObject.parseObject(s, PassportSiteHandleDTO.class);record.setRequestNo(newObj.getRequestNo());PassportSiteHandleDTO oldObj = new PassportSiteHandleDTO();if (Objects.isNull(oldObj.getId())) {prefix = "新增:";} else {BeanUtil.copyProperties(passportMapper.selectById(newObj.getId()), oldObj);}record.setOperateContent(this.compare(oldObj, newObj, newObj.getRequestNo(), prefix, content));//操作类型Integer status = newObj.getStatus();if (ApplyStatusEnum.UN_ACCEPTED.getCode().equals(status)) {record.setOperateType(PassportOperateTypeConstant.QXSL);} else if (ApplyStatusEnum.PENDING_AUDITING.getCode().equals(status)) {record.setOperateType(PassportOperateTypeConstant.SLBDY);}passportOperateRecordService.save(record);} else if (classType.equals(ClassTypEnum.PASSPORT_SIDE_HANDLE_DRAFT)) {//现场办理草稿箱PassportSiteHandleDraftDTO newObj = JSONObject.parseObject(s, PassportSiteHandleDraftDTO.class);String requestNo = newObj.getRequestNo();record.setRequestNo(requestNo);PassportSiteHandleDraftDTO oldObj = new PassportSiteHandleDraftDTO();if (Objects.isNull(oldObj.getId())) {prefix = "新增:";} else {BeanUtil.copyProperties(passportMapper.selectById(newObj.getId()), oldObj);}content = this.compare(oldObj, newObj, requestNo, prefix, content);record.setOperateContent(content);passportOperateRecordService.save(record);} else if (classType.equals(ClassTypEnum.PASSPORT_CHECK)) {//护照情况核查、退回修改、保存、生成传真并提交审核PassportCheckDTO newObj = JSONObject.parseObject(s, PassportCheckDTO.class);record.setRequestNo(newObj.getRequestNo());PassportCheckDTO oldObj = new PassportCheckDTO();BeanUtil.copyProperties(passportMapper.selectById(newObj.getId()), oldObj);record.setOperateContent(this.compare(oldObj, newObj, newObj.getRequestNo(), prefix, content));//操作类型Integer status = newObj.getStatus();Integer problemStatus = newObj.getProblemStatus();if (ApplyStatusEnum.NOT_VERIFIED.getCode().equals(status)) {record.setOperateType(PassportOperateTypeConstant.BC);}if (PassportProblemEnum.THXG.getCode().equals(problemStatus)) {record.setOperateType(PassportOperateTypeConstant.THXG);} else if (ApplyStatusEnum.PENDING_AUDITING.getCode().equals(status)) {record.setOperateType(PassportOperateTypeConstant.SCCZBTJSH);}passportOperateRecordService.save(record);} else if (classType.equals(ClassTypEnum.PASSPORT_CHECK_BATCH)) {//批量核查List ids = JSONObject.parseObject(s, List.class);for (Object id : ids) {Passport passport = passportMapper.selectById(Long.parseLong(id.toString()));record.setRequestNo(passport.getRequestNo());record.setOperateContent("批量生成传真并提交审核");passportOperateRecordService.save(record);}} else if (classType.equals(ClassTypEnum.PASSPORT_EXAMINE_BATCH)) {//批量审核List ids = JSONObject.parseObject(s, List.class);for (Object id : ids) {Passport passport = passportMapper.selectById(Long.parseLong(id.toString()));record.setRequestNo(passport.getRequestNo());record.setOperateContent("批量审核通过");passportOperateRecordService.save(record);}} else if (classType.equals(ClassTypEnum.PASSPORT_EXAMINE)) {//审核PassportExamineDTO newObj = JSONObject.parseObject(s, PassportExamineDTO.class);record.setRequestNo(newObj.getRequestNo());PassportExamineDTO oldObj = new PassportExamineDTO();BeanUtil.copyProperties(passportMapper.selectById(newObj.getId()), oldObj);//如果老状态是复核则页面应设置为复核页面if (ApplyStatusEnum.PENDING_REVIEW.getCode().equals(oldObj.getStatus())) {record.setOperatePage(PassportOperatePageConstant.HZBL_HZFH_ZHFX);}record.setOperateContent(this.compare(oldObj, newObj, newObj.getRequestNo(), prefix, content));//操作类型Integer status = newObj.getStatus();Integer problemStatus = newObj.getProblemStatus();if (ApplyStatusEnum.PENDING_REVIEW.getCode().equals(status)) {record.setOperateType(PassportOperateTypeConstant.TJFH);} else if (ApplyStatusEnum.RETURNED_ITEMS.getCode().equals(status)) {record.setOperateType(PassportOperateTypeConstant.TJ);} else if (ApplyStatusEnum.PENDING_CERTIFICATION.getCode().equals(status)) {record.setOperateType(PassportOperateTypeConstant.TG);}if (PassportProblemEnum.THXG.getCode().equals(problemStatus)) {record.setOperateType(PassportOperateTypeConstant.THXG);} else if (PassportProblemEnum.GQ.getCode().equals(problemStatus)) {record.setOperateType(PassportOperateTypeConstant.GQ);}passportOperateRecordService.save(record);}}/*** 比较两个对象,并且返回不一致的信息** @param newObj* @param oldObj* @param requestNo* @param prefix* @return*/private String compare(Object oldObj, Object newObj, String requestNo, String prefix, String str) throws IntrospectionException, InvocationTargetException, IllegalAccessException {str += prefix;//1:获取到对象的classClass<?> oldClass = oldObj.getClass();Class<?> newClass = newObj.getClass();//2:获取到对象的属性列表Field[] oldFields = oldClass.getDeclaredFields();Field[] newFields = newClass.getDeclaredFields();for (int i = 0; i < oldFields.length; i++) {if ("serialVersionUID".equals(oldFields[i].getName())) {continue;}//将此对象的 accessible 标志设置为指示的布尔值。// 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。// 值为 false 则指示反射的对象应该实施 Java 语言访问检查;// 实际上setAccessible是启用和禁用访问安全检查的开关,// 并不是为true就能访问为false就不能访问 ;oldFields[i].setAccessible(true);newFields[i].setAccessible(true);//获取到字段上的注解PassportField annotation = oldFields[i].getAnnotation(PassportField.class);//当没有注解的时候跳过本次循环if (annotation == null) {continue;}//获取注解中的字段名String name = annotation.name();ListTypEnum listTypEnum = annotation.listType();SysDictTypeEnum code = annotation.code();TypeEnum typeEnum = annotation.typeEnum();PropertyDescriptor oldPd = new PropertyDescriptor(oldFields[i].getName(), oldClass);PropertyDescriptor newPd = new PropertyDescriptor(newFields[i].getName(), newClass);//调用成员方法Method oldReadMethod = oldPd.getReadMethod();Method newReadMethod = newPd.getReadMethod();//3:获取到参数数值Object oldValue = oldReadMethod.invoke(oldObj);Object newValue = newReadMethod.invoke(newObj);if (StrUtil.isBlank(name)) {//处理listif (listTypEnum.equals(ListTypEnum.CARD_FILL)) {str = this.cardFill(newValue, requestNo, str);continue;} else if (listTypEnum.equals(ListTypEnum.EMERGENCY_CONTACT)) {str = this.emergencyContact(newValue, requestNo, str);continue;} else if (listTypEnum.equals(ListTypEnum.FAMILY_MEMBERS)) {str = this.familyMember(newValue, requestNo, str);continue;}} else {//处理系统字典if (ObjUtil.isNotNull(code) && !SysDictTypeEnum.NULL.equals(code)) {if (ObjUtil.isNotNull(oldValue)) {oldValue = systemDictService.queryDictName(code, oldValue.toString());}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {newValue = systemDictService.queryDictName(code, newValue.toString());}}if (ObjUtil.isNotNull(typeEnum) && !TypeEnum.NULL.equals(typeEnum)) {if (TypeEnum.STATUS.equals(typeEnum)) {if (ObjUtil.isNotNull(oldValue) && StrUtil.isNotBlank(oldValue.toString())) {oldValue = ApplyStatusEnum.getMessage(Integer.parseInt(oldValue.toString()));}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {newValue = ApplyStatusEnum.getMessage(Integer.parseInt(newValue.toString()));}} else if (TypeEnum.SF.equals(typeEnum)) {if (ObjUtil.isNotNull(oldValue) && StrUtil.isNotBlank(oldValue.toString())) {oldValue = PassportFlagEnum.getMessage(Integer.parseInt(oldValue.toString()));}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {newValue = PassportFlagEnum.getMessage(Integer.parseInt(newValue.toString()));}} else if (TypeEnum.BIRTHPLACE.equals(typeEnum)) {if (ObjUtil.isNotNull(oldValue) && StrUtil.isNotBlank(oldValue.toString())) {oldValue = systemDictService.birthdayPlace(oldValue.toString());}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {newValue = systemDictService.birthdayPlace(newValue.toString());}} else if (TypeEnum.CARD_VALID_UNIT.equals(typeEnum)) {if (ObjUtil.isNotNull(oldValue) && StrUtil.isNotBlank(oldValue.toString())) {oldValue = CardValidUnitEnum.getMessage(oldValue.toString());}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {newValue = CardValidUnitEnum.getMessage(newValue.toString());}} else if (TypeEnum.ISSUE_PLACE.equals(typeEnum)) {if (ObjUtil.isNotNull(oldValue) && StrUtil.isNotBlank(oldValue.toString())) {oldValue = systemDictService.issuePlace(oldValue.toString());}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {newValue = systemDictService.issuePlace(newValue.toString());}} else if (TypeEnum.ISSUE_CHECK.equals(typeEnum)) {if (ObjUtil.isNotNull(oldValue) && StrUtil.isNotBlank(oldValue.toString())) {oldValue = PassportDictIssueEnum.getDiceLabel(oldValue.toString());}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {newValue = PassportDictIssueEnum.getDiceLabel(newValue.toString());}} else if (TypeEnum.EVIDENCE_WAY.equals(typeEnum)) {if (ObjUtil.isNotNull(oldValue) && StrUtil.isNotBlank(oldValue.toString())) {oldValue = PassportEvidenceWayEnum.getMessage(Integer.parseInt(oldValue.toString()));}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {newValue = PassportEvidenceWayEnum.getMessage(Integer.parseInt(newValue.toString()));}} else if (TypeEnum.DECLARATION_RELATION.equals(typeEnum)) {if (ObjUtil.isNotNull(oldValue) && StrUtil.isNotBlank(oldValue.toString())) {oldValue = PassportDictRelationEnum.getDiceLabel(oldValue.toString());}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {newValue = PassportDictRelationEnum.getDiceLabel(newValue.toString());}} else if (TypeEnum.CHECK_OFFICE.equals(typeEnum)) {if (ObjUtil.isNotNull(oldValue) && StrUtil.isNotBlank(oldValue.toString())) {String[] split = oldValue.toString().split(",");StringBuilder oldValueContent = new StringBuilder();for (String s : split) {oldValueContent.append(systemDictService.queryDictName(SysDictTypeEnum.VERIFICATION_AND_SUBMISSION_AUTHORITY, s));}oldValue = oldValueContent.toString();}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {String[] split = newValue.toString().split(",");StringBuilder newValueContent = new StringBuilder();for (String s : split) {newValueContent.append(systemDictService.queryDictName(SysDictTypeEnum.VERIFICATION_AND_SUBMISSION_AUTHORITY, s));}newValue = newValueContent.toString();}} else if (TypeEnum.EMERGENCY_RELATION.equals(typeEnum)) {if (ObjUtil.isNotNull(oldValue) && StrUtil.isNotBlank(oldValue.toString())) {oldValue = PassportDictEmergencyContactEnum.getDiceLabel(oldValue.toString());}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {newValue = PassportDictEmergencyContactEnum.getDiceLabel(newValue.toString());}} else if (TypeEnum.FAMILY_RELATION.equals(typeEnum)) {if (ObjUtil.isNotNull(oldValue) && StrUtil.isNotBlank(oldValue.toString())) {oldValue = PassportDictFamilyEnum.getDiceLabel(oldValue.toString());}if (ObjUtil.isNotNull(newValue) && StrUtil.isNotBlank(newValue.toString())) {newValue = PassportDictFamilyEnum.getDiceLabel(newValue.toString());}}}//获取差异字段str = getDifferenceFieldStr(str, name, oldValue, newValue);}}return str;}/*** 获取差异字段新旧值** @param str* @param fieldName* @param oldValue* @param newValue* @return*/private static String getDifferenceFieldStr(String str, String fieldName, Object oldValue, Object newValue) {if (null == oldValue || StringUtils.isBlank(oldValue.toString())) {oldValue = "无";}if (null == newValue || StringUtils.isBlank(newValue.toString())) {newValue = "无";}if (!oldValue.equals(newValue)) {str += fieldName + "从 " + oldValue + ",修改为 " + newValue + SEPARATOR;}return str;}/*** 处理加注** @param newValue* @param requestNo* @throws IntrospectionException* @throws InvocationTargetException* @throws IllegalAccessException*/private String cardFill(Object newValue, String requestNo, String str) throws IntrospectionException, InvocationTargetException, IllegalAccessException {List<PassportCardFillDTO> newObjects = (List<PassportCardFillDTO>) newValue;List<PassportCardFillDTO> oldObjects = passportCardFillMapper.queryCardFillByRequestNo(requestNo);if (CollectionUtils.isEmpty(newObjects)) {if (!CollectionUtils.isEmpty(oldObjects)) {for (PassportCardFillDTO oldObject : oldObjects) {str = this.compare(oldObject, new PassportCardFillDTO(), requestNo, "删除加注:", str);}}} else {if (CollectionUtils.isEmpty(oldObjects)) {for (PassportCardFillDTO newObject : newObjects) {str = this.compare(new PassportCardFillDTO(), newObject, requestNo, "新增加注:", str);}} else {for (PassportCardFillDTO newObject : newObjects) {if (Objects.isNull(newObject.getId())) {str = this.compare(new PassportCardFillDTO(), newObject, requestNo, "新增加注:", str);} else {List<PassportCardFillDTO> removeFills = new ArrayList<>();for (PassportCardFillDTO oldObject : oldObjects) {if (oldObject.getId().equals(newObject.getId())) {if (!oldObject.equals(newObject)) {str = this.compare(oldObject, newObject, requestNo, "", str);}removeFills.add(oldObject);}}oldObjects.removeAll(removeFills);for (PassportCardFillDTO oldObject : oldObjects) {str = this.compare(oldObject, new PassportCardFillDTO(), requestNo, "删除加注:", str);}}}}}return str;}/*** 处理紧急联系人** @param newValue* @param requestNo* @throws IntrospectionException* @throws InvocationTargetException* @throws IllegalAccessException*/private String emergencyContact(Object newValue, String requestNo, String str) throws IntrospectionException, InvocationTargetException, IllegalAccessException {List<PassportEmergencyContactAddDTO> newObjects = (List<PassportEmergencyContactAddDTO>) newValue;List<PassportEmergencyContactAddDTO> oldObjects = passportEmergencyContactMapper.queryEmergencyContactByRequestNo(requestNo);if (CollectionUtils.isEmpty(newObjects)) {if (CollUtil.isNotEmpty(oldObjects)) {for (PassportEmergencyContactAddDTO oldObject : oldObjects) {str = this.compare(oldObject, new PassportEmergencyContactAddDTO(), requestNo, "删除紧急联系人:", str);}}} else {if (CollUtil.isEmpty(oldObjects)) {for (PassportEmergencyContactAddDTO newObject : newObjects) {str = this.compare(new PassportEmergencyContactAddDTO(), newObject, requestNo, "新增紧急联系人:", str);}} else {for (PassportEmergencyContactAddDTO newObject : newObjects) {if (ObjUtil.isNull(newObject.getId())) {str = this.compare(new PassportEmergencyContactAddDTO(), newObject, requestNo, "新增紧急联系人:", str);} else {for (PassportEmergencyContactAddDTO oldObject : oldObjects) {if (oldObject.getId().equals(newObject.getId())) {if (!oldObject.equals(newObject)) {str = this.compare(oldObject, newObject, requestNo, "", str);}oldObjects.remove(oldObject);}}if (CollUtil.isNotEmpty(oldObjects)) {for (PassportEmergencyContactAddDTO oldObject : oldObjects) {str = this.compare(oldObject, new PassportEmergencyContactAddDTO(), requestNo, "删除紧急联系人:", str);}}}}}}return str;}/*** 处理家庭成员** @param newValue* @param requestNo* @throws IntrospectionException* @throws InvocationTargetException* @throws IllegalAccessException*/private String familyMember(Object newValue, String requestNo, String str) throws IntrospectionException, InvocationTargetException, IllegalAccessException {List<PassportFamilyMembersAddDTO> newObjects = (List<PassportFamilyMembersAddDTO>) newValue;List<PassportFamilyMembersAddDTO> oldObjects = passportFamilyMembersMapper.queryFamilyMemberByRequest(requestNo);if (CollectionUtils.isEmpty(newObjects)) {if (ObjUtil.isNotEmpty(oldObjects)) {for (PassportFamilyMembersAddDTO oldObject : oldObjects) {str = this.compare(oldObject, new PassportFamilyMembersAddDTO(), requestNo, "删除家庭成员:", str);}}} else {if (CollUtil.isEmpty(oldObjects)) {for (PassportFamilyMembersAddDTO newObject : newObjects) {str = this.compare(new PassportFamilyMembersAddDTO(), newObject, requestNo, "新增家庭成员:", str);}} else {for (PassportFamilyMembersAddDTO newObject : newObjects) {if (ObjUtil.isNull(newObject.getId())) {str = this.compare(new PassportFamilyMembersAddDTO(), newObject, requestNo, "新增家庭成员:", str);} else {for (PassportFamilyMembersAddDTO oldObject : oldObjects) {if (oldObject.getId().equals(newObject.getId())) {if (!oldObject.equals(newObject)) {str = this.compare(oldObject, newObject, requestNo, "", str);}oldObjects.remove(oldObject);}}if (CollUtil.isNotEmpty(oldObjects)) {for (PassportFamilyMembersAddDTO oldObject : oldObjects) {str = this.compare(oldObject, new PassportFamilyMembersAddDTO(), requestNo, "删除家庭成员:", str);}}}}}}return str;}}

相关文章:

AOP操作日志记录

AOP操作日志记录 1.创建注解 Retention(RetentionPolicy.RUNTIME) Target(ElementType.METHOD) public interface PassportLog {String operatePage();String operateType();ClassTypEnum classType();}2.创建切面 对于字典&#xff0c;可以通过注解属性去转换&#xff0c;枚举…...

Linux C语言 42-进程间通信IPC之网络通信(套接字)

Linux C语言 42-进程间通信IPC之网络通信&#xff08;套接字&#xff09; 本节关键字&#xff1a;C语言 进程间通信 网络通信 套接字 TCP UDP 相关库函数&#xff1a;socket、bind、listen、accept、send、recv、sendto、recvfrom 参考之前的文章 Linux C语言 30-套接字操作…...

微服务知识大杂烩

1.什么是微服务? 微服务(Microservices)是一种软件架构风格,将一个大型应用程序划分为一组小型、自治且松耦合的服务。每个微服务负责执行特定的业务功能,并通过轻量级通信机制(如HTTP)相互协作。每个微服务可以独立开发、部署和扩展,使得应用程序更加灵活、可伸缩和可…...

记录一次vscode markdown的图片路径相关插件学习配置过程

插件及说明查找过程 csdn搜索markdown图片路径&#xff0c;找到关于这一款插件的回答。打开vscode拓展搜索Paste Image这款插件&#xff0c;看到下载量挺高的&#xff0c;应该不赖。 点击仓库,进入该插件开源的github仓库,查看README文件阅读说明. 淡然在Vscode 插件项目下的细…...

设计原则 | 依赖转置原则

一、依赖转置原则&#xff08;DIP&#xff1a;Dependence Inversion Principle&#xff09; 1、原理 高层模块不应该依赖低层模块&#xff0c;二者都应该依赖于抽象抽象不应该依赖于细节&#xff0c;细节应该依赖于抽象 2、层次化 Booch曾经说过&#xff1a;所有结构良好的面…...

前端开发实用技巧与经验分享

导语&#xff1a;在前端开发领域&#xff0c;掌握一些实用的技巧和经验可以帮助你更高效地完成任务。本文将分享一些前端开发的实用技巧和经验&#xff0c;帮助你在工作中更好地应对各种挑战。 一、使用开发者工具进行调试和优化 熟练掌握浏览器开发者工具的使用&#xff0c;…...

推荐一款Excel快速加载SQL的插件,方便又好用

如果告诉你只需要双击一下&#xff0c;SQL数据库中存放在表里面的数据&#xff0c;就能加载到你的Excel中&#xff0c;你想不想要&#xff1f; 今天给大家推荐一款好用的Excel插件&#xff0c;安装简单&#xff0c;使用方便&#xff0c;是经常使用SQL数据库的不二。 这款插件…...

Docker快速入门(docker加速,镜像,容器,数据卷常见命令操作整理)

Docker本质是将代码所需的环境依赖进行打包运行,而在Docker中最重要的是镜像和容器 镜像:可以简单地理解为每启动一个docker镜像就会占用计算机一个进程,这个进程和另外起的docker镜像的进程是相互独立的,以数据库为例,每个镜像都会copy一份数据库,在他所在的进程中.别的镜像在…...

http和https的区别有哪些

目录 HTTP&#xff08;HyperText Transfer Protocol&#xff09; HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09; 区别与优势 应用场景 未来趋势 当我们浏览互联网时&#xff0c;我们经常听到两个常用的协议&#xff1a;HTTP&#xff08;HyperText Tra…...

使用Keil-MDK生成*.bin格式可执行文件

使用Keil-MDK生成*.bin格式可执行文件 文章目录 使用Keil-MDK生成*.bin格式可执行文件前言一、fromelf.exe工具二、使用方法1.配置输出2.输出格式 前言 在使用Keil MDK的集成开发环境中&#xff0c;默认情况下可以生成*.axf格式的调试文件和*.hex格式的可执行文件。虽然文件可…...

基于springboot+vue篮球联盟管理系统源码

&#x1f345; 简介&#xff1a;500精品计算机源码学习 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 文末获取源码 目录 一、以下学习内容欢迎交流&#xff1a; 二、文档资料截图&#xff1a; 三、项目技术栈 四、项目运行图 背景&#xff1a; 篮球运…...

分页助手入门以及小bug,报sql语法错误

导入坐标 5版本以上的分页助手 可以不用手动指定数据库语言&#xff0c;它会自动识别 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.2</version> </dependency&g…...

Java中的并发编程:深入理解CountDownLatch

Java中的并发编程&#xff1a;深入理解CountDownLatch 本文将深入探讨Java中的并发编程&#xff0c;重点关注CountDownLatch的使用。通过理解这些概念和技术&#xff0c;我们可以编写出更高效、稳定的Java程序。 一、CountDownLatch简介 CountDownLatch是Java中的一个同步工具…...

Windows 安装 flash-attention 和 bitsandbytes

首先保证cuda版本为12.1&#xff0c;torch版本为2.1.0及以上&#xff0c;python版本3.10以上 从此处下载最新版的whl&#xff0c;https://github.com/jllllll/bitsandbytes-windows-webui/releases/tag/wheels&#xff0c;通过whl来安装bitsandbytes 从此处下载最新版的whl&a…...

AHB 与 DMA

AHB&#xff08;先进高性能总线&#xff09; 随着深亚微米工艺技术日益成熟&#xff0c;集成电路芯片的规模越来越大。数字IC从基于时序驱动的设计方法&#xff0c;发展到基于IP核复用的设计方法&#xff0c;并在SOC设计中得到了广泛应用。在基于IP核复用的SoC&#xff08;Syst…...

React使用echarts并且修改echarts图大小

React使用echarts 引入 npm install --save echarts-for-react npm install --save echarts使用 <ReactEChartsoption{option}notMerge{true}lazyUpdate{true}style{{"width": "100%","height": "800px"}}theme{"theme_nam…...

【Q6-30min】

1. ifndef/define/endif的作用&#xff1a;避免头文件被重复引用。 2.堆栈溢出主要的原因是&#xff1a; &#xff08;1&#xff09;函数调用层次太深。函数递归调用时&#xff0c;系统要在栈中不断保存函数调用时的现场和产生的变量&#xff0c;如果递归调用太深&#xff0c;…...

C++之类和对象(下)

目录 初始化列表 static成员 C11对于非静态成员变量初始化 友元 友元函数 友元类 总结 初始化列表 我们知道&#xff0c;在学习构造函数时&#xff0c;我们知道对象的成员变量的初始化我们是在构造函数函数体内进行初始化的&#xff0c;还有没有其它初始化成员变量的方…...

微服务开发:断路器详解

微服务是目前业界使用的最重要的实现方面。通过使用微服务架构&#xff0c;开发人员可以消除他们以前在单体应用程序中遇到的许多问题。展望未来&#xff0c;人们开始在微服务中搜索和采用各种模式。大多数时候&#xff0c;新模式的产生是为了解决另一个模式中出现的常见问题。…...

Leetcode—383.赎金信【简单】

2023每日刷题&#xff08;五十&#xff09; Leetcode—383.赎金信 实现代码 class Solution { public:int arr[26] {0};int arr2[26] {0};bool canConstruct(string ransomNote, string magazine) {int len ransomNote.size();int len2 magazine.size();for(int i 0; i …...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...

Linux操作系统共享Windows操作系统的文件

目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项&#xff0c;设置文件夹共享为总是启用&#xff0c;点击添加&#xff0c;可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download&#xff08;这是我共享的文件夹&#xff09;&…...

用鸿蒙HarmonyOS5实现国际象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的国际象棋小游戏的完整实现代码&#xff0c;使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├── …...