Spring AOP实现操作日志记录示例

1. 准备工作

项目环境:jdk8+springboot2.6.13+mysql8

1.1 MySQL表

/*Navicat Premium Data TransferSource Server         : localhostSource Server Type    : MySQLSource Server Version : 50730Source Host           : 127.0.0.1:3306Source Schema         : testTarget Server Type    : MySQLTarget Server Version : 50730File Encoding         : 65001Date: 04/07/2024 17:50:35
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for operation_log
-- ----------------------------
DROP TABLE IF EXISTS `operation_log`;
CREATE TABLE `operation_log`  (`id` bigint(20) NOT NULL AUTO_INCREMENT,`module_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`operation_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`method_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`args` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL,`ip_addr` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`create_time` datetime NOT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Table structure for tb_seller
-- ----------------------------
DROP TABLE IF EXISTS `tb_seller`;
CREATE TABLE `tb_seller`  (`sellerid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`nickname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`status` int(11) NOT NULL,`address` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`createtime` datetime NOT NULL,PRIMARY KEY (`sellerid`) USING BTREE,UNIQUE INDEX `name`(`name`, `status`, `address`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;

1.2 项目目录结构

新建一个springboot项目,项目目录结构如下:
在这里插入图片描述

1.3 maven依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.spring</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>spring-demo</name><description>spring-demo</description><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.6.13</spring-boot.version></properties><dependencies><!-- web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- MySQL JDBC --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.13</version></dependency><!-- mybatis-plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4</version></dependency><!-- hutool --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.6.6</version></dependency><!-- spring-aop --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
</project>

1.4 项目配置文件

配置文件application.yml

spring:datasource:username: rootpassword: xxxxdriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=falsemvc:pathmatch:matching-strategy: ant_path_matcher # 路径匹配mybatis-plus:configuration:#配置该类sql只会在控制台打印,不会输出到日志文件log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

1.5 domain层

TbSeller

package com.spring.demo.domain.po;import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;/*** <p>* * </p>** @author Sakura* @since 2024-07-03*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_seller")
@ToString
public class TbSeller implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "sellerid", type = IdType.AUTO)private String sellerid;private String name;private String nickname;private String password;private Integer status;private String address;private LocalDateTime createtime;}

OperationLog

package com.spring.demo.domain.po;import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;/*** <p>* 操作日志实体类,用于记录每个请求的详细信息。* </p>** @author Sakura* @since 2024-07-03*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@Builder
@TableName("operation_log")
@ToString
public class OperationLog implements Serializable {private static final long serialVersionUID = 1L;/*** 日志记录的主键ID,自动递增。*/@TableId(value = "id", type = IdType.AUTO)private Long id;/*** 模块名称,表示在哪个模块执行了操作。*/private String moduleName;/*** 操作名称,表示执行了什么操作。*/private String operationName;/*** 请求方法类型(GET, POST, PUT, DELETE等)。*/private String methodType;/*** 请求的URL地址。*/private String url;/*** 请求的参数,记录请求时传递的参数信息。*/private String args;/*** 请求的IP地址,记录请求的来源IP。*/private String ipAddr;/*** 创建时间,记录请求的时间。*/private LocalDateTime createTime;
}

1.6 controller层

TbSellerController

/*** <p>* 前端控制器* </p>** @author Sakura* @since 2024-07-03*/
@RestController
@RequestMapping("/tb-seller")
@RequiredArgsConstructor
public class TbSellerController {private final ITbSellerService tbSellerService;/*** 获取供应商信息*/@GetMapping("/getById/{id}")@MyLog(moduleName = "供应商模块", operationName = "获取供应商信息")public TbSeller getTbSellerById(@PathVariable String id) {return tbSellerService.getTbSellerById(id);}
}

1.7 service层

ITbSellerService

