R 文件优化插件:Binary XML file in layout Error inflating class

在这里插入图片描述

场景一:构造函数缺失

问题

自定义布局(FlagmentLayout)加载自定义属性失败,导致广告显示异常,甚至是闪退~

InflateException 在 Android 中我们遇到的通常发生在自定义 View 创建中,动态加载布局一般使用 View view = View.inflate(context, int resource, ViewGroup root);,View.inflate 方法具有多个重载函数。

这里日志大概意思是:
在布局文件 layout/jiy 的第 7 行,存在一个自定义 view com.xphxqk.bmerth 加载失败。

Caused by:
android.view.InflateException:
Binary XML file line #7 in com.primer.hello:layout/jiy:
Error inflating class com.xphxqk.bmerth

这里日志大概意思是:
java.lang.reflect 可知此处属于反射,说的是反射调用异常

Caused by: java.lang.reflect.InvocationTargetException

为什么存在反射相关呢?
根据下面的日志可知,动态加载布局最中是通过反射创建对象(XML 文件里面的 view 是如何初始化的?)。

Constructor.newInstance
… …
LayoutInflater.createView
… …
LayoutInflater.inflate
… …

错误日志

 android.view.InflateException: 
  Binary XML file line #7 in com.primer.hello:layout/jiy:
  Binary XML file line #7 in com.primer.hello:layout/jiy: 
  Error inflating class com.xphxqk.bmerth

 Caused by: android.view.InflateException: 
 Binary XML file line #7 in com.primer.hello:layout/jiy:
 Error inflating class com.xphxqk.bmerth
 
 Caused by: java.lang.reflect.InvocationTargetException
 	at java.lang.reflect.Constructor.newInstance0(Native Method)
 	at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
 	at android.view.LayoutInflater.createView(LayoutInflater.java:858)
 	at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1010)
 	at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:965)
 	at android.view.LayoutInflater.rInflate(LayoutInflater.java:1127)
 	at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
 	at android.view.LayoutInflater.rInflate(LayoutInflater.java:1130)
 	at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
 	at android.view.LayoutInflater.rInflate(LayoutInflater.java:1130)
 	at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
 	at android.view.LayoutInflater.inflate(LayoutInflater.java:686)
 	at android.view.LayoutInflater.inflate(LayoutInflater.java:538)
 	at android.view.LayoutInflater.inflate(LayoutInflater.java:485)
 	at com.JBruhU.OewGelzz.GFAvHQl.iPclUCgYxLa.OAOQTuGm.OOooo(SourceFile:13)
 	at com.JBruhU.OewGelzz.GFAvHQl.iPclUCgYxLa.OAOQTuGm.OooOO0(SourceFile:22)
 	at com.JBruhU.OewGelzz.GFAvHQl.MXGbW.VRyBu.<init>(SourceFile:9)
 	at com.JBruhU.OewGelzz.GFAvHQl.MXGbW.VkNMUXIrzzB.<init>(SourceFile:3)
 	at com.JBruhU.OewGelzz.GFAvHQl.MXGbW.VkNMUXIrzzB.<init>(SourceFile:2)
 	at com.JBruhU.OewGelzz.GFAvHQl.MXGbW.VkNMUXIrzzB.<init>(SourceFile:1)
 	at com.JBruhU.OewGelzz.GFAvHQl.iPclUCgYxLa.OAOQTuGm.<init>(SourceFile:1)
 	at OOO0o0o0.o0OOO0OO.getMsgViewByOpentype(SourceFile:19)
 	at OOO0o0o0.o0OOO0OO.dispatchNativeAd(SourceFile:259)
 	at oOo0oo.OOOooo0.OOooO0O0(Unknown Source:4)
 	at oOo0oo.O0oOOo.O0o0o(Unknown Source:380)
 	at oOo0oo.O0oOOo$ooo0OOOO.run(Unknown Source:8)
 	at o0o0oo0.O0o0O0oo.o0OOO0OO(Unknown Source:15)
 	at oOo0oo.O0oOOo.O0ooo0(Unknown Source:57)
 	at com.pokfzu.doljxp$o0OOO0OO.run(Unknown Source:46)
 	at android.os.Handler.handleCallback(Handler.java:938)
 	at android.os.Handler.dispatchMessage(Handler.java:99)
 	at android.os.Looper.loopOnce(Looper.java:233)
 	at android.os.Looper.loop(Looper.java:344)
 	at android.app.ActivityThread.main(ActivityThread.java:8191)
 	at java.lang.reflect.Method.invoke(Native Method)
 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584)
 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)
 Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Lorg/xqq/w/R$styleable;
 	at com.xphxqk.bmerth.<init>(SourceFile:5)
 	... 37 more
 Caused by: java.lang.ClassNotFoundException: org.xqq.w.R$styleable
 	... 38 more

