一万多字拆解java中——“ 注解 ”的一切(三)(已完结)

前言:

咱们书接上回,上次按照框架讲了

第一篇,我们讲到了:

注解的引入(简单概述):在jdk5.0的时候

注解与注释的区别:

  • 注释 是为了帮助人类阅读代码,不会对程序的执行产生任何影响。
  • 注解 是为了给编译器或运行时环境提供额外的信息,可能会影响程序的编译或运行行为。

        并通过  比喻日记和标签,贴纸)和  举代码例子 的方式帮助大家更直观的了解二者的区别

③注解的重要性:

并通过  传统方式(XML配置)和   现代方式使用注解)代码比对的方式,带大家更直观的明白注解的好处

  • 简化配置
  • 提高开发效率

第二篇,我们讲到了:

一,常见的Annotation 作用:(三大作用)

 

  • 1:生成文档相关的注解:(⭐⭐⭐)

小编给大家总结了很多常见的注解,并且通过具体的代码例子,体会注解在其中发挥的作用以及该如何正确使用

 

  • 2:在编译时进行格式检查(JDK内置的三个基本注解)(⭐⭐⭐)

  

  •      2.1@Override: 限定重写父类方法,该注解只能用于方法

  

  •      2.2@Deprecated: 用于表示所修饰的元素(类,方法等)已过时。通常是因为所修饰 的结构危险或存在更好的选择

  

  •      2.3@SuppressWarnings: 抑制编译器警告

 

  • 3:跟踪代码依赖性,实现替代配置文件功能(小白可不看)

Servlet类(因为咱们主要是讲Java,而这个涉及到HTML了)

开始之前,大家可不可以给小编一个免费的赞或者关注我们一起进步啊!!!)               


三,元注解:(⭐⭐⭐⭐)

概述:

  • 元注解(Meta-annotation)是用于注解其他注解的注解。在编程语言中,如Java、C#等,
  • 注解是一种用来为代码元素(类、方法、变量等)提供额外信息或元数据的机制。
  • 而元注解则是这些注解的注解,它们可以用来定义新的注解的行为和属性。(⭐⭐⭐
  • 在Java中,有几种内置的元注解,比如 @Retention@Target@Documented@Inherited它们允许开发者指定自定义注解的相关特性,例如注解的作用范围、生命周期以及是否会被编译到文档中等。
  • JDK1.5 在 java.lang.annotation 包定义了 4 个标准的 meta-annotation 类型,它 们被用来提供对其它 annotation类型作说明。

大白话拆解:

你正在给一幅画做标记,比如说用红圈标出重要的部分,用蓝箭头指出需要特别注意的地方。这些标记帮助别人更好地理解这幅画。在编程中,我们也有类似的东西叫“注解”,它就像是给代码加上一些特殊的标记,告诉计算机或者其他程序员这段代码有什么特殊的意义或者应该怎么处理。

元注解就是给这些“标记”本身再加一个标记。就好比你在红圈旁边写上“这个红圈意味着重要信息”,或者在蓝箭头旁边说明“这个箭头指向需要注意的区域”。元注解就是用来解释我们创建的那些注解是什么意思,或者应该怎样使用。

官方定义使用的例子

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyCustomAnnotation {
    String value();
}
代码解释和总结:
  •  @Retention 和 @Target 就是元注解。
  • @Retention 指定了注解的生命周期,这里设置为 RUNTIME 表示这个注解会在运行时仍然可用。@Target 则指定了这个注解可以应用于哪些程序元素,这里是 METHOD,表示只能用于方法上。

我给大家举个简单的栗子

创建一个名为 @NeedsTesting 的注解,当你在某个方法上使用这个注解时,就表示这个方法需要被测试。为了确保这个注解能在运行时被读取,并且只能应用于方法上,

// 告诉Java这个注解应该在运行时还能被读取
@Retention(RetentionPolicy.RUNTIME)
// 指定这个注解只能用在方法上
@Target(ElementType.METHOD)
public @interface NeedsTesting {
    // 这个注解还可以带一个参数,比如测试的优先级
    int priority() default 1;
}

然后你可以在你的代码中像这样使用:
public class MyClass {

    @NeedsTesting(priority = 5)  // 标记这个方法需要高优先级的测试
    public void myMethod() {
        // 方法的实现
    }
}

(1)@Target:用于描述注解的使用范围

 可以通过  枚举类型   ElementType  的10个常量对象来指定 :

  • ETYP: 类、接口(包括注解类型)或枚举声明。
  • FIELD: 字段、枚举常量。
  • METHOD: 方法。
  • PARAMETER: 方法参数。
  • CONSTRUCTOR: 构造函数。
  • LOCAL_VARIABLE: 局部变量。
  • ANNOTATION_TYPE: 注解类型。
  • PACKAGE: 包声明。
  • TYPE_PARAMETER: 类型参数。
  • TYPE_USE: 类型使用。

举个栗子:

创建一个名为 @Author 的注解,我们希望它只能用在类和方法上。我们可以这样定义:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 指定 @Author 注解只能用于类和方法
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME) // 表示该注解将在运行时保留
public @interface Author {
    String name(); // 作者的名字
    String date() default "2024-12-26"; // 默认日期
}

