注解【元数据,自定义注解等概念详解】(超简单的好吧)
注解的理解与使用
- 注解的释义
- 元数据的含义
- 基础阶段常见的注解
- 注解的作用(包括但不限于)
- 教你读懂注解内部代码内容
- 五种元注解
- 尝试解读简单注解
- ==我当时的疑惑点==
- 自定义注解
- 自定义注解举例
- 注解的原理
- 总结
注解的释义
我们都知道注释是拿来给程序员看的,而注解就是给程序(或者说JVM)看的。
注解(Annotation)是代码级别的说明,它是JDK 1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。注解是Java语言中的一种元数据形式,它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明。

元数据的含义
在Java中,元数据的含义是指描述Java类、接口、字段和方法等元素的数据。这些数据提供了关于Java程序元素的额外信息,可以用于反射、注解处理、代码生成等场景。通过元数据,我们可以在运行时获取和操作程序元素的属性、注解等信息,从而实现更灵活和动态的编程能力。
基础阶段常见的注解
我们在基础阶段常见的注解并没有多少,很少用到复杂注解,
| 注解 | Value |
|---|---|
@Override(重写或者覆盖) | 一般放在方法前面,表示方法在子类中重写了超类中的方法 |
@Deprecated | 可放在类、方法或字段前面,表示一个类、方法或字段已经过时了,不应该再使用 |
@SuppressWarnings | 一般放在程序代码靠前位置,抑制编译器产生的警告,这个注解后面有大括号是可以传参的,一般图方便就是写个“all” |
@Native | 一般放在方法前面,指示一个方法是native方法,即由本地代码实现的方法 |
@Test | 一般用于测试,可以不用启动整个项目就能调用部分代码 |
注解的作用(包括但不限于)
标记检查:
注解可以用来标记一些需要被检查的代码,以便进行静态检查或动态检查。
代码生成:
注解可以被用来生成代码,如JUnit注解可以根据测试方法定义生成测试用例。
生成文档:
特定的注解可以用来生成对应文档,例子是在注释里的注解
拿最后一个举个例子
编写一个演示类
package budiu.budiu;/*** 这是一个名字为DocDemo的类** @Author:罗不丢* @Version:1.0*/public class DocDemo {/*** @param name* @return java.lang.String**/public String play (String name){return name+"正在玩";}
}
注意编码格式别搞错,有中文的把UTF-8换成GBK

用javadoc命令生成文档

就会生成一堆的前端文件,可以当做文档查看