package com.spring.demo.service;import com.spring.demo.domain.po.TbSeller;
import com.baomidou.mybatisplus.extension.service.IService;/*** <p>*  服务类* </p>** @author Sakura* @since 2024-07-03*/
public interface ITbSellerService extends IService<TbSeller> {TbSeller getTbSellerById(String id);
}

TbSellerServiceImpl

package com.spring.demo.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spring.demo.domain.po.OperationLog;
import com.spring.demo.domain.po.TbSeller;
import com.spring.demo.mapper.TbSellerMapper;
import com.spring.demo.service.IOperationLogService;
import com.spring.demo.service.ITbSellerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;import java.util.List;/*** <p>* 服务实现类* </p>** @author Sakura* @since 2024-07-03*/
@Service
@Slf4j
@RequiredArgsConstructor
public class TbSellerServiceImpl extends ServiceImpl<TbSellerMapper, TbSeller> implements ITbSellerService {private final TbSellerMapper tbSellerMapper;@Overridepublic TbSeller getTbSellerById(String id) {return this.lambdaQuery().eq(TbSeller::getSellerid,id).one();}
}

IOperationLogService

package com.spring.demo.service;import com.spring.demo.domain.po.OperationLog;
import com.baomidou.mybatisplus.extension.service.IService;/*** <p>*  服务类* </p>** @author Sakura* @since 2024-07-03*/
public interface IOperationLogService extends IService<OperationLog> {}

OperationLogServiceImpl

package com.spring.demo.service.impl;import com.spring.demo.domain.po.OperationLog;
import com.spring.demo.mapper.OperationLogMapper;
import com.spring.demo.service.IOperationLogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spring.demo.service.ITbSellerService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;/*** <p>*  服务实现类* </p>** @author Sakura* @since 2024-07-03*/
@Service
@RequiredArgsConstructor
public class OperationLogServiceImpl extends ServiceImpl<OperationLogMapper, OperationLog> implements IOperationLogService {}

1.8 mapper层

TbSellerMapper

import com.spring.demo.domain.po.TbSeller;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/*** <p>*  Mapper 接口* </p>** @author Sakura* @since 2024-07-03*/
public interface TbSellerMapper extends BaseMapper<TbSeller> {/*** 根据sellerid查询*/TbSeller getTbSellerById(String sellerid);
}

OperationLogMapper

package com.spring.demo.mapper;import com.spring.demo.domain.po.OperationLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/*** <p>*  Mapper 接口* </p>** @author Sakura* @since 2024-07-03*/
public interface OperationLogMapper extends BaseMapper<OperationLog> {}

1.9 util包

package com.spring.demo.util;import javax.servlet.http.HttpServletRequest;/*** @author:* @date 2024-07-03 17:23*/
public class IpUtil {/*** 获取ip地址*/public static String getIpAddr(HttpServletRequest request) {String ip = request.getHeader("x-forwarded-for");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;}
}

1.10 启动类

package com.spring.demo;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@SpringBootApplication
@MapperScan(basePackages = "com.spring.demo.mapper")
public class SpringDemoApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(SpringDemoApplication.class, args);System.out.println();}}

2. AOP配置

2.1 开启AOP代理

在启动类上添加注解@EnableAspectJAutoProxy开启AOP代理。

2.2 定义日志注解

在aop包下新建注解MyLog

package com.spring.demo.aop;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义注解:实现登录日志记录*/
@Retention(RetentionPolicy.RUNTIME) // 运行时生效
@Target(ElementType.METHOD) // 作用在方法上
public @interface MyLog {/*** 模块名称*/String moduleName() default "";/*** 操作名称*/String operationName() default "";}

2.3 定义切面类

在aop包下定义切面类