在我们的代码中像这样使用 @Author 注解:

// 正确使用:应用于类
@Author(name = "张三")
public class MyClass {

    // 正确使用:应用于方法
    @Author(name = "李四", date = "2024-12-25")
    public void myMethod() {
        // 方法的实现
    }

    // 错误使用:尝试应用于字段(根据 @Target 定义,这是不允许的)
    // @Author(name = "王五") // 这行代码会导致编译错误
    private String myField;
}

代码解释和总结:

  • @Target 元注解指定了 @Author 只能用于类 (ElementType.TYPE) 和方法 (ElementType.METHOD)。如果你试着将 @Author 应用于其他类型的元素,例如字段,Java 编译器将会报错,提示你这个注解不能用于那个位置。

(2)@Retention:用于描述注解的生命周期

概述:

  • @Retention 是 Java 中的一个元注解,它用来指定自定义注解在程序中存在的时间长度,也就是它的生命周期。
  • 通过 @Retention,你可以控制注解是在编译时被丢弃、包含在编译后的字节码中但不加载到 JVM 中,还是在运行时仍然可用并可以通过反射机制读取。

大白话拆解:


你写了一封信(注解),然后你决定这封信可以在什么情况下被读到:

  • SOURCE(源代码):这封信只在你写的草稿纸上(源代码文件)可以看到,一旦你把信寄出去(编译),这封信就消失了。
  • CLASS(字节码):这封信会和你的信一起打包(编译成字节码),但是当别人收到信并打开阅读(运行程序)的时候,这封信已经被销毁了,他们看不到。
  • RUNTIME(运行时):这封信不仅会和你的信一起打包,而且当别人收到并打开阅读(运行程序)的时候,他们还能看到这封信,并且可以根据信中的指示做出相应的行动(比如执行特定的操作)。

  • 可以通过枚举类型RetentionPolicy的3个常量对象来指定 
  • SOURCE(源代码)、CLASS(字节码)、RUNTIME(运行时) 
  • 唯有RUNTIME阶段才能被反射读取到。

RetentionPolicy 的常量对象:


RetentionPolicy 枚举类型定义了3个常量,它们分别代表不同的生命周期:

  • SOURCE: 注解仅存在于源代码级别,不会被编译器处理或保留在类文件中。
  • CLASS: 注解会被编译器记录到类文件中,但在运行时不会被JVM保留,因此无法通过反射访问。
  • RUNTIME: 注解会被编译器记录到类文件中,并且会在运行时由JVM保留,所以可以通过反射机制读取。

举个栗子:

创建一个名为 @DebugInfo 的注解,我们希望它能够在运行时被读取,以便于调试工具可以获取这些信息。我们可以这样定义:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 指定 @DebugInfo 注解将在运行时保留
@Retention(RetentionPolicy.RUNTIME)
// 指定 @DebugInfo 注解只能用于方法
@Target(ElementType.METHOD)
public @interface DebugInfo {
    String value(); // 调试信息
}