教你读懂注解内部代码内容
在想要了解注解的内部代码,我们要先了解五种元注解(元注解的意思是注解的最基本组成部分,任何注解都要由它们组成)
五种元注解
@Retention:
它只有一个参数:RetentionPolicy,用于指定注解的生命周期。
这个参数有三个可能的值:
RetentionPolicy.SOURCE(注解仅在源代码中存在,编译时会被丢弃),
RetentionPolicy.CLASS(注解在编译时会被保留,在JVM中运行时不可见)
RetentionPolicy.RUNTIME(注解在运行时还会存在,可以通过反射机制读取它的信息)。
@Target:
它有一个参数:ElementType,用于指定注解可以应用到的Java元素类型。
例如,方法可以被注解,字段可以被注解,甚至注解本身也可以被注解。
ElementType包含多种可能的值,如ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE等。
@Documented:
这个元注解没有参数。它的作用是表示使用该注解的注解信息能够被javadoc或类似工具文档化。
@Inherited:
这个元注解也没有参数。表示被它修饰的注解具有继承性,即如果一个类声明了被@Inherited修饰的注解,那么它的子类也将具有这个注解。
注意:不是注解继承父注解,而是子类继承父类里的注解。
@Repeatable:
这个元注解是Java 1.8引入的,它表示一个注解可以被重复使用在一个声明上。它有一个参数,这个参数是用来定义该注解的“容器”注解类型,用于存储重复注解的数据。(还没怎么了解过)
尝试解读简单注解
这里以最简单的@Override注解(JDK1.8版本)为引入
/** Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*/package java.lang;import java.lang.annotation.*;/*** Indicates that a method declaration is intended to override a* method declaration in a supertype. If a method is annotated with* this annotation type compilers are required to generate an error* message unless at least one of the following conditions hold:* 指示方法声明旨在重写* 超类型中的方法声明。如果方法被注释*需要此注释类型编译器才能生成错误*消息,除非至少满足以下条件之一:*** <ul><li>* The method does override or implement a method declared in a* supertype.* 该方法会重写或实现在* 超类型。* </li><li>* The method has a signature that is override-equivalent to that of* any public method declared in {@linkplain Object}.* 该方法具有覆盖等效于* 在 {@linkplain Object} 中声明的任何公共方法。* </li></ul>** @author Peter von der Ahé* @author Joshua Bloch* @jls 9.6.1.4 @Override* @since 1.5*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
除去注释后,代码并不算长,我们只需要了解三行,
@Target(ElementType.METHOD):
这是一个元注解,它用来指明Override注解可以用在什么地方。在这个例子中,它表示Override只能用在方法上。ElementType.METHOD表示这个注解的目标是方法。
@Retention(RetentionPolicy.SOURCE):
这是另一个元注解,用来指明注解的保留策略。这里指定的是RetentionPolicy.SOURCE,意味着这个注解只保留在源代码中,编译成.class文件时它将被丢弃。也就是说,这个注解在运行时是不可见的。
public @interface Override:
这定义了一个名为Override的注解接口。@interface是用来声明一个注解的关键字。这个接口是公开的(public),意味着它可以被任何人访问。
再试着解读一个
/*** Indicates that the named compiler warnings should be suppressed in the* annotated element (and in all program elements contained in the annotated* element). Note that the set of warnings suppressed in a given element is* a superset of the warnings suppressed in all containing elements. For* example, if you annotate a class to suppress one warning and annotate a* method to suppress another, both warnings will be suppressed in the method.* 表示应在* 带注释的元素(以及包含在带注释的* 元素)。 请注意,给定元素中禁止显示的警告集是* 在所有包含元素中禁止显示的警告的超集。 为* 例如,如果您对一个类进行注释以禁止显示一个警告并注释一个警告* 方法来抑制另一个,两个警告都会在该方法中被禁止。*** <p>As a matter of style, programmers should always use this annotation* on the most deeply nested element where it is effective. If you want to* suppress a warning in a particular method, you should annotate that* method rather than its class.**作为风格问题,程序员应该始终使用此注解* 在最深嵌套的元素上,它有效。 如果你想* 在特定方法中禁止警告,您应该注释* 方法而不是它的类。* @author Josh Bloch* @since 1.5* @jls 4.8 Raw Types* @jls 4.12.2 Variables of Reference Type* @jls 5.1.9 Unchecked Conversion* @jls 5.5.2 Checked Casts and Unchecked Casts* @jls 9.6.3.5 @SuppressWarnings*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {/*** The set of warnings that are to be suppressed by the compiler in the* annotated element. Duplicate names are permitted. The second and* successive occurrences of a name are ignored. The presence of* unrecognized warning names is <i>not</i> an error: Compilers must* ignore any warning names they do not recognize. They are, however,* free to emit a warning if an annotation contains an unrecognized* warning name.** <p> The string {@code "unchecked"} is used to suppress* unchecked warnings. Compiler vendors should document the* additional warning names they support in conjunction with this* annotation type. They are encouraged to cooperate to ensure* that the same names work across multiple compilers.* @return the set of warnings to be suppressed*/String[] value();
}
这个注解是Java的@SuppressWarnings注解,它的定义解释了它的功能和用法。现在,我们来详细解读一下这个注解:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}):
这是@SuppressWarnings注解的元注解,指明了它可以用于什么类型的Java元素。具体来说,它可以用于类、字段、方法、参数、构造器和局部变量。它的作用范围非常广泛。
@Retention(RetentionPolicy.SOURCE):
这个元注解表示@SuppressWarnings注解的保留策略是SOURCE,也就是说它仅在源代码中存在,编译时会被丢弃。因此,这个注解不会影响运行时的行为。
public @interface SuppressWarnings:
这定义了名为SuppressWarnings的注解。当开发者想要抑制编译器产生的某些警告时,可以使用这个注解。
String[] value();:
这是@SuppressWarnings注解的唯一 一个元素。它是一个字符串数组,表示要抑制的警告的名称。例如,如果你想要抑制未经检查的转换警告,你可以使用"unchecked"字符串。编译器会忽略这些特定的警告。需要注意的是,这里提到编译器应该忽略它们不认识的警告名称,但是也可以自由选择在遇到不识别的警告名称时发出警告。
我当时的疑惑点
在解读SuppressWarnings注解时,为什么最后一段的大括号里就定义了一个字符串数组,一点逻辑都看不出来,要按照之前的思维来说,它怎么识别到字符串并判断抑制特定警告的,不应该有一些内部方法来完成吗?