package com.spring.demo.aop;import com.spring.demo.domain.po.OperationLog;
import com.spring.demo.service.IOperationLogService;
import com.spring.demo.util.IpUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.stream.Collectors;/*** 日志切面类** @author: * @date 2024-07-03 16:30*/
@Slf4j
@Component
@Aspect
@RequiredArgsConstructor
public class MyAspect {private final IOperationLogService operationLogService;@AfterReturning("@annotation(com.spring.demo.aop.MyLog)")public void afterReturningMethod(JoinPoint joinPoint) {// 获取被增强类和方法的信息Signature signature = joinPoint.getSignature();MethodSignature methodSignature = (MethodSignature) signature;// 获取被增强的方法对象Method method = methodSignature.getMethod();String moduleName = "";   // 模块名称String operationName = "";    // 操作名称// 从方法中解析注解MyLog myLog = null;if (method != null) {myLog = method.getAnnotation(MyLog.class);moduleName = myLog.moduleName();operationName = myLog.operationName();}// 通过工具类获取Request对象RequestAttributes reqa = RequestContextHolder.getRequestAttributes();ServletRequestAttributes sra = (ServletRequestAttributes) reqa;HttpServletRequest request = sra.getRequest();// 请求方式String methodType = request.getMethod();// 请求地址String url = request.getRequestURI().toString();// 请求参数String args = Arrays.stream(joinPoint.getArgs()).map(Object::toString).collect(Collectors.joining(","));// 登录IPString ipAddr = IpUtil.getIpAddr(request);// 请求时间LocalDateTime createTime = LocalDateTime.now();// 打印日志log.info("moduleName:{}, operationName:{}, methodType:{}, url:{}, args:{}, ipAddr:{}, createTime:{}",moduleName, operationName, methodType, url, args, ipAddr, createTime);// 保存日志OperationLog operationLog = OperationLog.builder().moduleName(moduleName).operationName(operationName).methodType(methodType).url(url).args(args).ipAddr(ipAddr).createTime(createTime).build();operationLogService.save(operationLog);}}

2.4 日志注解使用

修改TbSellerController,在方法上添加MyLog注解

    /*** 获取供应商信息*/@GetMapping("/getById/{id}")@MyLog(moduleName = "供应商模块", operationName = "获取供应商信息")public TbSeller getTbSellerById(@PathVariable String id) {return tbSellerService.getTbSellerById(id);}

3.测试

启动springboot项目,访问路径:http://localhost:8080/tb-seller/getById/baidu
控制台输出如下:

JDBC Connection [HikariProxyConnection@130007367 wrapping com.mysql.cj.jdbc.ConnectionImpl@116246bc] will not be managed by Spring
==>  Preparing: SELECT s.sellerid AS sellerid, s.name AS name, s.nickname AS nickname, s.password AS password, s.status AS status, s.address AS address, s.createtime AS createtime, s.uid AS uid FROM tb_seller s where s.sellerid = ?;
==> Parameters: baidu(String)
<==    Columns: sellerid, name, nickname, password, status, address, createtime, uid
<==        Row: baidu, 百度科技有限公司, 百度小店, e10adc3949ba59abbe56e057f20f883e, 1, 北京市, 2088-01-01 12:00:00, 1
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@118dd810]
2024-07-04 18:25:54.559  INFO 251072 --- [nio-8080-exec-1] com.spring.demo.aop.MyAspect             : moduleName:供应商模块, operationName:获取供应商信息, methodType:GET, url:/tb-seller/getById/baidu, args:baidu, ipAddr:127.0.0.1, createTime:2024-07-04T18:25:54.559
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1416af2f] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@136495746 wrapping com.mysql.cj.jdbc.ConnectionImpl@116246bc] will not be managed by Spring
==>  Preparing: INSERT INTO operation_log ( module_name, operation_name, method_type, url, args, ip_addr, create_time ) VALUES ( ?, ?, ?, ?, ?, ?, ? )
==> Parameters: 供应商模块(String), 获取供应商信息(String), GET(String), /tb-seller/getById/baidu(String), baidu(String), 127.0.0.1(String), 2024-07-04T18:25:54.559(LocalDateTime)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1416af2f]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/41326.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

双扩散金属氧化物半导体(DMOS)应用广泛 超结VDMOS市场需求空间大

