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

阿里代码规范插件中,Apache Beanutils为什么被禁止使用?

在实际的项目开发中,对象间赋值普遍存在,随着双十一、秒杀等电商过程愈加复杂,数据量也在不断攀升,效率问题,浮出水面。

问:如果是你来写对象间赋值的代码,你会怎么做?

答:想都不用想,直接代码走起来,get、set即可。

问:下图这样?

答:对啊,你怎么能把我的代码放到网上?

问:没,我只是举个例子

答:这涉及到商业机密,是很严重的问题

问:我发现你挺能扯皮啊,直接回答问题行吗?

答:OK,OK,我也觉得这样写很low,上次这么写之后,差点挨打

  1. 对象太多,ctrl c + strl v,键盘差点没敲坏;
  2. 而且很容易出错,一不留神,属性没对应上,赋错值了;
  3. 代码看起来很傻缺,一个类好几千行,全是get、set复制,还起个了自以为很优雅的名字transfer;
  4. 如果属性名不能见名知意,还得加上每个属性的含义注释(基本这种赋值操作,都是要加的,注释很重要,注释很重要,注释很重要);
  5. 代码维护起来很麻烦;
  6. 如果对象过多,会产生类爆炸问题,如果属性过多,会严重违背阿里巴巴代码规约(一个方法的实际代码最多20行);

问:行了,行了,说说,怎么解决吧。

答:很简单啊,可以通过工具类Beanutils直接赋值啊

问:我听说工具类最近很卷,你用的哪个啊?

答:就Apache自带的那个啊,贼简单。我手写一个,给你欣赏一下。

问:你这代码报错啊,避免用Apache Beanutils进行属性的copy。

答:没报错,只是严重警告而已,代码能跑就行,有问题再优化呗

问:你这什么态度?人事在哪划拉的人,为啥会出现严重警告?

答:拿多少钱,干多少活,我又不是XXX,应该是性能问题吧

问:具体什么原因导致的呢?

答:3000块钱还得手撕一下 apache copyProperties的源代码呗?

通过单例模式调用copyProperties,但是,每一个方法对应一个BeanUtilsBean.getInstance()实例,每一个类实例对应一个实例,这不算一个真正的单例模式。

public static void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException {BeanUtilsBean.getInstance().copyProperties(dest, orig);
}

性能瓶颈 --> 日志太多也是病

通过源码可以看到,每一个copyProperties都要进行多次类型检查,还要打印日志。

/*** org.apache.commons.beanutils.BeanUtils.copyProperties方法源码解析* @author 哪吒编程* @time 2023-01-07*/
public void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException {// 类型检查if (dest == null) {throw new IllegalArgumentException("No destination bean specified");} else if (orig == null) {throw new IllegalArgumentException("No origin bean specified");} else {// 打印日志if (this.log.isDebugEnabled()) {this.log.debug("BeanUtils.copyProperties(" + dest + ", " + orig + ")");}int var5;int var6;String name;Object value;// 类型检查// DanyBean 提供了可以动态修改实现他的类的属性名称、属性值、属性类型的功能if (orig instanceof DynaBean) {// 获取源对象所有属性DynaProperty[] origDescriptors = ((DynaBean)orig).getDynaClass().getDynaProperties();DynaProperty[] var4 = origDescriptors;var5 = origDescriptors.length;for(var6 = 0; var6 < var5; ++var6) {DynaProperty origDescriptor = var4[var6];// 获取源对象属性名name = origDescriptor.getName();// 判断源对象是否可读、判断目标对象是否可写if (this.getPropertyUtils().isReadable(orig, name) && this.getPropertyUtils().isWriteable(dest, name)) {// 获取对应的值value = ((DynaBean)orig).get(name);// 每个属性都调用一次copyPropertythis.copyProperty(dest, name, value);}}} else if (orig instanceof Map) {Map<String, Object> propMap = (Map)orig;Iterator var13 = propMap.entrySet().iterator();while(var13.hasNext()) {Map.Entry<String, Object> entry = (Map.Entry)var13.next();String name = (String)entry.getKey();if (this.getPropertyUtils().isWriteable(dest, name)) {this.copyProperty(dest, name, entry.getValue());}}} else {PropertyDescriptor[] origDescriptors = this.getPropertyUtils().getPropertyDescriptors(orig);PropertyDescriptor[] var14 = origDescriptors;var5 = origDescriptors.length;for(var6 = 0; var6 < var5; ++var6) {PropertyDescriptor origDescriptor = var14[var6];name = origDescriptor.getName();if (!"class".equals(name) && this.getPropertyUtils().isReadable(orig, name) && this.getPropertyUtils().isWriteable(dest, name)) {try {value = this.getPropertyUtils().getSimpleProperty(orig, name);this.copyProperty(dest, name, value);} catch (NoSuchMethodException var10) {}}}}}
}