我们可以在我们的代码中像这样使用 @DebugInfo 注解:

public class MyClass {

    // 使用 @DebugInfo 注解添加调试信息
    @DebugInfo("This method adds two numbers.")
    public int add(int a, int b) {
        return a + b;
    }

    // 一个简单的测试方法,用来读取并打印 @DebugInfo 注解的信息
    public static void main(String[] args) throws Exception {
        // 获取 MyClass 类的所有方法
        for (java.lang.reflect.Method method : MyClass.class.getDeclaredMethods()) {
            // 检查方法上是否有 @DebugInfo 注解
            if (method.isAnnotationPresent(DebugInfo.class)) {
                // 获取并打印 @DebugInfo 注解的值
                DebugInfo debugInfo = method.getAnnotation(DebugInfo.class);
                System.out.println("Debug Info for " + method.getName() + ": " + debugInfo.value());
            }
        }
    }
}

代码解释和总结:

  • @Retention(RetentionPolicy.RUNTIME) 元注解指定了 @DebugInfo 注解会在运行时保留,这意味着我们可以在运行时通过反射来读取这个注解。
  • 如果我们尝试将 @Retention 改为 SOURCE 或 CLASS,那么在 main 方法中尝试读取 @DebugInfo 注解将会失败,因为注解信息不会在运行时保留。

(3)@Documented:表明这个注解应该被 javadoc工具记录。

概述:

  • @Documented 是 Java 中的一个元注解,它用于指定自定义注解应该被包含在由 javadoc 工具生成的文档中。
  • 默认情况下,Java 的注解不会出现在生成的 API 文档中,但如果你希望某些注解能够帮助其他开发者理解代码的功能或用法,你可以使用 @Documented 来确保这些注解会被记录到文档中。

举个栗子:

  • 创建一个名为 @DeprecatedMethod 的注解,用来标记那些已经被废弃的方法,并且我们希望这个信息能出现在生成的 Javadoc 文档中。我们可以这样定义:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 指定 @DeprecatedMethod 注解应该被 javadoc 工具记录
@Documented
// 指定 @DeprecatedMethod 注解将在运行时保留
@Retention(RetentionPolicy.RUNTIME)
// 指定 @DeprecatedMethod 注解只能用于方法
@Target(ElementType.METHOD)
public @interface DeprecatedMethod {
    String reason() default "未提供原因"; // 废弃的原因
}
  • 在我们的代码中像这样使用 @DeprecatedMethod 注解:
/**
 * 一个示例类,包含一些方法。
 */
public class MyClass {

    /**
     * 一个已经被废弃的方法,不建议使用。
     *
     * @deprecated 请使用 {@link #newMethod} 代替。
     */
    @DeprecatedMethod(reason = "该方法已被新方法取代")
    public void oldMethod() {
        System.out.println("这是一个旧方法。");
    }

    /**
     * 新的方法,推荐使用。
     */
    public void newMethod() {
        System.out.println("这是一个新方法。");
    }
}

代码解释和总结:

  • @Documented 元注解指定了 @DeprecatedMethod 注解应该被 javadoc 工具记录。
  • 当你使用 javadoc 工具为 MyClass 生成文档时,@DeprecatedMethod 注解以及它的 reason 参数将会出现在生成的 HTML 文档中,从而帮助其他开发者了解哪些方法是不推荐使用的及其原因。

(4)@Inherited:允许子类继承父类中的注解

概述:

  • @Inherited 是 Java 中的一个元注解,它用于指定自定义注解可以被子类继承。默认情况下,Java 的注解不会自动传递给子类。如果你希望某个注解能够被子类自动继承,可以在定义注解时使用 @Inherited 元注解。