双扩散金属氧化物半导体&#xff08;DMOS&#xff09;应用广泛 超结VDMOS市场需求空间大 双扩散金属氧化物半导体简称DMOS&#xff0c;是MOS管的一种。MOS管全称为金属氧化物半导体场效应管&#xff0c;又称为MOSFET&#xff0c;是一种利用改变电压来控制电流的半导体器件。  …

《梦醒蝶飞:释放Excel函数与公式的力量》8.8 STDEVP函数

8.8 STDEVP函数 STDEVP函数是Excel中用于计算总体数据的标准偏差的函数。标准偏差是统计学中的一个重要指标&#xff0c;用于衡量数据集中各数值偏离平均值的程度。总体标准偏差考虑了整个数据集&#xff0c;而不是样本。 8.8.1 函数简介 STDEVP函数用于返回总体数据的标准偏…

Redis 中的通用命令(命令的返回值、复杂度、注意事项及操作演示)

Redis 中的通用命令(高频率操作) 文章目录 Redis 中的通用命令(高频率操作)Redis 的数据类型redis-cli 命令Keys 命令Exists 命令Expire 命令Ttl 命令Type命令 Redis 的数据类型 Redis 支持多种数据类型&#xff0c;整体来说&#xff0c;Redis 是一个键值对结构的&#xff0c;…

第N7周:seq2seq翻译实战-pytorch复现-小白版

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 理论基础 seq2seq&#xff08;Sequence-to-Sequence&#xff09;模型是一种用于机器翻译、文本摘要等序列转换任务的框架。它由两个主要的递归神经网络&#…

【leetcode】双指针算法题

文章目录 1.算法思想2.移动零3.复写零方法一方法二 4.快乐数5.盛水最多的容器方法一&#xff08;暴力求解&#xff09;方法二&#xff08;左右指针&#xff09; 6.有效三角形的个数方法一&#xff08;暴力求解&#xff09;方法二&#xff08;左右指针&#xff09; 7.两数之和8.…

CNN文献综述

卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;简称CNN&#xff09;是深度学习领域中的一种重要模型&#xff0c;主要用于图像识别和计算机视觉任务。其设计灵感来自于生物学中视觉皮层的工作原理&#xff0c;能够高效地处理图像和语音等数据。 基本原理…

UVa1265/LA4848 Tour Belt

UVa1265/LA4848 Tour Belt 题目链接题意分析AC 代码 题目链接 本题是2010年icpc亚洲区域赛大田赛区的F题 题意 给出一个有n个结点m条边的加权无向图G&#xff08;2≤n≤5000&#xff0c;1≤m≤n(n-1)/2&#xff09;&#xff0c;满足如下条件的结点集B&#xff08;2≤|B|≤n&am…

剪画小程序:手机制作音乐串烧,用它,真的很简单!

Hello&#xff0c;大家好呀&#xff0c;我是不会画画的小画。 相伴关注歌手的小伙伴们&#xff0c;上周五的《歌手 2024》第八期大家看了吧&#xff01;那期节目里有好几首歌都让我沉醉其中&#xff0c;像汪苏泷的《听见下雨的声音》、谭维维的《兰花花儿》等等。 为了能让大…

c++之旅第十一弹——顺序表

大家好啊&#xff0c;这里是c之旅第十一弹&#xff0c;跟随我的步伐来开始这一篇的学习吧&#xff01; 如果有知识性错误&#xff0c;欢迎各位指正&#xff01;&#xff01;一起加油&#xff01;&#xff01; 创作不易&#xff0c;希望大家多多支持哦&#xff01; 一,数据结构…

基于docker环境及Harbor部署{很简短一点了,耐心看吧}

用到的环境&#xff1a; docker 、nacos、compose、harbor&#xff08;自行安装 ,以下连接作为参考&#xff09; nacos&#xff1a;史上最全整合nacos单机模式整合哈哈哈哈哈_nacos 源码启动 单机模式-CSDN博客 docker、compose、harbor:史上最全的整合Harbor安装教程&#…