通过 jvisualvm.exe 检测代码性能

再通过jvisualvm.exe检测一下运行情况,果然,logging.log4j赫然在列,稳居耗时Top1。

问:还有其它好的方式吗?性能好一点的

答:当然有,据我了解有 4 种工具类,实际上,可能会有更多,话不多说,先简单介绍一下。

  1. org.apache.commons.beanutils.BeanUtils;
  2. org.apache.commons.beanutils.PropertyUtils;
  3. org.springframework.cglib.beans.BeanCopier;
  4. org.springframework.beans.BeanUtils;

问:那你怎么不用?

答:OK,我来演示一下

package com.nezha.copy;import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.util.StopWatch;public class Test {public static void main(String[] args) {User user = new User();user.setUserId("1");user.setUserName("哪吒编程");user.setCardId("123");user.setCreateTime("2023-01-03");user.setEmail("666666666@qq.com");user.setOperate("哪吒");user.setOrgId("46987916");user.setPassword("123456");user.setPhone("10086");user.setRemark("456");user.setSex(1);user.setStatus("1");user.setTel("110");user.setType("0");user.setUpdateTime("2023-01-05");User target = new User();int sum = 10000000;apacheBeanUtilsCopyTest(user,target,sum);commonsPropertyCopyTest(user,target,sum);cglibBeanCopyTest(user,target,sum);springBeanCopyTest(user,target,sum);}private static void apacheBeanUtilsCopyTest(User source, User target, int sum) {StopWatch stopWatch = new StopWatch();stopWatch.start();for (int i = 0; i < sum; i++) {apacheBeanUtilsCopy(source,target);}stopWatch.stop();System.out.println("使用org.apache.commons.beanutils.BeanUtils方式赋值"+sum+"个user对象,耗时:"+stopWatch.getLastTaskTimeMillis()+"毫秒");}/*** org.apache.commons.beanutils.BeanUtils方式*/private static void apacheBeanUtilsCopy(User source, User target) {try {BeanUtils.copyProperties(source, target);} catch (Exception e) {}}private static void commonsPropertyCopyTest(User source, User target, int sum) {StopWatch stopWatch = new StopWatch();stopWatch.start();for (int i = 0; i < sum; i++) {commonsPropertyCopy(source,target);}stopWatch.stop();System.out.println("使用org.apache.commons.beanutils.PropertyUtils方式赋值"+sum+"个user对象,耗时:"+stopWatch.getLastTaskTimeMillis()+"毫秒");}/*** org.apache.commons.beanutils.PropertyUtils方式*/private static void commonsPropertyCopy(User source, User target) {try {PropertyUtils.copyProperties(target, source);} catch (Exception e) {}}private static void cglibBeanCopyTest(User source, User target, int sum) {StopWatch stopWatch = new StopWatch();stopWatch.start();for (int i = 0; i < sum; i++) {cglibBeanCopy(source,target);}stopWatch.stop();System.out.println("使用org.springframework.cglib.beans.BeanCopier方式赋值"+sum+"个user对象,耗时:"+stopWatch.getLastTaskTimeMillis()+"毫秒");}/*** org.springframework.cglib.beans.BeanCopier方式*/static BeanCopier copier = BeanCopier.create(User.class, User.class, false);private static void cglibBeanCopy(User source, User target) {copier.copy(source, target, null);}private static void springBeanCopyTest(User source, User target, int sum) {StopWatch stopWatch = new StopWatch();stopWatch.start();for (int i = 0; i < sum; i++) {springBeanCopy(source,target);}stopWatch.stop();System.out.println("使用org.springframework.beans.BeanUtils.copyProperties方式赋值"+sum+"个user对象,耗时:"+stopWatch.getLastTaskTimeMillis()+"毫秒");}/*** org.springframework.beans.BeanUtils.copyProperties方式*/private static void springBeanCopy(User source, User target) {org.springframework.beans.BeanUtils.copyProperties(source, target);}
}

