8、springboot3 vue3开发平台-后端-使用aop 添加系统访问日志

1. 添加依赖, 创建数据库

		 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!-- IP地址解析 --><dependency><groupId>org.lionsoul</groupId><artifactId>ip2region</artifactId><version>2.6.5</version></dependency>

数据表创建:

CREATE TABLE `sys_log` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',`log_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '日志类型',`create_date` datetime NOT NULL COMMENT '创建时间',`oper_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '操作人员',`request_uri` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '请求URI',`request_type` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '请求方式',`request_params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '请求参数',`request_ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '请求IP',`oper_location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '请求地点',`response_result` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '返回参数',`oper_status` int DEFAULT '0' COMMENT '操作状态(0正常1异常)',`exception_info` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '异常信息',`start_time` datetime DEFAULT NULL COMMENT '开始时间',`end_time` datetime DEFAULT NULL COMMENT '结束时间',`execute_time` bigint DEFAULT NULL COMMENT '执行时间',`user_agent` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '用户代理',`device_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '操作系统',`browser_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '浏览器名称',`module` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '模块名称',`oper_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '操作说明',PRIMARY KEY (`id`) USING BTREE,KEY `idx_sys_log_lt` (`log_type`) USING BTREE,KEY `idx_sys_log_cd` (`create_date`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=716 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='系统日志表';

2. ip2region.xdb 下载使用

使用原因: 内网环境提供离线解析, ip2region.xdb文件,需要不定期的更新
地址: https://gitee.com/lionsoul/ip2region/tree/master/data
使用:下载后将其放到resources 下, 在工具类中加载配置文件
在这里插入图片描述

2.1 工具类封装