看到这个错误隐约记得之前遇到过,但是一时间想不起来,直到后来记起才就此记录一笔。

以 FragmentLayout 为例,查看源码我们知道他有四个重载的构造函数,什么时候使用那个构造函数比较合适我们可能不清楚,但是我们在自定义 View 时候通常会加入新的属性 attrs,那么会使用到构造函数2️⃣,在函数里获取属性attrs值再进一步操作。

@RemoteView
public class FrameLayout extends ViewGroup {
  
  	//构造函数 1️⃣
    public FrameLayout(@NonNull Context context) {
        super(context);
    }

	//2️⃣
    public FrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

	//3️⃣
    public FrameLayout(@NonNull Context context, @Nullable AttributeSet attrs,
            @AttrRes int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

	//4️⃣
    public FrameLayout(@NonNull Context context, @Nullable AttributeSet attrs,
            @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
	
	//other ... ...
}

通过反射创建一个类,反射创建传给构造函数的参数不一致(在类内找不到合适的构造函数),那么会发生反射调用异常,也就是上述的InvocationTargetException异常,最终是对象创建失败!

在以前遇到的案例中:
就是这种构造函数缺失(反射找不到合适的构造函数创建实例)导致自定义 View 创建失败,布局动态加载失败。

那么为什么会缺失构造函数?

  • 场景一:自定义 view 时,漏写对象的构造函数(比如你使用 View.inflate 加载布局,可是没写构造函数2️⃣)
  • 场景二:开启混淆,在打包混淆过程构造函数被移除(之前遇到过的就是这种情况)

解决

  • 场景一:自然是补充构造函数(重写)
  • 场景二:通过 keep 规则保持自定义 view 类内的构造函数在混淆过程中不被移除(例如:-keep class com.primer.view.*{*;}

还没完,下面开始才是本次遇到的场景三,新方向,新问题~

场景二:R 文件优化插件

问题

纳闷了,在我的 AGP4+ 项目打包运行正常,在 AGP7+ 项目打包运行闪退!

看混淆映射 mapping.txt 文件,自定义 view 类的构造函数都在,没有混淆被移除,所以可以确定不是因构造函数缺失导致的闪退。

查看 class 文件通常能看到这两个东西:

  • <init> 是实例构造函数(new 等非静态初始化)
  • <cinit> 是类构造器函数(静态属性等初始化)

在这里插入图片描述

源代码

以下分析的是混淆之后的包,所以类名称和部分方法名可能不一样,都是混淆后的。

这就是那个自定义布局,我们自定义了新的属性 attr,所以用到下面这个构造函数,并且在函数里获取自定义属性值。

自定义两个属性

<resources>
   <declare-styleable name="RatioFrameLayout">
       <attr name="frameratio" format="float" />
       <attr name="orientation" format="integer" />
   </declare-styleable>
</resources>

动态加载布局,反射创建实例是被调用的构造函数

public RatioFrameLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RatioFrameLayout);
    
    mRatio = typedArray.getFloat(R.styleable.RatioFrameLayout_frameratio, 0f);
    mScreenOrientation = typedArray.getInt(R.styleable.RatioFrameLayout_orientation, 0);
    typedArray.recycle();
}

分析

AGP4+

AGP4+ 上打的包,查看 smile obtainStyledAttributes(AttributeSet,int[]) 方法,方法调用传入的第二个参数v1 是一个整型数组这是符合要求的,并且数组是有值的,这两值正是对应自定义属性 RatioFrameLayout 的两个属性的属性ID,这是完全正确的,运行正常。

在这里插入图片描述

属性 ID 在打包过程中 build 目录下可以查看,在包体全局搜索也能找到。

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

通过 smile 了解 R 文件引用:

  • obtainStyledAttributes(attrs, R.styleable.RatioFrameLayout);

方法的第二个参数是 int[] 整型数组,查看上述的 smile 也能知道,所以 R.styleable.RatioFrameLayout 本质上它的值就是一个 int[]

  • typedArray.getInt(R.styleable.RatioFrameLayout_orientation, 0);
  • typedArray.getFloat(R.styleable.RatioFrameLayout_frameratio, 0f);

一开始我不知道 R.styleable.RatioFrameLayout_frameratio 到底是一个什么样的值?通过日志打印结合 smile 了解到这就是属性 RatioFrameLayout 的索引,实际上对应的就是属性数组 typedArray 的索引,通过索引确定位置获取属性值。

AGP7+

在 AGP7+ 发生了什么?

obtainStyledAttributes 方法的第二个参数 v1 怎么不是数组的具体值?而是指向:从 org.xqq.w.R 类获取值。难道从这个 R 类获取不到值吗?

在这里插入图片描述

查看日志和代码,这个两个属性确实是存在的(混淆后的)

在这里插入图片描述

只是这个属性存在包名的 R 类下,而不是另外一个不确定的包下 org.xqq.w

在这里插入图片描述

这指定是有问题,这个类的 R 类就没有内容。所以第二个参数 v1 执行的是类下的某个属性,并未获取到具体的值?

所以,我们大胆猜测:
是否是因为没有获取到第二个参数 R.styleable.RatioFrameLayout 的值,导致传入参数异常,反射创建实例失败?

在这里插入图片描述

解决方案一

查看包体,既然属性值是真实存在的(在包名的 R 类下),并且我们知道 R.styleable.RatioFrameLayout 的值本质就是一个整型数组 int[],那么我们是否可通过别的方式获取到 RatioFrameLayout 两个属性的值再组成一个数组传给 obtainStyledAttributes 就可以了?

经验证,方案缺失可行!

    public RatioFrameLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
		//闪退代码:R.styleable.RatioFrameLayout 没有值
		//TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RatioFrameLayout);
		
		//修改后:分别获取 frameratio、orientation 的属性ID,重组成整型数组
		//注:开启资源混淆时,需要 keep 属性 frameratio、orientation
		//如,需配置微信资源混淆白名单 "R.attr.orientation","R.attr.orientation"
		int id1 = context.getResources().getIdentifier("frameratio", "attr", context.getPackageName());
        int id2 = context.getResources().getIdentifier("orientation", "attr", context.getPackageName());
        int[] attrsId = {id1, id2};
        LogUtil.d("RatioFrameLayout", " id1 = " + id1 + "  id2 = " + id2);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, attrsId);
        
        int a1 = R.styleable.RatioFrameLayout_frameratio;
        int a2 = R.styleable.RatioFrameLayout_orientation;
        LogUtil.d("RatioFrameLayout", " a1 = " + a1 + "  a2 = " + a2);
        
        mRatio = typedArray.getFloat(a1, 0f);
        mScreenOrientation = typedArray.getInt(a2, 0);
        typedArray.recycle();
    }

在这里插入图片描述

再次闪退

本以为万事大吉,准备下班

谁知道还能遇到闪退,测试反馈说小米激励视频广告闪退~

闪退日志

其他日志基本与上述一致,主要区别在于闪退来自小米广告 sdk 内部

Constructor.newInstance
… …
LayoutInflater.inflate
… …
com.miui.zeus.mimo.sdk.p4.a(SourceFile:26)
… …
com.miui.zeus.mimo.sdk.ad.reward.view.RewardTemplateP2View.a(SourceFile:2)