“四大金刚” 性能统计

方法1000100001000001000000
apache BeanUtils906毫秒807毫秒1892毫秒11049毫秒
apache PropertyUtils17毫秒96毫秒648毫秒5896毫秒
spring cglib BeanCopier0毫秒1毫秒3毫秒10毫秒
spring copyProperties87毫秒90毫秒123毫秒482毫秒

不测不知道,一测吓一跳,差的还真的多。

spring cglib BeanCopier性能最好,apache BeanUtils性能最差。

性能走势 --> spring cglib BeanCopier优于 spring copyProperties优于 apache PropertyUtils优于 apache BeanUtils

避免用Apache Beanutils进行属性的copy的问题 上面分析完了,下面再看看其它的方法做了哪些优化。

Apache PropertyUtils 源码分析

从源码可以清晰的看到,类型检查变成了非空校验,去掉了每一次copy的日志记录,性能肯定更好了。

  1. 类型检查变成了非空校验
  2. 去掉了每一次copy的日志记录
  3. 实际赋值的地方由copyProperty变成了DanyBean + setSimpleProperty;

DanyBean 提供了可以动态修改实现他的类的属性名称、属性值、属性类型的功能。

/*** org.apache.commons.beanutils.PropertyUtils方式源码解析* @author 哪吒编程* @time 2023-01-07*/
public void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {// 判断数据源和目标对象不是nullif (dest == null) {throw new IllegalArgumentException("No destination bean specified");} else if (orig == null) {throw new IllegalArgumentException("No origin bean specified");} else {// 删除了org.apache.commons.beanutils.BeanUtils.copyProperties中最为耗时的log日志记录int var5;int var6;String name;Object value;// 类型检查if (orig instanceof DynaBean) {// 获取源对象所有属性DynaProperty[] origDescriptors = ((DynaBean)orig).getDynaClass().getDynaProperties();DynaProperty[] var4 = origDescriptors;var5 = origDescriptors.length;for(var6 = 0; var6 < var5; ++var6) {DynaProperty origDescriptor = var4[var6];// 获取源对象属性名name = origDescriptor.getName();// 判断源对象是否可读、判断目标对象是否可写if (this.isReadable(orig, name) && this.isWriteable(dest, name)) {try {// 获取对应的值value = ((DynaBean)orig).get(name);// 相对于org.apache.commons.beanutils.BeanUtils.copyProperties此处有优化// DanyBean 提供了可以动态修改实现他的类的属性名称、属性值、属性类型的功能if (dest instanceof DynaBean) {((DynaBean)dest).set(name, value);} else {// 每个属性都调用一次copyPropertythis.setSimpleProperty(dest, name, value);}} catch (NoSuchMethodException var12) {if (this.log.isDebugEnabled()) {this.log.debug("Error writing to '" + name + "' on class '" + dest.getClass() + "'", var12);}}}}} else if (orig instanceof Map) {Iterator entries = ((Map)orig).entrySet().iterator();while(true) {Map.Entry entry;String name;do {if (!entries.hasNext()) {return;}entry = (Map.Entry)entries.next();name = (String)entry.getKey();} while(!this.isWriteable(dest, name));try {if (dest instanceof DynaBean) {((DynaBean)dest).set(name, entry.getValue());} else {this.setSimpleProperty(dest, name, entry.getValue());}} catch (NoSuchMethodException var11) {if (this.log.isDebugEnabled()) {this.log.debug("Error writing to '" + name + "' on class '" + dest.getClass() + "'", var11);}}}} else {PropertyDescriptor[] origDescriptors = this.getPropertyDescriptors(orig);PropertyDescriptor[] var16 = origDescriptors;var5 = origDescriptors.length;for(var6 = 0; var6 < var5; ++var6) {PropertyDescriptor origDescriptor = var16[var6];name = origDescriptor.getName();if (this.isReadable(orig, name) && this.isWriteable(dest, name)) {try {value = this.getSimpleProperty(orig, name);if (dest instanceof DynaBean) {((DynaBean)dest).set(name, value);} else {this.setSimpleProperty(dest, name, value);}} catch (NoSuchMethodException var10) {if (this.log.isDebugEnabled()) {this.log.debug("Error writing to '" + name + "' on class '" + dest.getClass() + "'", var10);}}}}}}
}