举个栗子:

  • 创建一个名为 @Versioned 的注解,用来标记类的版本信息,并且我们希望这个注解能够被子类自动继承。我们可以这样定义:
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 指定 @Versioned 注解可以被子类继承
@Inherited
// 指定 @Versioned 注解将在运行时保留
@Retention(RetentionPolicy.RUNTIME)
// 指定 @Versioned 注解只能用于类
@Target(ElementType.TYPE)
public @interface Versioned {
    String version(); // 版本号
}

在我们的代码中像这样使用 @Versioned 注解:

// 父类带有 @Versioned 注解
@Versioned(version = "1.0")
public class ParentClass {
    public void display() {
        System.out.println("这是父类的方法。");
    }
}

// 子类没有显式地添加 @Versioned 注解,但会自动继承父类的注解
public class ChildClass extends ParentClass {
    @Override
    public void display() {
        System.out.println("这是子类的方法。");
    }
}

// 一个简单的测试方法,用来读取并打印 @Versioned 注解的信息
public class TestInheritance {
    public static void main(String[] args) {
        // 获取 ParentClass 类的 @Versioned 注解
        Versioned parentVersion = ParentClass.class.getAnnotation(Versioned.class);
        if (parentVersion != null) {
            System.out.println("ParentClass version: " + parentVersion.version());
        }

        // 获取 ChildClass 类的 @Versioned 注解
        Versioned childVersion = ChildClass.class.getAnnotation(Versioned.class);
        if (childVersion != null) {
            System.out.println("ChildClass version: " + childVersion.version());
        } else {
            System.out.println("ChildClass did not inherit the @Versioned annotation.");
        }
    }
}

代码解释和总结:

  • @Inherited 元注解指定了 @Versioned 注解可以被子类继承。因此,尽管 ChildClass 没有显式地添加 @Versioned 注解,它仍然会从 ParentClass 继承这个注解。
  • 当你运行 TestInheritance 类的 main 方法时,你会看到 ChildClass 也显示了从 ParentClass 继承的版本信息。

四,自定义注解的使用(⭐⭐⭐⭐)

4.1声明自定义注解

语法格式:

【元注解】 
【修饰符】 @interface 注解名{ 
【成员列表】 
} 

  • 自定义注解可以通过四个元注解  @Retention,@Target,@Inherited,@Documented, 分别说明它的声明周期,使用位置,是否被继承,是否被生成到API文档中。
  • Annotation 的成员在 Annotation 定义中以无参数有返回值的抽象方法的形式来声 明,我们又称为配置参数。返回值类型只能是八种基本数据类型、String类型、Class 类型、enum类型、Annotation类型、以上所有类型的数组
  • 可以使用 default 关键字为抽象方法指定默认返回值
  • 如果定义的注解含有抽象方法,那么使用时必须指定返回值,除非它有默认值。格式 是“方法名 = 返回值”,如果只有一个抽象方法需要赋值,且方法名为value,可以省 略“value=”,所以如果注解只有一个抽象方法成员,建议使用方法名value。

举个栗子:

定义自定义注解:

import java.lang.annotation.*;

// 定义 TaskPriority 枚举,用于表示任务的优先级
public enum TaskPriority {
    LOW, MEDIUM, HIGH
}

// 定义 @TaskInfo 注解
@Documented // 表明这个注解应该被 javadoc 工具记录
@Inherited   // 允许子类继承父类中的注解
@Target(ElementType.TYPE) // 指定注解只能用于类
@Retention(RetentionPolicy.RUNTIME) // 指定注解将在运行时保留
public @interface TaskInfo {
    // 配置参数:任务名称,默认值为 "Unnamed Task"
    String name() default "Unnamed Task";

    // 配置参数:任务优先级,默认值为 TaskPriority.LOW
    TaskPriority priority() default TaskPriority.LOW;

    // 配置参数:任务截止日期,默认值为空字符串
    String deadline() default "";

    // 配置参数:任务描述,默认值为空字符串
    String description() default "";
}

4.2使用自定义注解

使用自定义注解:

// 父类带有 @TaskInfo 注解
@TaskInfo(
    name = "Develop Feature A",
    priority = TaskPriority.HIGH,
    deadline = "2024-12-31",
    description = "Implement the core functionality of the application."
)
public class ParentTask {