com.miui.zeus.mimo.sdk.view.DownloadBtnView.(SourceFile:19)

 FATAL EXCEPTION: main
 Process: com.primer.hello, PID: 23659
 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.primer.hello/com.miui.zeus.mimo.sdk.ad.reward.RewardVideoAdActivityNewPE}: android.view.InflateException: Binary XML file line #119 in com.primer.hello:layout/mimo_reward_template_p_2: Binary XML file line #119 in com.primer.hello:layout/mimo_reward_template_p_2: Error inflating class <unknown>
 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3308)
 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3457)
 	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2044)
 	at android.os.Handler.dispatchMessage(Handler.java:107)
 	at android.os.Looper.loop(Looper.java:224)
 	at android.app.ActivityThread.main(ActivityThread.java:7562)
 	at java.lang.reflect.Method.invoke(Native Method)
 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
 Caused by: android.view.InflateException: Binary XML file line #119 in com.primer.hello:layout/mimo_reward_template_p_2: Binary XML file line #119 in com.primer.hello:layout/mimo_reward_template_p_2: Error inflating class <unknown>
 Caused by: android.view.InflateException: Binary XML file line #119 in com.primer.hello:layout/mimo_reward_template_p_2: Error inflating class <unknown>
 Caused by: java.lang.reflect.InvocationTargetException
 	at java.lang.reflect.Constructor.newInstance0(Native Method)
 	at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
 	at android.view.LayoutInflater.createView(LayoutInflater.java:858)
 	at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1010)
 	at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:965)
 	at android.view.LayoutInflater.rInflate(LayoutInflater.java:1127)
 	at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
 	at android.view.LayoutInflater.rInflate(LayoutInflater.java:1130)
 	at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
 	at android.view.LayoutInflater.rInflate(LayoutInflater.java:1130)
 	at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
 	at android.view.LayoutInflater.rInflate(LayoutInflater.java:1130)
 	at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
 	at android.view.LayoutInflater.inflate(LayoutInflater.java:686)
 	at android.view.LayoutInflater.inflate(LayoutInflater.java:538)
 	at android.view.LayoutInflater.inflate(LayoutInflater.java:481)
 	at com.miui.zeus.mimo.sdk.p4.a(SourceFile:26)
 	at com.miui.zeus.mimo.sdk.p4.a(SourceFile:23)
 	at com.miui.zeus.mimo.sdk.ad.reward.view.RewardTemplateP2View.a(SourceFile:2)
 	at com.miui.zeus.mimo.sdk.ad.reward.RewardTemplatePType$5.newTemplateView(SourceFile:1)
 	at mimo_1011.NCall.IV(Native Method)
 	at com.miui.zeus.mimo.sdk.ad.reward.RewardVideoAdActivityNewPE.onCreate(Unknown Source:18)
 	at android.app.Activity.performCreate(Activity.java:7893)
 	at android.app.Activity.performCreate(Activity.java:7880)
 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3283)
 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3457)
 	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2044)
 	at android.os.Handler.dispatchMessage(Handler.java:107)
 	at android.os.Looper.loop(Looper.java:224)
 	at android.app.ActivityThread.main(ActivityThread.java:7562)
 	at java.lang.reflect.Method.invoke(Native Method)
 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
 Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Lorg/xqq/w/R$styleable;
 	at com.miui.zeus.mimo.sdk.view.DownloadBtnView.<init>(SourceFile:19)
 	... 37 more
 Caused by: java.lang.ClassNotFoundException: org.xqq.w.R$styleable

查看源码,同是obtainStyledAttributes方法这里,引用指定的 R 类经也是之前错误的 org.xqq.w.R。这就很奇怪了

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

上述的解决方案只能修改自己的源码解决问题,但这里是第三方代码按照上述方案修改不切实际,还不清楚是否还有很多这样的危险代码,难道都要手动一一修改吗?

后来怀疑是否有其他地方(插件)干预 R 类的生成或引用?

突然,我想起来了!我们打包项目里缺失使用了 R 文件优化的插件

  • AGP4+ 项目使用的是:字节 Shrink-r-plugin 插件
  • AGP7+ 项目使用的是:滴滴 Booster-transform-r-inline 插件

之前做 AGP4+ 升级到 AGP7+ 时遇到 shrink 插件问题,似乎是不支持 AGP7,所以找了滴滴的这个插件作为替代品。