通过 jvisualvm.exe 检测代码性能

再通过jvisualvm.exe检测一下运行情况,果然,logging.log4j没有了,其他的基本不变。

Spring copyProperties 源码分析

  1. 判断数据源和目标对象的非空判断改为了断言;
  2. 每次copy没有日志记录;
  3. 没有if (orig instanceof DynaBean) {这个类型检查;
  4. 增加了放开权限的步骤;
/*** org.springframework.beans.BeanUtils.copyProperties方法源码解析* @author 哪吒编程* @time 2023-01-07*/
private static void copyProperties(Object source, Object target, @Nullable Class<?> editable,@Nullable String... ignoreProperties) throws BeansException {// 判断数据源和目标对象不是nullAssert.notNull(source, "Source must not be null");Assert.notNull(target, "Target must not be null");/*** 若target设置了泛型,则默认使用泛型* 若是 editable 是 null,则此处忽略* 一般情况下editable都默认为null*/Class<?> actualEditable = target.getClass();if (editable != null) {if (!editable.isInstance(target)) {throw new IllegalArgumentException("Target class [" + target.getClass().getName() +"] not assignable to Editable class [" + editable.getName() + "]");}actualEditable = editable;}// 获取target中全部的属性描述PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);// 需要忽略的属性List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);for (PropertyDescriptor targetPd : targetPds) {Method writeMethod = targetPd.getWriteMethod();// 目标对象存在写入方法、属性不被忽略if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());if (sourcePd != null) {Method readMethod = sourcePd.getReadMethod();/*** 源对象存在读取方法、数据是可复制的* writeMethod.getParameterTypes()[0]:获取 writeMethod 的第一个入参类型* readMethod.getReturnType():获取 readMethod 的返回值类型* 判断返回值类型和入参类型是否存在继承关系,只有是继承关系或相等的情况下,才会进行注入*/if (readMethod != null &&ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {try {// 放开读取方法的权限if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {readMethod.setAccessible(true);}// 通过反射获取值Object value = readMethod.invoke(source);// 放开写入方法的权限if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {writeMethod.setAccessible(true);}// 通过反射写入值writeMethod.invoke(target, value);}catch (Throwable ex) {throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", ex);}}}}}
}

总结

阿里的友情提示,避免用Apache Beanutils进行对象的copy,还是很有道理的。

Apache Beanutils的性能问题出现在类型校验和每一次copy的日志记录;

Apache PropertyUtils 进行了如下优化:

  1. 类型检查变成了非空校验
  2. 去掉了每一次copy的日志记录
  3. 实际赋值的地方由copyProperty变成了DanyBean + setSimpleProperty;

Spring copyProperties 进行了如下优化:

  1. 判断数据源和目标对象的非空判断改为了断言;
  2. 每次copy没有日志记录;
  3. 没有if (orig instanceof DynaBean) {这个类型检查;
  4. 增加了放开权限的步骤;

在这里插入图片描述
在这里插入图片描述

Java学习路线总结,搬砖工逆袭Java架构师

10万字208道Java经典面试题总结(附答案)

Java基础教程系列

Java基础教程系列(进阶篇)

相关文章:

阿里代码规范插件中,Apache Beanutils为什么被禁止使用?

在实际的项目开发中&#xff0c;对象间赋值普遍存在&#xff0c;随着双十一、秒杀等电商过程愈加复杂&#xff0c;数据量也在不断攀升&#xff0c;效率问题&#xff0c;浮出水面。 问&#xff1a;如果是你来写对象间赋值的代码&#xff0c;你会怎么做&#xff1f; 答&#xf…...

NFC enable NFC使能流程

同学,别退出呀,我可是全网最牛逼的 WIFI/BT/GPS/NFC分析博主,我写了上百篇文章,请点击下面了解本专栏,进入本博主主页看看再走呗,一定不会让你后悔的,记得一定要去看主页置顶文章哦。 NFC enable NFC使能流程 认识nfc系统如何工作,最好的方法就是了解nfc的各个流程,…...

Redis实例绑定CPU物理核优化Redis性能

进入本次Redis性能调优之前&#xff0c;首先要知道CPU结构也会影响Redis的性能。接下来&#xff0c;具体了解一下&#xff01;为什么CPU结构也会影响Redis的性能&#xff1f;主流的 CPU 架构一个 CPU 处理器中一般有多个物理核&#xff0c;每个物理核都可以运行应用程序。每个物…...

STC15中断系统介绍

STC15中断系统介绍✨本篇参考来源于STC官方stc15系列手册:538页- 589页。&#xff08;文末提供该摘取部分的文档资料&#xff09; &#x1f389;在官方提供的手册资料中&#xff0c;一个系列一份手册&#xff0c;手册内容涵盖了数据手册和参考手册以及例程案例。对于学习着来说…...

力扣HOT100 11-15

11.盛水最多的容器 思路&#xff1a;最大水量 底边 * 高度。较短的一边控制最大水量&#xff0c;因此&#xff0c;采用双指针的方式&#xff0c;左、右指针指向开始和末尾&#xff0c;逐个向中间移动&#xff0c;判断左右指针所指向的高度哪个更低&#xff0c;它就向中间移动一…...

深入浅出单调栈与单调队列

目录一、单调栈情形一&#xff1a;寻找一个数左边第一个小于它的数情形二&#xff1a;寻找一个数左边第一个小于它的数的下标情形三&#xff1a;寻找一个数右边第一个大于它的数情形四&#xff1a;寻找一个数右边第一个大于它的数的下标二、单调栈的应用2.1 单调栈模板题I2.2 单…...

深入C语言——实现可变参数函数

文章目录初步示例函数解析最大值函数初步示例 stdarg.h提供了C语言对可变参数的支持&#xff0c;先举一个简短的例子 //testStdArg.c #include <stdarg.h> #include <stdio.h>void printIntList(int N, ...){va_list args; //存放...所代表的参数va_start(…...

41-Dockerfile-Dockerfile简介

Dockerfile简介前言Dockerfile 简介基础知识使用Dockerfile 构建镜像步骤Dockerfile 构建过程Dockerfile基本结构Dockerfile示例总结前言 本篇开始来学习下Dockerfile相关的用法 Dockerfile 简介 Dockerfile : 是用来构建 Docker 镜像的文本文件&#xff0c;是有一条条构建镜…...

【408】操作系统 - 刻骨铭心自测题1(上)

文章目录OS练习题第一部分&#xff1a;1&#xff1a;2&#xff1a;3&#xff1a;4&#xff1a;5&#xff1a;6&#xff1a;7&#xff1a;8&#xff1a;9&#xff1a;10&#xff1a;11&#xff1a;12&#xff1a;13&#xff1a;14&#xff1a;15&#xff1a;16&#xff1a;17&am…...

【老卫拆书】009期:Vue+Node肩挑全栈!《Node.js+Express+MongoDB+Vue.js全栈开发实战》开箱

今天刚拿到一本新书&#xff0c;叫做《Node.jsExpressMongoDBVue.js全栈开发实战》&#xff0c;做个开箱。 外观 先从外观上讲&#xff0c;这本是全新的未开封的&#xff0c;膜还在。 这本书介绍从技术原理到整合开发实战&#xff0c;以丰富的项目展现全栈开发的一个技巧。 …...

【LeetCode】动态规划总结

动态规划解决的问题 动态规划和贪心的区别&#xff1a; 动态规划是由前一个状态推导出来的&#xff1b; 贪心是局部直接选最优的。 动态规划解题步骤 状态定义&#xff1a;确定dp数组以及下标的含义状态转移方程&#xff1a;确定递推公式初始条件&#xff1a;dp如何初始化遍历…...

CAS详解.

CAS这个机制就给实现线程安全版本的代码&#xff0c;提供了一个新的思路&#xff0c;之前通过加锁&#xff0c;把多个指令打包成整体&#xff0c;来实现线程安全。现在就可以考虑直接基与CAS来实现一些修改操作&#xff0c;也能保证线程安全&#xff08;不需要加锁&#xff09;…...

Mock.js初步使用(浏览器端)

Mock.js&#xff1a;生成随机数据&#xff0c;拦截 Ajax 请求。官方地址&#xff1a;http://mockjs.com/第一个demodemo.html<!DOCTYPE html> <html> <head><meta charset"utf-8"><title>mockjs demo</title> </head> <…...

opencv保存图片

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…...

【c++】数据类型

文章目录整型实型科学计数法sizeof关键字字符型字符串类型转义字符bool布尔类型c规定在创建一个变量或者常量时&#xff0c;必须要指定出相应的数据类型&#xff0c;否则无法给变量分配内存。 整型 作用&#xff1a;整型变量表示的是整数类型的数据。 实型 float f3.14; //默…...

Elasticsearch的写的底层原理

前面有一篇文章讲解了Elasticsearch的读写搜索过程&#xff0c;有的人感觉不太理解&#xff0c;今天我们再来看看这些过程的原理 写数据底层原理 首先是将数据写入到内存buffer中&#xff0c;在这里的时候&#xff0c;数据是搜索不到。他同时会将数据写入到translog日志文件中…...

【网络编程】Java中的Socket

文章目录前言socket是什么&#xff1f;Java中的SocketJava实现网络上传文件前言 所谓Socket&#xff08;套接字&#xff09;&#xff0c;就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端&#xff0c;提供了应用层进程利用…...

有趣的Hack-A-Sat黑掉卫星挑战赛——跟踪卫星

国家太空安全是国家安全在空间领域的表现。随着太空技术在政治、经济、军事、文化等各个领域的应用不断增加&#xff0c;太空已经成为国家赖以生存与发展的命脉之一&#xff0c;凝聚着巨大的国家利益&#xff0c;太空安全的重要性日益凸显[1]。而在信息化时代&#xff0c;太空安…...

Ubuntu安装配置Cuda和Pytorch gpu

前言 在Ubuntu中操作系统中,通过Anconda安装对应的虚拟环境以及软件包,一般都需要适配Cuda、Pytorch版本等 以下安装配置都是在Ubuntu操作系统下 1. 安装Cuda 通过Ubuntu操作系统查看cuda适配的版本:nvidia-smi 截图如下: 查看Ubuntu版本可如下方式 (1)cat /proc/ver…...

三、Java面向对象

1 . 方法 方法(method)是程序中最小的执行单元方法就是一些代码的打包 需要的时候可以直接调用方法之间是平级的关系 不能在方法里面定义方法方法不调用就不执行 方法的定义 // 方法的定义 /* [修饰符] 返回值类型 方法名称([参数 1],[参数 2]){语句A;return 返回值; } *///…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...