其实在Java编译器中,当解析和处理Java代码时,会检查代码上的注解。当编译器遇到@SuppressWarnings注解时,它会查看注解中的value数组,这些值表示需要抑制的警告类型。
编译器内部会有一个警告名称与警告类型的映射逻辑。当编译器遇到特定的代码模式或情况时,它会生成相应的警告。当存在@SuppressWarnings注解时,编译器会检查生成的警告名称是否匹配注解中指定的名称,如果匹配,则不会将该警告显示给开发者。
需要注意的是,这个匹配和抑制逻辑是由编译器实现的,而不是由注解本身实现的。不同的编译器可能会对@SuppressWarnings注解中的警告名称有不同的处理方式,但通常都会遵循Java语言规范中定义的行为。
虽然@SuppressWarnings注解本身只是一个标记,但通过编译器的逻辑处理,它能够实现警告的抑制功能。

所以我们不太需要关注注解的逻辑,就单纯把它理解成一种给编译器识别的标识符号就好。
自定义注解
除了官方提供的注解,我们也可以自定义注解,并使用自定义注解。
自定义注解的一些规范:
注解定义:
注解使用@interface关键字进行定义。
元注解:
为你的自定义注解提供元注解,特别是@Target和@Retention,以明确你的注解的用途和生命周期。
成员变量:
注解中的成员变量代表注解的参数。这些成员变量只能是基本类型、String、Class、枚举类型、注解类型,或者这些类型的数组。
默认值:
为注解的成员变量提供一个默认值。
命名规范:
注解的名称应该是描述性的,并且应该使用名词。同时,为了避免混淆,建议为注解名称加上一个特定的前缀。
自定义注解举例
自定义注解的例子——@RepeatableHint。这个注解的目的是给开发者提供一个可重复的提示信息。
首先,定义 Hint 注解:

import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) //会保留到运行时阶段
@Target(ElementType.TYPE) //限制使用范围是类,枚举,接口
public @interface Hint { String value();
}
接着,定义 RepeatableHint 注解:
import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) //会保留到运行时阶段
@Target(ElementType.TYPE) //限制使用范围是类,枚举,接口
public @interface RepeatableHint { Hint[] hints() default {}; //算是个嵌套吧,但底层仍是字符串数组
}
注意这里 RepeatableHint 注解中定义了一个名为 hints 的成员,它的类型是 Hint[],默认值为空数组。这样就可以在使用 RepeatableHint 注解时,重复使用 Hint 注解。
然后在需要的类或者接口或枚举类上使用这些注解:
@RepeatableHint(hints={@Hint("这是一个测试类的提示1"),@Hint("提示2")
})
public class TestClass { public static void main(String[] args) { // 获取TestClass的Class对象 Class<TestClass> testClass = TestClass.class; // 判断TestClass是否带有RepeatableHint注解 if (testClass.isAnnotationPresent(RepeatableHint.class)) { // 获取RepeatableHint注解对象 RepeatableHint repeatableHint = testClass.getAnnotation(RepeatableHint.class); // 获取所有的Hint注解对象 Hint[] hints = repeatableHint.hints(); // 遍历并打印所有的提示信息 for (Hint hint : hints) { System.out.println(hint.value()); } } }
}
在处理这些注解时,可以通过反射获取到所有的 Hint 注解,并对其进行处理。例如,可以在程序启动时,通过解析这些注解,将提示信息打印到日志中或者进行其他处理。

注解的原理
注解的原理基于Java的反射机制。
注解本质:
注解本质上是一个接口,它继承了java.lang.annotation.Annotation接口。当我们定义一个注解时,实际上定义了一个新的接口。
动态代理:
当我们通过反射获取注解时,返回的对象实际上是Java运行时生成的动态代理对象。这意味着我们调用注解的方法时,实际上是在调用动态代理对象上的方法。
AnnotationInvocationHandler:
这是Java内部用于处理注解调用的一个类。当我们通过动态代理对象调用注解的方法时,最终会调用AnnotationInvocationHandler的invoke方法。这个方法会从一个叫做memberValues的Map中索引出对应的值。
memberValues的来源:
memberValues中的数据来源于Java的常量池。这就是为什么我们可以在注解中定义一些常量,然后这些常量的值会被存储在Java的常量池中。
元注解的角色:
元注解如@Retention, @Target等,它们的作用是描述注解的特性。例如,@Retention定义了注解的生命周期,@Target定义了注解可以应用的目标。
运行时处理:
大部分注解的处理都是在运行时完成的。例如,框架可能会在运行时扫描某个特定的注解,并根据该注解的属性修改框架的行为。
总的来说,注解提供了一种元编程的方式。我们可以在不改变原有代码逻辑的情况下,通过添加注解来改变代码在编译后或者运行时的行为。而这一切都是基于Java的反射机制以及动态代理技术实现的。
总结
虽然注解在Java SE阶段用的很少,但在框架学习中,比如SpringBoot中将会成为常客,我们也会从面向对象编程逐渐转化为面向注解编程🤭🤭🤭🤭🤭。

相关文章:
注解【元数据,自定义注解等概念详解】(超简单的好吧)
注解的理解与使用 注解的释义元数据的含义基础阶段常见的注解注解的作用(包括但不限于)教你读懂注解内部代码内容五种元注解尝试解读简单注解我当时的疑惑点 自定义注解自定义注解举例 注解的原理总结 注解的释义 我们都知道注释是拿来给程序员看的&…...
vue-pdf在vue框架中的使用
在components目录下新建PdfViewer/index.vue vue-pdf版本为4.3.0 <template><div :id"containerId" v-if"hasProps" class"container"><div class"right-btn"><div class"pageNum"><input v-m…...
Wordpress页面生成器:Elementor 插件制作网站页面教程(图文完整)
本文来教大家怎么使用Wordpress Elementor页面编辑器插件来自由创建我们的网页内容。很多同学在面对建站的时候,一开始都是热血沸腾信心满满的,等到实际上手的时候就会发现有很多问题都是无法解决的,希望本篇Elementor插件使用指南能够帮助到你。 Wordpress Elementor页面编…...
完全随机设计的方差分析
一、说明 实验设计在科学研究中发挥着至关重要的作用,使研究人员能够从数据中得出有意义的结论。一种常见的实验设计是完全随机设计(CRD),其特征是将实验单元随机分配到治疗组。CRD 的方差分析 (ANOVA) 是一种统计技术,…...
035、目标检测-物体和数据集
之——物体检测和数据集 目录 之——物体检测和数据集 杂谈 正文 1.目标检测 2.目标检测数据集 3.目标检测和边界框 4.目标检测数据集示例 杂谈 目标检测是计算机视觉中应用最为广泛的,之前所研究的图片分类等都需要基于目标检测完成。 在图像分类任务中&am…...
【开源】基于Vue.js的社区买菜系统的设计和实现
项目编号: S 011 ,文末获取源码。 \color{red}{项目编号:S011,文末获取源码。} 项目编号:S011,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 数据中心模块2.1…...
【双指针】复写0
复写0 1089. 复写零 - 力扣(LeetCode) 给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。 注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上…...
记录一些涉及到界的题
文章目录 coppersmith的一些相关知识题1 [N1CTF 2023] e2Wrmup题2 [ACTF 2023] midRSA题3 [qsnctf 2023]浅记一下 coppersmith的一些相关知识 上界 X c e i l ( 1 2 ∗ N β 2 d − ϵ ) X ceil(\frac{1}{2} * N^{\frac{\beta^2}{d} - \epsilon}) Xceil(21∗Ndβ2−ϵ) …...
Linux秋招面试题
自己在秋招过程中遇到的Linux相关的面试题 linux查找含有“xxxx”的文件名 将/path/to/search替换为要搜索的目录路径,xxxx表示要匹配的文件名模式,其中xxxx是你要查找的字符串。这个命令将会在指定路径下递归地查找所有文件名中包含给定字符串的文件 …...
OPPO发布AndesGPT大模型;Emu Video和Emu Edit的新突破
🦉 AI新闻 🚀 OPPO发布全新ColorOS 14及自主训练的AndesGPT大模型 摘要:OPPO在2023 OPPO开发者大会上发布了全新的ColorOS 14,并正式推出了自主训练的安第斯大模型(AndesGPT)。AndesGPT拥有对话增强、个人…...
2311rust,到46版本更新
1.43.0稳定版 项(item)片段 在宏中,可用项片段把项插值到特征,实现和extern块的块体中.如: macro_rules! mac_trait {($i:item) > {trait T { $i }} } mac_trait! {fn foo() {} }这生成: trait T {fn foo() {} }围绕原语的推导类型 改进了围绕原语,引用和二进制操作的推…...
Rust根据条件删除相邻元素:dedup
文章目录 示例dedup_bydedup_by_key Rust系列:初步⚙所有权⚙结构体和枚举类⚙函数进阶⚙泛型和特征⚙并发和线程通信 示例 Rust中的动态数组Vec提供了dedup函数,用于删除相邻重复元素。此外,还提供了dedup_by和dedup_by_key,可…...
2023年(第六届)电力机器人应用与创新发展论坛-核心PPT资料下载
一、峰会简介 大会以“聚焦电力机器人创新、助力行业数字化转型、促进产业链协同发展”为主题,展示电力机器人产业全景创新技术,探讨数字化战略下电力机器人应用前景和发展趋势。为加快推进电力机器人应用拓新,助力电网数字化转型升级&#…...
Android BitmapFactory.decodeResource读取原始图片装载成原始宽高Bitmap,Kotlin
Android BitmapFactory.decodeResource读取原始图片装载成原始宽高Bitmap,Kotlin fun getOriginalBitmap(resId: Int): Bitmap {val options BitmapFactory.Options()options.inJustDecodeBounds true //只解析原始图片的宽高,不decode原始文件装载到内…...
阿里云服务器 手动搭建WordPress(CentOS 8)
前提条件 已创建Linux操作系统的ECS实例,并且手动部署LNMP环境,具体操作,请参见手动部署LNMP环境(CentOS 8)。本教程使用的相关资源版本如下。 实例规格:ecs.c6.large 操作系统:公共镜像CentO…...
竞赛 题目:基于深度学习的中文对话问答机器人
文章目录 0 简介1 项目架构2 项目的主要过程2.1 数据清洗、预处理2.2 分桶2.3 训练 3 项目的整体结构4 重要的API4.1 LSTM cells部分:4.2 损失函数:4.3 搭建seq2seq框架:4.4 测试部分:4.5 评价NLP测试效果:4.6 梯度截断…...
CCF ChinaSoft 2023 论坛巡礼|软件测试产教研融合论坛
2023年CCF中国软件大会(CCF ChinaSoft 2023)由CCF主办,CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办,将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…...
浅谈WPF之控件模板和数据模板
WPF不仅支持传统的Windows Forms编程的用户界面和用户体验设计,同时还推出了以模板为核心的新一代设计理念。在WPF中,通过引入模板,将数据和算法的“内容”和“形式”进行解耦。模板主要分为两大类:数据模板【Data Template】和控…...
微信小程序会议OA首页-开发说明创建项目关于flex布局关于尺寸单位(rpx)关于WXS轮播图会议信息
目录 1. 创建项目 2. 关于flex布局 3. 关于尺寸单位(rpx) 4. 关于WXS 4. 轮播图 5. 会议信息 1. 创建项目 基于微信原生开发工具,稳定版 Stable Build (1.06.22010310) 创建项目前,请确定有小程序测试账号 使用向导创建一个…...
Linux上编译和安装SOFA23.06
前言 你可以直接使用编译安装好的SOFA版本Installing from all-included binaries (v23.06.00): 如果你想自己编译,可以看我下面写的内容,不过绝大多数是从官网来的,如果和官网有出入,建议还是以官网为准。 在Linux下…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