package com.ylp.sys.utils;import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;@Component
public class IPUtils {private static Searcher searcher;/*** 在 Nginx 等代理之后获取用户真实 IP 地址* @return 用户的真实 IP 地址*/public static String getIpAddress(HttpServletRequest request) {if (request == null) {return null;}String ip = request.getHeader("x-forwarded-for");if (isIpaddress(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (isIpaddress(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (isIpaddress(ip)) {ip = request.getHeader("HTTP_CLIENT_IP");}if (isIpaddress(ip)) {ip = request.getHeader("HTTP_X_FORWARDED_FOR");}if (isIpaddress(ip)) {ip = request.getRemoteAddr();if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {//根据网卡取本机配置的IPtry {InetAddress inet = InetAddress.getLocalHost();ip = inet.getHostAddress();} catch (UnknownHostException e) {e.printStackTrace();}}}return ip;}/*** 判断是否为 IP 地址* @param ip  IP 地址*/public static boolean isIpaddress(String ip) {return ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip);}/*** 获取本地 IP 地址* @return 本地 IP 地址*/public static String getHostIp() {try {return InetAddress.getLocalHost().getHostAddress();} catch (UnknownHostException e) {e.printStackTrace();}return "127.0.0.1";}/*** 获取主机名* @return 本地主机名*/public static String getHostName() {try {return InetAddress.getLocalHost().getHostName();} catch (UnknownHostException e) {e.printStackTrace();}return "未知";}/*** 根据 IP 地址从 ip2region.db 中获取地理位置* @param ip IP 地址* @return IP归属地*/public static String getCityInfo(String ip) {try {return searcher.search(ip);} catch (Exception e) {e.printStackTrace();}return null;}/*** 在服务启动时加载 ip2region.db 到内存中* 解决打包 jar 后找不到 ip2region.db 的问题* @throws Exception 出现异常应该直接抛出终止程序启动,避免后续 invoke 时出现更多错误*/@PostConstructprivate static void initIp2regionResource() {try {InputStream inputStream = new ClassPathResource("/ipdb/ip2region.xdb").getInputStream();byte[] dbBinStr = FileCopyUtils.copyToByteArray(inputStream);// 创建一个完全基于内存的查询对象searcher = Searcher.newWithBuffer(dbBinStr);} catch (Exception e) {e.printStackTrace();}}/*** 根据 IP 地址返回归属地,国内返回但省份,国外返回到国家* @param ip IP 地址* @return IP 归属地*/public static String getIpRegion(String ip) {initIp2regionResource();HashMap<String, String> cityInfo = new HashMap<>();String searchIpInfo = getCityInfo(ip);//-------------------------------------------------------//searchIpInfo 的数据格式: 国家|区域|省份|城市|ISP//192.168.31.160 0|0|0|内网IP|内网IP//47.52.236.180 中国|0|香港|0|阿里云//220.248.12.158 中国|0|上海|上海市|联通//164.114.53.60 美国|0|华盛顿|0|0//-------------------------------------------------------String[] splitIpInfo = searchIpInfo.split("\\|");cityInfo.put("ip",ip);cityInfo.put("searchInfo", searchIpInfo);cityInfo.put("country",splitIpInfo[0]);cityInfo.put("region",splitIpInfo[1]);cityInfo.put("province",splitIpInfo[2]);cityInfo.put("city",splitIpInfo[3]);cityInfo.put("ISP",splitIpInfo[3]);//--------------国内属地返回省份--------------if ("中国".equals(cityInfo.get("country"))){return cityInfo.get("province");}//------------------内网 IP----------------if ("0".equals(cityInfo.get("country"))){
//            if ("内网IP".equals(cityInfo.get("ISP"))){
//                return "";
//            }
//            else return "";return cityInfo.get("ISP");}//--------------国外属地返回国家--------------else {return cityInfo.get("country");}}}

3. 使用AOP 注册访问日志

3.1 创建注解,用于标注接口

package com.ylp.sys.annotation;import java.lang.annotation.*;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLogAnnotation {String module()  default "";//模块String operDesc() default "";   // 操作说明
}

3.2 创建AOP 配置

package com.ylp.sys.aop;import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ylp.common.response.Result;
import com.ylp.sys.annotation.SysLogAnnotation;
import com.ylp.sys.auth.entity.UserInfo;
import com.ylp.sys.common.SysLogConstant;
import com.ylp.sys.domain.entity.SysLog;
import com.ylp.sys.service.SysLogService;
import com.ylp.sys.utils.IPUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor;/*** 系统日志切面** @author ylp**/
@Aspect
@Component
public class SysLogAspect {private static final Logger logger = LoggerFactory.getLogger(SysLogAspect.class);private ThreadLocal<SysLog> sysLogThreadLocal = new ThreadLocal<>();@Autowiredprivate Executor customThreadPoolTaskExecutor;@Autowiredprivate SysLogService sysLogService;/*** 日志切点*/@Pointcut("execution(public * com.ylp..*controller.*.*(..))")public void sysLogOperAspect() {}@Pointcut("execution(public * com.ylp.sys.auth.controller.*.*(..))")public void sysLogAuthAspect() {}// 定义一个组合切点@Pointcut("sysLogOperAspect() || sysLogAuthAspect()")public void combinedExecution() {}/*** 前置通知** @param joinPoint*/@Before(value = "combinedExecution()")public void doBefore(JoinPoint joinPoint) {//System.out.println("doBefore aop===============joinPoint===="+ joinPoint);try {HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();SysLog sysLog = new SysLog();// 创建人信息请根据实际项目获取方式获取//登录后拿用户信息if(StpUtil.isLogin()) {UserInfo userLoginInfo = (UserInfo) StpUtil.getSession().get("userInfo");sysLog.setOperName(userLoginInfo.getUsername());}sysLog.setStartTime(LocalDateTime.now());sysLog.setRequestUri(URLUtil.getPath(request.getRequestURI()));sysLog.setRequestParams(formatParams(request.getParameterMap()));sysLog.setRequestType(request.getMethod());sysLog.setRequestIp(IPUtils.getIpAddress(request));String userAgentStr = request.getHeader("User-Agent");sysLog.setUserAgent(userAgentStr);UserAgent userAgent = UserAgentUtil.parse(userAgentStr);sysLog.setDeviceName(userAgent.getOs().getName());sysLog.setBrowserName(userAgent.getBrowser().getName());// 获取请求体参数Object[] args = joinPoint.getArgs();for(Object arg : args){try {String jsonString = JSON.toJSONString(arg);JSONObject jsonObject = JSON.parseObject(jsonString);if (jsonObject.containsKey("password")) {jsonObject.put("password", "*****");}System.out.println("参数=" + JSON.toJSONString(jsonObject));sysLog.setRequestParams(sysLog.getRequestParams() + JSON.toJSONString(jsonObject));} catch (Exception e) {//e.printStackTrace();}}// 获取日志注解MethodSignature signature = (MethodSignature)joinPoint.getSignature();SysLogAnnotation annotation = signature.getMethod().getAnnotation(SysLogAnnotation.class);if (annotation != null) {sysLog.setModule(annotation.module());sysLog.setOperDesc(annotation.operDesc());}sysLogThreadLocal.set(sysLog);// System.out.println("doBefore aop111111===============");//          logger.info("开始计时: {}  URI: {}  IP: {}", sysLog.getStartTime(), sysLog.getRequestUri(), sysLog.getRequestIp());} catch (Exception e) {logger.error(e.getMessage());}}/*** 返回通知** @param ret*/@AfterReturning(pointcut = "combinedExecution()", returning = "ret")public void doAfterReturning(Object ret) {// System.out.println("doAfterReturning aop===============");try {SysLog sysLog = sysLogThreadLocal.get();sysLog.setLogType(SysLogConstant.LOG_INGO);sysLog.setEndTime(LocalDateTime.now());sysLog.setExecuteTime(Long.valueOf(ChronoUnit.MILLIS.between(sysLog.getStartTime(), sysLog.getEndTime())));Result<?> r = Convert.convert(Result.class, ret);
//            if (SysLogConstant.TRUE.equals(String.valueOf(r.getCode()))) {if (r.getCode() == 0) {sysLog.setOperStatus(SysLogConstant.OPER_SUCCESS);} else {sysLog.setOperStatus(SysLogConstant.OPER_EXECPTION);sysLog.setExceptionInfo(r.getMessage());}sysLog.setResponseResult(JSON.toJSONString(r));customThreadPoolTaskExecutor.execute(new SaveLogThread(sysLog, sysLogService));sysLogThreadLocal.remove();// Runtime runtime = Runtime.getRuntime();
//            logger.info("计时结束: {}  用时: {}ms  URI: {}  总内存: {}  已用内存: {}", sysLog.getEndTime(), sysLog.getExecuteTime(),
//                    sysLog.getRequestUri(), ByteUtils.formatByteSize(runtime.totalMemory()),
//                    ByteUtils.formatByteSize(runtime.totalMemory() - runtime.freeMemory()));} catch (Exception e) {logger.error(e.getMessage());}}/*** 异常通知** @param e*/@AfterThrowing(pointcut = "combinedExecution()", throwing = "e")public void doAfterThrowable(Throwable e) {try {SysLog sysLog = sysLogThreadLocal.get();sysLog.setLogType(SysLogConstant.LOG_ERROR);sysLog.setEndTime(LocalDateTime.now());sysLog.setExecuteTime(Long.valueOf(ChronoUnit.MINUTES.between(sysLog.getStartTime(), sysLog.getEndTime())));sysLog.setOperStatus(SysLogConstant.OPER_EXECPTION);sysLog.setExceptionInfo(e.getMessage());customThreadPoolTaskExecutor.execute(new SaveLogThread(sysLog, sysLogService));sysLogThreadLocal.remove();//            Runtime runtime = Runtime.getRuntime();
//            logger.info("计时结束: {}  用时: {}ms  URI: {}  总内存: {}  已用内存: {}", sysLog.getEndTime(), sysLog.getExecuteTime(),
//                    sysLog.getRequestUri(), ByteUtils.formatByteSize(runtime.totalMemory()),
//                    ByteUtils.formatByteSize(runtime.totalMemory() - runtime.freeMemory()));} catch (Exception e1) {logger.error(e1.getMessage());}}/*** 格式化参数** @param parameterMap* @return*/private String formatParams(Map<String, String[]> parameterMap) {if (parameterMap == null) {return null;}StringBuilder params = new StringBuilder();for (Map.Entry<String, String[]> param : (parameterMap).entrySet()) {if (params.length() != 0) {params.append("&");}params.append(param.getKey() + "=");if (StrUtil.endWithIgnoreCase(param.getKey(), "password")) {params.append("*");} else if (param.getValue() != null) {params.append(ArrayUtil.join(param.getValue(), ","));}}return params.toString();}/*** 保存日志线程** @author ylp*/private static class SaveLogThread extends Thread {private SysLog sysLog;private SysLogService sysLogService;public SaveLogThread(SysLog sysLog, SysLogService sysLogService) {this.sysLog = sysLog;this.sysLogService = sysLogService;}@Overridepublic void run() {try {sysLog.setCreateDate(LocalDateTime.now());String ipLocation = IPUtils.getIpRegion(sysLog.getRequestIp());logger.info("ip地址{}", ipLocation);sysLog.setOperLocation(ipLocation);sysLogService.save(sysLog);} catch (Exception e) {logger.error(e.getMessage());}}}
}

3.3 配置线程池

将配置放到support 模块下, 后续其他模块也可以直接使用, 开发环境不要将线程数配置到极限,会影响其他应用。

package com.ylp.support.config.thread;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;/*** 线程池配置类** @author ylp**/
@Configuration
public class ThreadPoolTaskExecutorConfig {@Beanpublic Executor customThreadPoolTaskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// Java虚拟机可用的处理器数int corePoolSize = Runtime.getRuntime().availableProcessors();// 配置核心线程数executor.setCorePoolSize(corePoolSize);// 配置最大线程数
//        executor.setMaxPoolSize(corePoolSize * 2 + 1);executor.setMaxPoolSize(corePoolSize + 1);// 配置队列大小executor.setQueueCapacity(100);// 空闲的多余线程最大存活时间executor.setKeepAliveSeconds(3);// 配置线程池中的线程的名称前缀executor.setThreadNamePrefix("thread-execute-");// 当线程池达到最大大小时,在调用者的线程中执行任务executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 执行初始化executor.initialize();return executor;}
}

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

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

相关文章

1000W长连接,如何建立和维护?千万用户IM 架构设计

1000W长连接&#xff0c;如何建立和维护&#xff1f;千万用户IM 架构设计 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的架构类/设计类…

【Vulnhub靶场AI-WEB-1.0打靶教程】

第一步&#xff1a;查看虚拟机的ip 第二步&#xff1a;扫描ip下开放的80端口 第三步&#xff1a;扫描查到的ip地址下的目录 第四步&#xff1a;访问查到的目录 访问robot.txt 第五步:访问robot.txt显示出的目录 第六步&#xff1a;打开kali终端&#xff0c;使用sqlmap功能 sq…

YOLO:训练自己的样本数据集进行目标检测

作者&#xff1a;CSDN _养乐多_ 本文将介绍如何使用python语言和 ultralytics 库训练自己的数据集&#xff0c;并进行 YOLO 目标检测模型训练和推理的代码。 文章目录 一、样本数据集准备1.1 标注工具1.2 数据集格式1.2.1 图片和标签数据集制作1.2.2 data.yaml制作 二、模型训…

canvas根据图片生成粒子动画

canvas根据图片生成粒子动画 效果展示&#xff1a; canvas根据图片生成粒子动画效果 注意&#xff1a; js和css的引入 id&#xff1a; cartoonDot-img对应的是被 拷贝的图像&#xff0c;后期要替换的 粒子图像就在这 min.js 地址 HTML代码块 <!DOCTYPE html> <h…

系统架构师考点--系统架构设计(中)

大家好。今天继续总结一下系统架构设计的一些考点。 一、软件架构复用 软件产品线是指一组软件密集型系统&#xff0c;它们共享一个公共的、可管理的特性集&#xff0c;满足某个特定市场或任务的具体需要&#xff0c;是以规定的方式用公共的核心资产集成开发出来的。即围绕核…

SpringBoot 日志:从基础到高级的全面指南

&#x1f4da; SpringBoot 日志&#xff1a;从基础到高级的全面指南 &#x1f50d; &#x1f4da; SpringBoot 日志&#xff1a;从基础到高级的全面指南 &#x1f50d;摘要引言正文内容一、日志概述 &#x1f4dc;二、日志使用 &#x1f4dd;2.1 打印日志 &#x1f4e3;2.2 日志…

IIS解析漏洞~ IIS7.漏洞分析

IIS解析漏洞 文件解析漏洞是由于中间件错误的将特殊格式的文件解析成可执行网页文件(脚本)&#xff0c;配合文件上传漏洞进行GetShell的漏洞&#xff01; 1.2&#xff1a;IIS7.X 在IIS7.0和IIS7.5版本下也存在解析漏洞&#xff0c;在默认Fast-CGI开启状况下&#xff0c;在一个文…

DM集群的高可用的配置方式(多语言)

一、介绍 强调以下&#xff1a;dm_svc.conf必须放置到应用服务器上才行&#xff0c;放到其他服务器上识别不到。 文章中有的框架可能没写到并不代表不支持&#xff0c;有没提到的可文章下方留言。 1.dm_svc.conf的作用&#xff1a; dm_svc.conf文件主要是为了当DM数据库集群…

PHP健身微信小程序系统源码

&#x1f3cb;️‍♀️健身新潮流&#xff01;解锁“健身微信小程序”的全方位塑形秘籍 &#x1f4f1;开篇&#xff1a;掌中健身房&#xff0c;随时随地动起来 你还在为找不到合适的健身场地或教练而烦恼吗&#xff1f;是时候告别这些束缚&#xff0c;拥抱“健身微信小程序”…

如何在数据埋点中发现和修复数据上报逻辑错误

如何发现和处理数据埋点中的逻辑错误 在大数据分析中,数据埋点是至关重要的一环。然而,当我们遇到数据上报逻辑错误时,该如何应对呢?本文将为你揭示解决这一棘手问题的有效方法。 目录 如何发现和处理数据埋点中的逻辑错误什么是数据上报逻辑错误?如何发现数据上报逻辑错误…

S32G3系列芯片Serial Boot功能详解!

《S32G3系列芯片——Boot详解》系列——S32G3系列芯片Serial Boot功能详解&#xff01;★★★ 一、Serial Boot模式概述二、串行下载协议2.1 基于UART和CAN的下载协议概述2.2 基于FlexCAN的Serial Boot2.2.1 IO配置2.2.2 时钟配置2.2.3 通信波特率2.2.4 基于FlexCAN的Serial Bo…

定义和使用自己的子程序——函数的介绍

定义和使用自己的子程序——函数的介绍 1.函数基础语法1.1.基础语法1.2.例题1——距离函数题目描述输入格式输出格式输入输出样例输入 #1输出 #1 提示 2.void类型3.变量作用域和参数传递3.1.局部变量和全局变量3.2.形式参数和实际参数3.3.例题2——歌唱比赛题目描述输入格式输出…

计算机基础(Windows 10+Office 2016)教程 —— 第6章 电子表格软件Excel 2016(下)

电子表格软件Excel 2016 6.4 Excel 2016的公式与函数6.4.1 公式的概念6.4.2 公式的使用6.4.3 单元格的引用6.4.4 函数的使用6.4.5 快速计算与自动求和 6.5 Excel 2016的数据管理6.5.1 数据排序6.5.2 数据筛选6.5.3 分类汇总6.5.4 分组显示6.5.5 合并计算 6.6 Excel 2016的图表6…

【RabbitMQ】通配符模式(Topics)

一、基本概念 生产者&#xff08;Producer&#xff09;&#xff1a;发送消息到RabbitMQ交换机的程序。生产者定义消息的路由键&#xff0c;用于标识消息的目的地。交换机&#xff08;Exchange&#xff09;&#xff1a;接收生产者发送的消息&#xff0c;并根据路由键和绑定规则…

一款.NET开源、跨平台的DASH/HLS/MSS下载工具

前言 今天大姚给大家分享一款.NET开源&#xff08;MIT License&#xff09;、免费、跨平台的DASH/HLS/MSS下载工具&#xff0c;并且支持点播和直播&#xff08;DASH/HLS&#xff09;的内容下载&#xff1a;N_m3u8DL-RE。 网络流媒体传输协议介绍 DASH DASH是一种基于HTTP的…

2024年8月1日(前端服务器的配置以及tomcat环境的配置)

[rootstatic ~]# cd eleme_web/ [rootstatic eleme_web]# cd src/ [rootstatic src]# ls views/ AboutView.vue HomeView.vue [rootstatic src]# vim views/HomeView.vue [rootstatic src]# nohup npm run serve nohup: 忽略输入并把输出追加到"nohup.out" 构建项目…

零基础入门转录组数据分析——机器学习算法之boruta(筛选特征基因)

零基础入门转录组数据分析——机器学习算法之boruta&#xff08;筛选特征基因&#xff09; 目录 零基础入门转录组数据分析——机器学习算法之boruta&#xff08;筛选特征基因&#xff09;1. boruta基础知识2. boruta&#xff08;Rstudio&#xff09;——代码实操2. 1 数据处理…

机器学习之贝叶斯方法

机器学习之贝叶斯方法 1. 贝叶斯定理基础1.1 贝叶斯定理公式1.2 先验概率 (Prior Probability)1.3 后验概率 (Posterior Probability)1.4 似然 (Likelihood)1.5 证据 (Evidence)1.6 贝叶斯定理的应用实例 2. 贝叶斯方法的基本概念2.1 条件概率 (Conditional Probability)2.2 全…

Python SDK 使用Azure Document intelligence报错(404) Resource not found

最近项目需要使用到Azure Document intelligence,于是去做POC&#xff0c;但是发现最简单的demo跑的时候都会报这个错&#xff0c;解决了一下午终于搞定了&#xff0c;记录下。 首先是官方文档&#xff1a;Quickstart: Document Intelligence (formerly Form Recognizer) clien…

反序列化漏洞vulhub靶场serial

环境搭建 下载 https://download.vulnhub.com/serial/serial.zip 解压出来就是这种 你会得到一个这样的文件&#xff0c;这里使用VMware新建一个虚拟机&#xff0c;这里记录比较重要的几部分。 这里就是使用我们刚才下过来的。 漏洞过程详解 1.信息收集 打开靶机&#xff0…