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.创建切面 对于字典,可以通过注解属性去转换,枚举…...
Linux C语言 42-进程间通信IPC之网络通信(套接字)
Linux C语言 42-进程间通信IPC之网络通信(套接字) 本节关键字:C语言 进程间通信 网络通信 套接字 TCP UDP 相关库函数:socket、bind、listen、accept、send、recv、sendto、recvfrom 参考之前的文章 Linux C语言 30-套接字操作…...
微服务知识大杂烩
1.什么是微服务? 微服务(Microservices)是一种软件架构风格,将一个大型应用程序划分为一组小型、自治且松耦合的服务。每个微服务负责执行特定的业务功能,并通过轻量级通信机制(如HTTP)相互协作。每个微服务可以独立开发、部署和扩展,使得应用程序更加灵活、可伸缩和可…...
记录一次vscode markdown的图片路径相关插件学习配置过程
插件及说明查找过程 csdn搜索markdown图片路径,找到关于这一款插件的回答。打开vscode拓展搜索Paste Image这款插件,看到下载量挺高的,应该不赖。 点击仓库,进入该插件开源的github仓库,查看README文件阅读说明. 淡然在Vscode 插件项目下的细…...
设计原则 | 依赖转置原则
一、依赖转置原则(DIP:Dependence Inversion Principle) 1、原理 高层模块不应该依赖低层模块,二者都应该依赖于抽象抽象不应该依赖于细节,细节应该依赖于抽象 2、层次化 Booch曾经说过:所有结构良好的面…...
前端开发实用技巧与经验分享
导语:在前端开发领域,掌握一些实用的技巧和经验可以帮助你更高效地完成任务。本文将分享一些前端开发的实用技巧和经验,帮助你在工作中更好地应对各种挑战。 一、使用开发者工具进行调试和优化 熟练掌握浏览器开发者工具的使用,…...
推荐一款Excel快速加载SQL的插件,方便又好用
如果告诉你只需要双击一下,SQL数据库中存放在表里面的数据,就能加载到你的Excel中,你想不想要? 今天给大家推荐一款好用的Excel插件,安装简单,使用方便,是经常使用SQL数据库的不二。 这款插件…...
Docker快速入门(docker加速,镜像,容器,数据卷常见命令操作整理)
Docker本质是将代码所需的环境依赖进行打包运行,而在Docker中最重要的是镜像和容器 镜像:可以简单地理解为每启动一个docker镜像就会占用计算机一个进程,这个进程和另外起的docker镜像的进程是相互独立的,以数据库为例,每个镜像都会copy一份数据库,在他所在的进程中.别的镜像在…...
http和https的区别有哪些
目录 HTTP(HyperText Transfer Protocol) HTTPS(HyperText Transfer Protocol Secure) 区别与优势 应用场景 未来趋势 当我们浏览互联网时,我们经常听到两个常用的协议:HTTP(HyperText Tra…...
使用Keil-MDK生成*.bin格式可执行文件
使用Keil-MDK生成*.bin格式可执行文件 文章目录 使用Keil-MDK生成*.bin格式可执行文件前言一、fromelf.exe工具二、使用方法1.配置输出2.输出格式 前言 在使用Keil MDK的集成开发环境中,默认情况下可以生成*.axf格式的调试文件和*.hex格式的可执行文件。虽然文件可…...
基于springboot+vue篮球联盟管理系统源码
🍅 简介:500精品计算机源码学习 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 文末获取源码 目录 一、以下学习内容欢迎交流: 二、文档资料截图: 三、项目技术栈 四、项目运行图 背景: 篮球运…...
分页助手入门以及小bug,报sql语法错误
导入坐标 5版本以上的分页助手 可以不用手动指定数据库语言,它会自动识别 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.2</version> </dependency&g…...
Java中的并发编程:深入理解CountDownLatch
Java中的并发编程:深入理解CountDownLatch 本文将深入探讨Java中的并发编程,重点关注CountDownLatch的使用。通过理解这些概念和技术,我们可以编写出更高效、稳定的Java程序。 一、CountDownLatch简介 CountDownLatch是Java中的一个同步工具…...
Windows 安装 flash-attention 和 bitsandbytes
首先保证cuda版本为12.1,torch版本为2.1.0及以上,python版本3.10以上 从此处下载最新版的whl,https://github.com/jllllll/bitsandbytes-windows-webui/releases/tag/wheels,通过whl来安装bitsandbytes 从此处下载最新版的whl&a…...
AHB 与 DMA
AHB(先进高性能总线) 随着深亚微米工艺技术日益成熟,集成电路芯片的规模越来越大。数字IC从基于时序驱动的设计方法,发展到基于IP核复用的设计方法,并在SOC设计中得到了广泛应用。在基于IP核复用的SoC(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的作用:避免头文件被重复引用。 2.堆栈溢出主要的原因是: (1)函数调用层次太深。函数递归调用时,系统要在栈中不断保存函数调用时的现场和产生的变量,如果递归调用太深,…...
C++之类和对象(下)
目录 初始化列表 static成员 C11对于非静态成员变量初始化 友元 友元函数 友元类 总结 初始化列表 我们知道,在学习构造函数时,我们知道对象的成员变量的初始化我们是在构造函数函数体内进行初始化的,还有没有其它初始化成员变量的方…...
微服务开发:断路器详解
微服务是目前业界使用的最重要的实现方面。通过使用微服务架构,开发人员可以消除他们以前在单体应用程序中遇到的许多问题。展望未来,人们开始在微服务中搜索和采用各种模式。大多数时候,新模式的产生是为了解决另一个模式中出现的常见问题。…...
Leetcode—383.赎金信【简单】
2023每日刷题(五十) 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 …...
爬虫-xpath篇
1.xpath的基础语法 表达式描述nodename选中该元素/从根节点选取、或者是元素和元素间的过渡//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置.选取当前节点…选取当前节点的父节点选取属性text()选取文本 举例: 路径表达式结果html选择html元…...
Oracle初始化参数文件pfile和spfile
pfile :Oracle 9i之前,ORACLE一直采用PFILE方式存储初始化参数,该文件为文本文件,可以在操作系统级别修改。当spfile文件修改出现错误导致oracle无法启动时,可以使用 pfile文件启动数据库 spfile:从Oracle…...
zookeeper 客户端常用命令简单记录(实操课程系列--watcher功能测试)(发布订阅功能测试)
本系列是zookeeper相关的实操课程,课程测试环环相扣,请按照顺序阅读测试来学习zookeeper。阅读本文之前,请先阅读----zookeeper 单机伪集群搭建简单记录(实操课程系列) 1、命令行工具切换到zookeeper的bin目录下面&am…...
Scrapy爬虫数据存储为JSON文件的解决方案
什么是JSON文件 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人们阅读和编写,同时也易于机器解析和生成。它基于JavaScript Spark语言的一个子集,但独立于Smashing语言,因此在许多中…...
计算机设计大赛 选题推荐
0 前言 比赛介绍 中国大学生计算机设计大赛是中国高等教育学会“全国普通高校大学生竞赛排行榜”竞赛之一。自2008年开赛至2019年,一直由教育部高校与计算机相关教指委等或独立或联合主办。2023年(第16届)中国大学生计算机设计大赛是由、中…...
基于springboot,vue高校图书馆管理系统
开发工具:IDEA 服务器:Tomcat9.0, jdk1.8 项目构建:gradle-5.6.4 数据库:mysql5.7 系统分前后台,项目采用前后端分离 前端技术:vueelementUI 服务端技术:springbootmybatisred…...
如何打造更高效、安全、灵活的企业网络组网方案
随着互联网的快速发展,企业对于网络的需求也变得越来越高。然而,企业规模不断扩大,分布式办公越来越普遍,如何保证数据安全传输和网络稳定运行是每一家企业都需要面对的问题。因此,合理构建企业组网架构已经成为了现代…...
MATLAB Simulink +STM32硬件在环 (HIL)实现例程测试
MATLAB Simulink STM32硬件在环 (HIL)实现例程测试 📍相关篇《STM32CubeMxMATLAB Simulink点灯程序》✨本例程没有使用到STM32CubeMX来创建工程(在Simulink 中不是选择的STM32xxxbased类型的)。 🔖STM32xxx…...
Kubernetes Service控制器详解以及切换为ipvs代理模式
文章目录 一、Service 存在的意义二、Pod与Service的关系三、Service定义与创建四、Service三种常用类型五、Service代理模式六、切换Service代理模式七、service总体工作流程八、kube-proxy ipvs和iptables的异同九、Service DNS名称 一、Service 存在的意义 service的引入主…...
搭建samba服务
公司内部需要文件共享,自建samba服务,满足功能 在搭建过程中,踩了一些坑,如windows无法访问、macos无法访问、账号添加、权限控制 分享一下实现过程,内容不详细的地方,可评论或私聊 前置准备 服务器 阿里…...
证书兼职的正规平台哪里有/seo模拟点击软件源码
采用Mysqldump备份 相当于读出数据然后导出,这个过程禁止非读操作,因此,加锁读取。 1. 刷新数据库并加锁 FLUSH TABLES WITH READ LOCK; 2. 新开一个会话,执行导出 mysqldump -u root -p sakila > sakila-backup.sql 3. 原会…...
东莞茶山网站建设/百度关键词首页排名怎么上
最近推荐一位日本女明星——石原里美 封面就是其本人 有颜有才 笑起来真的很好看了 希望大家能与我一起欣赏她的美 啊哈哈哈哈哈哈哈哈 补一句:我不是超级无敌屌丝猥琐男哈!!! 给定一个可能包含重复元素的整数数组 nums&…...
龙岩装修公司/seo外包网站
获取文件 常用日志路径 /var/log/message //系统信息日志 /var/log/secure //系统登录日志 /var/log/cron //定时任务日志 /var/log/maillog //邮件日志 /var/log/boot.log //系统启动日志 查看日志 常用命令 tail:查看后多少行日志-n 显示行号(nl)tail -100f test.…...
彩票自己开盘做网站/谷歌关键词挖掘工具
通过MYSQL查询语句动态的显示图表一、在官网上下载对应的组件,四者均可,并倒入到项目的JS包下二、写MYSQL语句并查询的数量num和名称nameSELECT s.peopleNums,r.name from statistics as s,readrooms as r where s.ReadRoomID r.ID GROUP BY s.ReadRoom…...
asp做网站教程/网络营销的特点和优势
Agile testing(敏捷测试)基本上是伴随着敏捷开发的概念成长起来的,但在受关注程度上,远远不及敏捷开发本身。自然,开发队伍从数量和活跃度上来讲大于测试队伍,是其中的一个原因;除了这个原因之外…...
深圳网站制作/肇庆seo外包公司
2019独角兽企业重金招聘Python工程师标准>>> Netty实现安全Socket通信 SSL通信的原理请看:http://my.oschina.net/xinxingegeya/blog/266801 关于netty的编解码器请看:http://asialee.iteye.com/category/257110 netty的ssl通信其实就是在客户…...