数据结构之顺序表专题

在学习数据结构之前我们要先了解什么是数据结构&#xff1f; 1.数据结构相关概念 1.什么是数据结构&#xff1f; 数据结构是由“数据”和“结构”两词组合而来。 什么是数据?常见的数值1、2、3、4.、教务系统里保存的用户信息(姓名、性别、年龄、学历等等)、网页里肉眼可以…

TensorBoard进阶

文章目录 TensorBoard进阶1.设置TensorBoard2.图像数据在TensorBoard中可视化3.模型结构在TensorBoard中可视化&#xff08;重点✅&#xff09;4.高维数据在TensorBoard中低维可视化5.利用TensorBoard跟踪模型的训练过程&#xff08;重点✅&#xff09;6.利用TensorBoard给每个…

complex复数库学习

此头文件是数值库的一部分。本篇介绍complex的基本用法。 常用的API如下&#xff1a; 运算 real 返回实部 (函数模板) imag 返回虚部 (函数模板) abs(std::complex) 返回复数的模 (函数模板) arg 返回辐角 (函数模板) norm 返回模(范数)的平方 (函数模板) conj 返回复共轭 (函…

桌面保存的Word文件删除怎么找回?超实用的三个方法?

在日常工作和学习中&#xff0c;我们经常会使用Word文档进行文字编辑和文件保存。但是&#xff0c;有时由于操作失误或系统故障&#xff0c;我们会不小心将存放在电脑桌面重要的Word文件删除了。导致无法挽回的损失&#xff0c;但幸运的是&#xff0c;有一些方法可以帮助我们找…

源代码防泄漏的制胜法宝——沙箱

沙箱技术作为现代信息安全领域的一种重要手段&#xff0c;其在源代码防泄密方面的应用愈发受到业界的关注。源代码作为企业或组织的核心资产&#xff0c;一旦泄露&#xff0c;不仅可能导致知识产权的流失&#xff0c;还可能对企业运营造成重大影响。因此&#xff0c;利用沙箱技…

跨境干货|最新注册Google账号方法分享

谷歌账号对做跨境外贸业务的人来说是刚需&#xff0c;目前来说大部分的海外社媒平台、工具都可以用谷歌账号来注册。但是仍然有很多朋友并不知道如何注册这个谷歌账号&#xff0c;今天就来给大家分享2个注册谷歌账号的方法&#xff0c;一个是手机号注册&#xff0c;一个是如何跳…

面向对象案例:电影院

TOC 思路 代码 结构 具体代码 Movie.java public class Movie {//一共七个private int id;private String name;private double price;private double score;private String director;private String actors;private String info;//get和setpublic int getId() {return id;…

opencv概念以及安装方法

#opencv相关概念介绍 Open Source Computer Vision Library 缩写 opencv 翻译&#xff1a;开源的计算机视觉库 &#xff0c;英特尔公司发起并开发&#xff0c;支持多种编程语言&#xff08;如C、Python、Java等&#xff09;&#xff0c;支持计算机视觉和机器学习等众多算法&a…

如何让自动化测试更加灵活简洁?

简化的架构对于自动化测试和主代码一样重要。冗余和不灵活性可能会导致一些问题&#xff1a;比如 UI 中的任何更改都需要更新多个文件&#xff0c;测试可能在功能上相互重复&#xff0c;并且支持新功能可能会变成一项耗时且有挑战性的工作来适应现有测试。 页面对象模式如何理…

DataWhale-吃瓜教程学习笔记 (七)

学习视频**&#xff1a;第6章-支持向量机_哔哩哔哩_bilibili 西瓜书对应章节&#xff1a; 第六章 支持向量机 - 算法原理 几何角度 对于线性可分数据集&#xff0c;找距离正负样本距离都最远的超平面&#xff0c;解是唯一的&#xff0c;泛化性能较好 - 超平面 - 几何间隔 例…