    public void execute() {
        System.out.println("Executing ParentTask.");
    }
}

// 子类没有显式地添加 @TaskInfo 注解,但会自动继承父类的注解
public class ChildTask extends ParentTask {

    @Override
    public void execute() {
        System.out.println("Executing ChildTask.");
    }
}

// 测试类,用来读取并打印 @TaskInfo 注解的信息
public class TestTaskInfo {
    public static void main(String[] args) {
        // 获取 ParentTask 类的 @TaskInfo 注解
        TaskInfo parentTaskInfo = ParentTask.class.getAnnotation(TaskInfo.class);
        if (parentTaskInfo != null) {
            printTaskInfo(parentTaskInfo, "ParentTask");
        }

        // 获取 ChildTask 类的 @TaskInfo 注解
        TaskInfo childTaskInfo = ChildTask.class.getAnnotation(TaskInfo.class);
        if (childTaskInfo != null) {
            printTaskInfo(childTaskInfo, "ChildTask");
        } else {
            System.out.println("ChildTask did not inherit the @TaskInfo annotation.");
        }
    }

    // 辅助方法,用来打印 TaskInfo 注解的信息
    private static void printTaskInfo(TaskInfo taskInfo, String className) {
        System.out.println(className + " info:");
        System.out.println("  Name: " + taskInfo.name());
        System.out.println("  Priority: " + taskInfo.priority());
        System.out.println("  Deadline: " + taskInfo.deadline());
        System.out.println("  Description: " + taskInfo.description());
    }
}

大白话拆解:

你正在管理一个项目,每个任务都有名字、优先级、截止日期和描述。为了帮助团队成员更好地理解每个任务,你决定在代码中为每个任务添加一些标签(注解)。这些标签可以帮助你在编写代码时记住任务的详细信息,并且可以在生成文档时自动包含这些信息。

  • @Retention:这个标签决定了它能存在多久。我们可以选择让它只存在于源代码中(SOURCE),编译后仍然保留在字节码中(CLASS),或者在程序运行时也可以访问(RUNTIME)。在这个例子中,我们选择了 RUNTIME,这样我们可以在运行时通过反射读取这些标签。
  • @Target:这个标签决定了它可以贴在哪里。我们可以选择让它只能贴在类上(TYPE),方法上(METHOD),字段上(FIELD)等。在这个例子中,我们选择了 TYPE,所以它只能用在类上。
  • @Inherited:这个标签告诉 Java:“如果一个类有这个标签,那么它的所有子类也会自动拥有这个标签。” 这样,如果你有一个父类的任务信息,子类也可以继承这些信息,而不需要重复定义。
  • @Documented:这个标签告诉 javadoc 工具:“请把这个标签也加到生成的文档中。” 这样,其他开发者在查看文档时也能看到这些任务信息。
  • 配置参数:注解中的配置参数就像标签上的信息。你可以指定任务的名字、优先级、截止日期和描述。这些参数可以用默认值,也可以在使用时指定具体的值。例如,如果我们不提供任务的名字,它将默认为 “Unnamed Task”。

4.3读取和处理自定义注解

1. 定义自定义注解
创建一个名为 @TaskInfo 的注解,用来标记任务的相关信息。这个注解将包含任务的名称、优先级(枚举类型)、截止日期(字符串),并且可以在运行时被读取和处理。

import java.lang.annotation.*;

// 定义 TaskPriority 枚举,用于表示任务的优先级
public enum TaskPriority {
    LOW, MEDIUM, HIGH
}

// 定义 @TaskInfo 注解
@Retention(RetentionPolicy.RUNTIME) // 指定注解将在运行时保留
@Target(ElementType.TYPE)           // 指定注解只能用于类
public @interface TaskInfo {
    String name() default "Unnamed Task";      // 任务名称,默认值为 "Unnamed Task"
    TaskPriority priority() default TaskPriority.LOW; // 任务优先级,默认值为 LOW
    String deadline() default "";              // 任务截止日期,默认值为空字符串
    String description() default "";           // 任务描述,默认值为空字符串
}