插件的主要功能是:

  • R文件常量内联,R文件瘦身
  • 无用Resource资源检查
  • 无用assets检查
  • 内联资源索引,例如R$id、R$layout、R$string等字段

解决方案二

不出意外,经测试,移除 booster-transform-r-inline 插件的引用打包运行一切正常了!

//apply
//classpath "com.didiglobal.booster:booster-gradle-plugin:$booster_version"
//classpath "com.didiglobal.booster:booster-transform-r-inline:$booster_version"

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

家用RJ45水晶头可以用在工业互联网中?

工业互联网作为智能制造的核心组成部分&#xff0c;已经在工业领域快速发展。在建立连接不同设备和系统的复杂网络中&#xff0c;网络设备和连接器的选择变得至关重要。其中&#xff0c;普遍使用的RJ45水晶头和网线在家庭和小型商业网络中被广泛采用&#xff0c;但是否适用于工…

记录一下PHP使用微信小程序支付

记录一下PHP使用微信小程序支付V3版本经历 官方文档&#xff1a;https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_0.shtml 请详细查看文档中小程序支付接入前准备&#xff08;https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml&#xff…

电脑怎么录制游戏视频?轻松捕捉每一帧精彩

随着游戏产业的蓬勃发展&#xff0c;越来越多的玩家不仅满足于在游戏世界中的探索与冒险&#xff0c;更希望将自己的游戏精彩瞬间记录下来&#xff0c;分享给更多的朋友。可是电脑怎么录制游戏视频呢&#xff1f;本文旨在为广大游戏爱好者提供一份详细的电脑游戏视频录制攻略&a…

GraphQL(9):Spring Boot集成Graphql简单实例

1 安装插件 我这边使用的是IDEA&#xff0c;需要先按照Graphql插件&#xff0c;步骤如下&#xff1a; &#xff08;1&#xff09;打开插件管理 在IDEA中&#xff0c;打开主菜单&#xff0c;选择 "File" -> "Settings" (或者使用快捷键 Ctrl Alt S …

2024黄河流域比赛的复现

目录 WEB [GKCTF 2021]easynode unser 知识点 WEB 根据此题先复现[GKCTF 2021]easynode这个题&#xff0c;这两个题类似 [GKCTF 2021]easynode 1.打开页面发现是登录页面&#xff0c;找到源文件里面的代码&#xff0c;分析如何进行登录&#xff0c;发现经过safeQuery()函…

外网访问公司内网服务器?

【天联】组网天联可以解决不同地区电脑与电脑、设备与设备、电脑与设备之间的信息远程通信问题。在全国各主要节点部署加速服务器&#xff0c;实现在低带宽、跨运营商的网络环境下高速访问&#xff1b;这为公司内网服务器提供了一个可行的外网访问解决方案。 在现代办公环境中…

Unet心电信号分割方法(Pytorch)

心血管疾病是一种常见病&#xff0c;严重影响人们的健康及日常生活。 近年来随着人们生活习惯的不断变化&#xff0c;心血管疾病对人们影响愈加明显&#xff0c;发病率呈现出逐年攀升的趋势&#xff0c;心血管疾病是中国城乡居民死亡的首要原因。心电图ECG已被广泛用于研究心跳…

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)复现

PHP语言在设计时忽略了Windows对字符编码转换的 Best-Fit 特性&#xff0c;导致未授权的攻击者可以通过特定字符串绕过 CVE-2012-1823 补丁&#xff0c;执行任意PHP代码&#xff0c;导致服务器失陷。 1.漏洞级别 高危 2.漏洞搜索 fofa: app"XAMPP"3.影响范围 P…

RTOS笔记--资源管理

资源管理 资源管理&#xff0c;其实就是前面介绍过的通知方式中的队列信号量互斥量等是如何访问临界资源的&#xff0c;如何做到完全互斥。 在之前举过一个例子&#xff1a;当我们使用全局变量来进行互斥操作时&#xff0c;有可能在改写全局变量时被切换使得不再互斥&#xff0…

使用thymeleaf直接渲染字符串

目录 一、依赖 二、示例代码 一、依赖 <--JAVA 8--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>2.7.18</version></dependency><-…

如何确保数据跨域交换安全、合规、可追溯性?

数据跨域交换是指在不同的组织、系统或网络之间进行数据的传输和共享。随着数字经济的发展&#xff0c;数据跨域交换在促进数据流通和创新融合方面发挥着重要作用。然而&#xff0c;这一过程也面临着诸多挑战和风险&#xff0c;例如数据安全、合规性、完整性以及责任不清晰等问…

C#操作MySQL从入门到精通(17)——使用联结

前言: 我们在查询数据的过程中有时候查询的数据不是来自一个表而是来自多个表,本文使用的测试数据如下: 本文使用了两个表student_info、address_info student_info的数据如下: address_info的数据如下: 1、内联结 所谓内联结就是求交集,两个表都有的数据才是有效数…

SSH密钥认证:实现远程服务器免密登录的两种方法|Linux scp命令详解:高效实现文件与目录的远程传输

简介&#xff1a; 服务器之间经常需要有一些跨服务器的操作&#xff0c;此时就需要我们在一台服务器上登录到另外一台服务器&#xff0c;若是人为操作时我们都可以每次输入密码进行远程登录&#xff0c;但要是程序需要跨服务器时&#xff0c;每次输入密码就不现实了&#xff0c…

Java 开发实例:Spring Boot+AOP+注解+Redis防重复提交(防抖)

文章目录 1. 环境准备2. 引入依赖3. 配置Redis4. 创建防重复提交注解5. 实现AOP切面6. 创建示例Controller7. 测试8. 进一步优化8.1 自定义异常处理8.2 提升Redis的健壮性 9. 总结 &#x1f389;欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨…

基于单片机的数控稳压开关电源研究

为了解决多种类供电的电压需求&#xff0c;克服供电电路体积大、性价比低的问题&#xff0c;复杂电路系统以单片机控制为核心&#xff0c;尝试构建单片机数控开关稳压电源的硬件平台&#xff0c;并开发软件程序&#xff0c;实现系统多种类供电电压输出的控制。实验证明&#xf…

zabbix老版本3.0.14迁移

由于之前zabbix版本过老&#xff0c;一直未能升级&#xff0c;现在一台老的服务器需要迁移&#xff0c;服务器较老&#xff0c;就不更新&#xff0c;先迁移数据&#xff0c; 下载地址&#xff1a; Zabbix Official Repository http://repo.zabbix.com/zabbix/3.0/rhel/7/x86…

「实战应用」如何用DHTMLX将上下文菜单集成到JavaScript甘特图中(一)

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求&#xff0c;是最完善的甘特图图表库。 DHTMLX Gantt是一个高度可定制的工具&#xff0c;可以与项目管理应用程序所需的其他功能相补充。在本文中您将学习如何使用自定义上…

如何使用Spring Boot框架整合Redis:超详细案例教程

目录 # 为什么选择Spring Boot与Redis整合&#xff1f; 1. 更新 pom.xml 2. 配置application.yml 3. 创建 Redis 配置类 4. Redis 操作类 5. 创建控制器 6. 启动应用程序 7. 测试 # 为什么选择Spring Boot与Redis整合&#xff1f; 将Spring Boot与Redis整合可以充分利…

自制一个Linux live固件镜像ISO可引导系统

使用母盘镜像制作两个虚拟&#xff0c;来制作一个包含基本需求的filesystem.squashfs文件&#xff0c;具体看下面的链接 使用的安装镜像 是Linux Mint 制作好的成品 https://cloud.189.cn/t/U32Mvi7FnyA3 &#xff08;访问码&#xff1a;2nbo&#xff09; 最简单制作LIVE CD…

java多线程概念

在Java多线程编程中有几个重要的概念&#xff0c;这些概念对于理解和编写正确的多线程应用程序至关重要&#xff1a; 1.线程&#xff08;Thread&#xff09;: 线程是操作系统能够进行运算调度的最小单位&#xff0c;Java通过线程实现并发执行。 2.进程&#xff08;Process&…