2. 使用自定义注解
在一个类中使用 @TaskInfo 注解,

// 使用 @TaskInfo 注解标记一个任务
@TaskInfo(
    name = "Develop Feature A",
    priority = TaskPriority.HIGH,
    deadline = "2024-12-31",
    description = "Implement the core functionality of the application."
)
public class TaskA {

    public void execute() {
        System.out.println("Executing TaskA.");
    }
}

// 另一个任务,没有显式地添加 @TaskInfo 注解
public class TaskB {

    public void execute() {
        System.out.println("Executing TaskB.");
    }
}

3. 读取和处理自定义注解
为了读取和处理这些注解,我们需要使用 Java 的反射 API 来获取注解信息并根据需要进行处理。可以创建一个工具类 TaskManager 来管理任务。

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;

public class TaskManager {

    // 辅助方法,用来打印 TaskInfo 注解的信息
    private static void printTaskInfo(TaskInfo taskInfo, String className) {
        System.out.println(className + " info:");
        System.out.println("  Name: " + taskInfo.name());
        System.out.println("  Priority: " + taskInfo.priority());
        System.out.println("  Deadline: " + taskInfo.deadline());
        System.out.println("  Description: " + taskInfo.description());
    }

    // 方法:读取并处理所有带有 @TaskInfo 注解的任务
    public static void processTasks(List<Class<?>> taskClasses) {
        for (Class<?> taskClass : taskClasses) {
            // 检查类上是否有 @TaskInfo 注解
            if (taskClass.isAnnotationPresent(TaskInfo.class)) {
                TaskInfo taskInfo = taskClass.getAnnotation(TaskInfo.class);
                printTaskInfo(taskInfo, taskClass.getSimpleName());

                // 创建任务实例并执行
                try {
                    Object taskInstance = taskClass.getDeclaredConstructor().newInstance();
                    if (taskInstance instanceof Task) {
                        ((Task) taskInstance).execute();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println(taskClass.getSimpleName() + " does not have @TaskInfo annotation.");
            }
        }
    }

    // 接口:定义任务必须实现的方法
    public interface Task {
        void execute();
    }
}

4. 测试注解的读取和处理
最后,我们编写一个测试类 TestTaskManager,来验证 TaskManager 是否能正确读取和处理带有 @TaskInfo 注解的任务。

public class TestTaskManager {

    public static void main(String[] args) {
        // 创建一个任务列表,包含 TaskA 和 TaskB
        List<Class<?>> tasks = new ArrayList<>();
        tasks.add(TaskA.class);
        tasks.add(TaskB.class);

        // 调用 TaskManager 处理任务
        TaskManager.processTasks(tasks);
    }
}

大白话拆解:

  • 你正在管理一个项目,每个任务都有名字、优先级、截止日期和描述。为了帮助团队成员更好地理解每个任务,你决定在代码中为每个任务添加一些标签(注解)。这些标签可以帮助你在编写代码时记住任务的详细信息,并且可以在运行时自动处理这些信息。
  • 定义注解:我们创建了一个名为 @TaskInfo 的注解,它可以标记任务的名称、优先级、截止日期和描述。我们使用 @Retention(RetentionPolicy.RUNTIME) 来确保这个注解可以在程序运行时被读取。
  • 使用注解:我们在 TaskA 类上使用了 @TaskInfo 注解,指定了任务的具体信息。而 TaskB 类没有使用这个注解,所以我们希望它不会被处理。
  • 读取和处理注解:我们编写了一个 TaskManager 类,它会遍历所有任务类,检查它们是否带有 @TaskInfo 注解。如果有,它会读取注解中的信息并打印出来,然后调用任务的 execute() 方法来执行任务。如果没有注解,它会提示该任务没有相关信息。
  • 测试:我们编写了一个 TestTaskManager 类来测试 TaskManager 是否能正确读取和处理带有 @TaskInfo 注解的任务。运行这个测试类时,你会看到 TaskA 的信息被打印出来,并且它的 execute() 方法被执行,而 TaskB 则没有相关信息。

ok,我们注解也彻底完结了。希望对大家有帮助。

键盘敲烂,月薪过万!!!

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

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

相关文章

Java开发-后端请求成功,前端显示失败

文章目录 报错解决方案1. 后端未配置跨域支持2. 后端响应的 Content-Type 或 CORS 配置问题3. 前端 request 配置问题4. 浏览器缓存或代理问题5. 后端端口未被正确映射 报错 如下图&#xff0c;后端显示请求成功&#xff0c;前端显示失败 解决方案 1. 后端未配置跨域支持 …

MarkItDown的使用(将Word、Excel、PDF等转换为Markdown格式)

MarkItDown的使用&#xff08;将Word、Excel、PDF等转换为Markdown格式&#xff09; 本文目录&#xff1a; 零、时光宝盒&#x1f33b; 一、简介 二、安装 三、使用方法 3.1、使用命令行形式 3.2、用 Python 调用 四、总结 五、参考资料 零、时光宝盒&#x1f33b; &a…

akamai3.0 wizzair 网站 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我删…

kubernetes Gateway API-1-部署和基础配置

文章目录 1 部署2 最简单的 Gateway3 基于主机名和请求头4 重定向 Redirects4.1 HTTP-to-HTTPS 重定向4.2 路径重定向4.2.1 ReplaceFullPath 替换完整路径4.2.2 ReplacePrefixMatch 替换路径前缀5 重写 Rewrites5.1 重写 主机名5.2 重写 路径5.2.1 重新完整路径5.2.1 重新部分路…

likeAdmin架构部署(踩坑后的部署流程

1、gitee下载 https://gitee.com/likeadmin/likeadmin_java.git 自己克隆 2、项目注意 Maven&#xff1a;>3.8 ❤️.9 (最好不要3.9已经试过失败 node &#xff1a;node14 (不能是18 已经测试过包打不上去使用14的换源即可 JDK&#xff1a;JDK8 node 需要换源 npm c…

宠物行业的出路:在爱与陪伴中寻找增长新机遇

在当下的消费市场中&#xff0c;如果说有什么领域能够逆势而上&#xff0c;宠物行业无疑是一个亮点。当人们越来越注重生活品质和精神寄托时&#xff0c;宠物成为了许多人的重要伴侣。它们不仅仅是家庭的一员&#xff0c;更是情感的寄托和生活的调剂。然而&#xff0c;随着行业…

Java 堆排序原理 图文详解 代码逻辑

文章目录 1. 时间复杂度 & 空间复杂度2. 大顶堆、小顶堆3. 具体步骤 & 原理1. 判断是否满足堆的性质2. 维护堆的性质3. 交换位置 4. 代码实现 1. 时间复杂度 & 空间复杂度 时间复杂度: O(nlogn) 建堆时间复杂度: O(n) 排序时间复杂度: O(nlogn)空间复杂度: O(1) …

计算机网络|数据流向剖析与分层模型详解

文章目录 一、网络中的数据流向二、计算机网络通信模型1.OSI 模型2.TCP/IP 模型3.TCP/IP五层模型3.1 分层架构描述3.2各层地址结构3.3UDP数据包报头结构 三、总结 一、网络中的数据流向 在计算机网络中&#xff0c;数据的流向是指数据从发送端到接收端的传输路径。数据流向涉及…

ensp、HCL环境部署vm版

ensp、HCL环境部署vm版 前言部署环境vmware安装下载镜像创建虚拟机安装ensp、HCL创建快照 问题此平台不支持虚拟化的 AMD-V/rvi。 前言 因为我换了电脑&#xff0c;锐龙版的win11&#xff0c;我按照以前的思路去装软件&#xff0c;发现有很多问题&#xff0c;特别是跳hyper-v弹…

鸿蒙项目云捐助第二十九讲云捐助项目云数据库商品的批量增加功能实现

鸿蒙项目云捐助第二十九讲云捐助项目云数据库商品的批量增加功能实现 关于鸿蒙云捐助项目&#xff0c;前面的内容已使用云函数&#xff0c;云数据库分别实现云捐助项目首页中的项分类导航&#xff0c;底部导航&#xff0c;轮播图功能&#xff0c;这里继续实现云数据库加载捐赠…

【LeetCode: 83. 删除排序链表中的重复元素 + 链表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Spring源码_05_IOC容器启动细节

前面几章&#xff0c;大致讲了Spring的IOC容器的大致过程和原理&#xff0c;以及重要的容器和beanFactory的继承关系&#xff0c;为后续这些细节挖掘提供一点理解基础。掌握总体脉络是必要的&#xff0c;接下来的每一章都是从总体脉络中&#xff0c; 去研究之前没看的一些重要…

2024-12-29-sklearn学习(25)无监督学习-神经网络模型(无监督) 烟笼寒水月笼沙,夜泊秦淮近酒家。

文章目录 sklearn学习(25) 无监督学习-神经网络模型&#xff08;无监督&#xff09;25.1 限制波尔兹曼机25.1.1 图形模型和参数化25.1.2 伯努利限制玻尔兹曼机25.1.3 随机最大似然学习 sklearn学习(25) 无监督学习-神经网络模型&#xff08;无监督&#xff09; 文章参考网站&a…

BUG分析 - 重启有时失败

1. 倒查版本 1.0_11 - ok1.0_12 - fail 2.对比1.0_11和1.0_12 失败时的日志 ================================== 1.0_11 ============================== 2024-12-26 09:46:51.886 INFO [26332] [ThreadPLCPool::in

git注意事项

提交代码的备注 feat : 开发 新增功能 fix: 修复 git相关 1. git安装及全局用户设置 Git安装 npm install git -ggit修改用户名邮箱密码 git config --global --replace-all user.name "要修改的用户名" git config --global --replace-all user.email"要修改…

LeetCode每日三题(六)数组

一、最大子数组和 自己答案&#xff1a; class Solution {public int maxSubArray(int[] nums) {int begin0;int end0;if(numsnull){//如果数组非空return 0;}else if(nums.length1){//如果数组只有一个元素return nums[0];}//初值选为数组的第一个值int resultnums[0];int i…

一个通用的居于 OAuth2的API集成方案

在现代 web 应用程序中&#xff0c;OAuth 协议是授权和认证的主流选择。为了与多个授权提供商进行无缝对接&#xff0c;我们需要一个易于扩展和维护的 OAuth 解决方案。本文将介绍如何构建一个灵活的、支持多提供商的 OAuth 系统&#xff0c;包括动态 API 调用、路径参数替换、…

小程序配置文件 —— 15 页面配置

页面配置 小程序的页面配置&#xff0c;也称为局部配置&#xff0c;每一个小程序页面也可以使用自己的 .json 文件来对页面的窗口表现进行配置&#xff1b; 需要注意的是&#xff1a;页面配置文件的属性和全局配置文件中的 window 属性几乎一致&#xff0c;只不过这里不需要额…

【从零开始入门unity游戏开发之——C#篇37】进程、线程和C# 中实现多线程有多种方案

文章目录 进程、线程和C#多线程一、进程的基本概念二、线程的基本概念三、C#中的多线程1、为什么需要多线程&#xff1f;2、*C# 中如何实现多线程**2.1 **使用 Thread 类**&#xff08;1&#xff09;示例&#xff08;2&#xff09;线程休眠&#xff08;3&#xff09;设置为后台…

评分模型在路网通勤习惯分析中的应用——提出问题(1)

1、问题的由来、目标和意义 最近一段时间和公司其它业务部门讨论时&#xff0c;发现一个有趣的交通路网问题&#xff0c;车辆从S点行驶到V点共用时40分钟&#xff0c;这段时间内路网中的卡口摄像头识别到了车辆通过的信息。如下图所示&#xff1a; 设计师需要通过这些有限的路…