【SpringMVC】自定义注解

news2024/11/23 17:07:52

🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚

🌟在这里,我要推荐给大家我的专栏《Spring MVC》。🎯🎯

🚀无论你是编程小白,还是有一定基础的程序员,这个专栏都能满足你的需求。我会用最简单易懂的语言,带你走进Spring MVC的世界,让你从零开始,一步步成为JAVA大师。🚀🏆

🌈让我们一起在SpringMVC的世界里畅游吧!🌈🌈

👉点击这里,就可以查看我的主页啦!👇👇

Java方文山的个人主页

🎁如果感觉还不错的话请记得给我点赞哦!🎁🎁

💖期待你的加入,一起学习,一起进步!💖💖

请添加图片描述

 

目录

一、前言

1.1.什么是注解

1.2.注解的用处

1.3.注解的原理

二、注解的分类

2.1.JDK基本注解

2.1.1.@Override

2.1.2.@SuppressWarnings

2.2.JDK元注解

2.2.1.@Retention

2.2.2.@Target

2.2.3.@Inherited

2.2.4.@Documented

2.3.自定义注解

2.3.1.自定义注解的分类

三、注解取值的应用

3.1.前期准备工作

3.2.案例一(获取类与方法上的注解值)

3.3. 案例二(获取类属性上的注解属性值)   

3.4. 案例三(获取参数修饰注解对应的属性值)

四、自定义注解案例


一、前言

1.1.什么是注解

 Annontation是Java5开始引入的新特征,中文名称叫注解。

它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。为程序的元素(类、方法、成员变量)加上更直观、更明了的说明,这些说明信息是与程序的业务逻辑无关,并且供指定的工具或框架使用。Annontation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。

Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。

 

1.2.注解的用处

  •  生成文档。这是最常见的,也是java 最早提供的注解。常用的有@param @return 等
  • 跟踪代码依赖性,实现替代配置文件功能。比如Dagger 2 依赖注入,未来java 开发,将大量注解配置,具有很大用处;
  • 在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。

1.3.注解的原理

注解本质是一个继承了Annotation 的特殊接口,其具体实现类是Java 运行时生成的动态代理类。而我们通过反射获取注解时,返回的是Java 运行时生成的动态代理对象$Proxy1。通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler 的invoke 方法。该方法会从memberValues 这个Map 中索引出对应的值。而memberValues 的来源是Java 常量池。

 

二、注解的分类

2.1.JDK基本注解

2.1.1.@Override

      java.lang.Override 是一个标记类型注解,它被用作标注方法。它说明了被标注的方法重写了父类的方法,起到了断言的作用。如果我们使用了这种注解在一个没有覆盖父类方法的方法时,java 编译器将以一个编译错误来警示。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Override是给javac(java编译器)看的,编译完以后就@Override注解就没有价值了,@Override注解在源代码中有用,编译成.class文件后@Override注解就没有用了,因此@Override的Retention的属性值是RetentionPolicy.SOURCE。

 

2.1.2.@SuppressWarnings

@SuppressWarnings是给javac(java编译器)看的,编译器编译完java文件后,@SuppressWarnings注解就没有用了,所以@SuppressWarnings的Retention的属性值是RetentionPolicy.SOURCE。

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
 
    String[] value();
}

2.2.JDK元注解

看完以上的JDK基本注解你是否更蒙了!?为什么注解类里面还有注解,那其实是JDK的元注解。

所有元注解定义在java.lang.annotation包下面,其中Annotation是注解的基本接口,所有的注解都继承这个接口

java.lang.annotation 提供了四种元注解,专门注解其他的注解(在自定义注解的时候,需要使用到元注解)

2.2.1.@Retention

指定注解的生命周期(源码、class文件、运行时)或是称作定义注解的保留策略。

该元注解中有三个属性值

@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含


@Retention(RetentionPolicy.CLASS) //默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得


@Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取到

 下面我用别人写好的注解来给大家演示:

@Retention(RetentionPolicy.SOURCE) 

@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE})
public @interface Slf4j {
    java.lang.String topic() default "";
}

 这是Slf4j的注解,用了元注解@Retention(RetentionPolicy.SOURCE) ,说明该注解仅存在于源码中,class文件中不包括我们来看看。

 确实如此我们的源码中有@Slf4j但是字节码文件中却没有,这就是该元注解以及属性的作用。

 用到最多的还是@Retention(RetentionPolicy.RUNTIME),下面我们来看一下该元注解的使用。

@java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Documented
@org.springframework.web.bind.annotation.Mapping
public @interface RequestMapping {
    java.lang.String name() default "";

    @org.springframework.core.annotation.AliasFor("path")
    java.lang.String[] value() default {};

    @org.springframework.core.annotation.AliasFor("value")
    java.lang.String[] path() default {};

    org.springframework.web.bind.annotation.RequestMethod[] method() default {};

    java.lang.String[] params() default {};

    java.lang.String[] headers() default {};

    java.lang.String[] consumes() default {};

    java.lang.String[] produces() default {};
}

这是注解RequestMapping,因为@Retention中所填写的是RetentionPolicy.RUNTIME,所以被该注解所修饰的类/方法/属性就可以在运行时可以通过反射获取到。

2.2.2.@Target

指定被修饰的Annotation指定注解使用的目标范围(类、方法、字段等)。

刚刚在上面我们提到了一个关键信息,被@RequestMapping注解所修饰的类/方法/属性,那我们怎么知道又怎么决定那些注解可以用于类/方法/属性呢?就是通过元注解@Target来决定。

元注解作用目标范围
@Target(ElementType.TYPE)   接口、类
@Target(ElementType.FIELD)   属性
@Target(ElementType.METHOD)    方法
@Target(ElementType.PARAMETER) 方法参数
@Target(ElementType.CONSTRUCTOR)构造函数
@Target(ElementType.LOCAL_VARIABLE) 局部变量
@Target(ElementType.ANNOTATION_TYPE) 注解
@Target(ElementType.PACKAGE) 

注意:可以指定多个位置,例如:
@Target({ElementType.METHOD, ElementType.TYPE}),也就是此注解可以在方法和类上面使用

不相信的同学可以回过头看看上面的代码中有没有Target哦!

2.2.3.@Inherited

指定子类可以继承父类的注解,只能是类上的注解,方法和字段的注解不能继承。即如果父类上的注解是@Inherited修饰的就能被子类继承。

当父类上的注解被@Inherited修饰时,子类可以继承该注解。下面是一个示例代码来演示这个概念:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface MyAnnotation {
    String value();
}

@MyAnnotation("我是父类的注解")
class ParentClass {
}


class ChildClass extends ParentClass {
}

 class Main {
    public static void main(String[] args) {
        // 获取父类上的注解
        MyAnnotation parentAnnotation = ParentClass.class.getAnnotation(MyAnnotation.class);
        System.out.println("获取父类上的注解: " + parentAnnotation.value());

        // 获取子类上的注解
        MyAnnotation childAnnotation = ChildClass.class.getAnnotation(MyAnnotation.class);
        System.out.println("获取子类上的注解: " + childAnnotation.value());
    }
}

如果我们没有用@Inherited会怎么样呢?

会抛出java.lang.NullPointerException异常,因为子类无法继承父类的注解。

 

2.2.4.@Documented

指定被修饰的该Annotation可以被javadoc工具提取成文档.

在Java中,注解(Annotation)是一种用于为代码添加元数据的方式。它们可以提供有关代码元素的信息,例如类、方法或变量。通过使用注解,开发人员可以在编译时或运行时对代码进行处理。

@Documented是Java中的一个注解属性,它指定被修饰的注解是否可以被Javadoc工具提取成文档。当一个注解被@Documented修饰时,它的目标元素(例如类、方法或字段)的相关文档中将包含该注解的描述。

这个属性对于生成API文档非常有用。当使用Javadoc工具生成API文档时,它会扫描源代码中的注解,并提取注解的描述信息。如果一个注解被@Documented修饰,那么它的描述信息将被包含在生成的API文档中,以便其他开发人员能够了解该注解的用途和作用。

总结一下,@Documented注解的作用是确保被修饰的注解可以被Javadoc工具提取成文档,并在生成的API文档中显示注解的描述信息。这样可以帮助其他开发人员更好地理解和使用你的代码。

 

小贴士:在Java 8中,引入了一些新的元注解,用于提供额外的功能和配置。以下是一些主要的元注解及其作用

元注解作用
@FunctionalInterface用于指示接口是一个函数式接口,即只有一个抽象方法的接口。
@Deprecated用于标记不推荐使用的元素、类或方法,表示它们已经过时。
@SuppressWarnings用于抑制编译器产生警告信息,可以应用于类、方法或字段上。
@SafeVarargs用于启用或禁用可变参数类型的堆分配,确保在使用可变参数时不会发生堆污染。
@NonNull用于标记不允许为null的元素、方法或构造函数的返回类型。
@CheckReturnValue用于指示方法的调用者必须检查并处理方法的返回值,而不是忽略它。
@Override用于指示子类覆盖了父类的方法,但并不需要重新编译父类的方法。
@Immutable用于指示一个不可变的类、接口或枚举类型,即它们的实例一旦创建就不能被修改。
@Inherited用于指示一个注解可以被子类继承。
@Repeatable用于在注解上使用重复注解,即可以在一个地方多次使用同一个注解。
@SafeVarargs (JEP 276)用于启用或禁用可变参数类型的堆分配,确保在使用可变参数时不会发生堆污染。 (JEP 276: "Unchecked Var Args")

 以上信息源于网络,更多细节请参考官方文档。

JDK官方文档icon-default.png?t=N7T8https://docs.oracle.com/en/java/javase/20/

 

2.3.自定义注解

自定义注解类编写的一些规则:

  1.    Annotation 类型定义为@interface, 所有的Annotation 会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口。
  2.   参数成员只能用public 或默认(default) 这两个访问权修饰。语法:类型  属性名()  [default 默认值];      default表示默认值 ,也可以不编写默认值的.
  3.   参数成员只能用基本类型byte、short、char、int、long、float、double、boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这一些类型的数组.
  4.   要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation 对象,因为你除此之外没有别的获取注解对象的方法。
  5.   注解也可以没有定义成员,,不过这样注解就没啥用了。

注意: 自定义注解需要使用到元注解。

  • 注解方法不能有参数。
  • 注解方法的返回类型局限于原始类型,字符串,枚举,注解,或以上类型构成的数组。
  • 注解方法可以包含默认值。

 

2.3.1.自定义注解的分类

注解分类(根据Annotation是否包含成员变量,可以把Annotation分为两类):

标记Annotation:
没有成员变量的Annotation; 这种Annotation仅利用自身的存在与否来提供信息

 

元数据Annotation:
包含成员变量的Annotation; 它们可以接受(和提供)更多的元数据;

三、注解取值的应用

3.1.前期准备工作

TranscationModel枚举类

public enum  TranscationModel {
    Read, Write, ReadWrite
}

小贴士什么是枚举类?枚举类的作用是什么?

枚举类是Java中一种特殊的数据类型,用于定义一组固定的命名常量。枚举类型提供了一种更强大、更安全和更易读的方式来表示一组相关的常量。在Java中,枚举类型是通过关键字`enum`来定义的。

枚举类的作用是提供一种类型安全的方式来表示一组固定的值,避免使用数字或字符串常量时可能出现的错误。通过使用枚举类型,可以限制变量只能取预定义的值,并且可以在代码中使用这些常量的名称来提高可读性和可维护性。

MyAnnotation1自定义注解类

/**
 * MyAnnotation1注解可以用在类、接口、属性、方法上
 * 注解运行期也保留
 * 不可继承
 */
@Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation1 {
    String name();
}

MyAnnotation2自定义注解类


/**
 *  MyAnnotation2注解可以用在方法上
 *  注解运行期也保留
 *  不可继承
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2 {
    TranscationModel model() default TranscationModel.ReadWrite;
}

MyAnnotation3自定义注解类


/**
 * MyAnnotation3注解可以用在方法上
 * 注解运行期也保留
 * 可继承
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation3 {
    TranscationModel[] models() default TranscationModel.ReadWrite;
}

TestAnnotation自定义注解类

//@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {
    String value() default "默认value值";

    String what() default "这里是默认的what属性对应的值";
}

IsNotNull自定义注解类

/**
 非空注解:使用在方法的参数上,false表示此参数可以为空,true不能为空
 */
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsNotNull {
    boolean value() default false;
}

3.2.案例一(获取类与方法上的注解值)

Demo1测试类

/**
 * 获取类与方法上的注解值
 */
@MyAnnotation1(name = "abc")
public class Demo1 {

    @MyAnnotation1(name = "xyz")
    private Integer age;

    @MyAnnotation2(model = TranscationModel.Read)
    public void list() {
        System.out.println("list");
    }

    @MyAnnotation3(models = {TranscationModel.Read, TranscationModel.Write})
    public void edit() {
        System.out.println("edit");
    }
}

Demo1Test测试类

public class Demo1Test {
    @Test
    public void list() throws Exception {
//        获取类上的注解
        MyAnnotation1 annotation1 = Demo1.class.getAnnotation(MyAnnotation1.class);
        System.out.println(annotation1.name());//abc

//        获取方法上的注解
        MyAnnotation2 myAnnotation2 = Demo1.class.getMethod("list").getAnnotation(MyAnnotation2.class);
        System.out.println(myAnnotation2.model());//Read

//        获取属性上的注解
        MyAnnotation1 myAnnotation1 = Demo1.class.getDeclaredField("age").getAnnotation(MyAnnotation1.class);
        System.out.println(myAnnotation1.name());// xyz
    }

    @Test
    public void edit() throws Exception {
        MyAnnotation3 myAnnotation3 = Demo1.class.getMethod("edit").getAnnotation(MyAnnotation3.class);
        for (TranscationModel model : myAnnotation3.models()) {
            System.out.println(model);//Read,Write
        }
    }
}

 运行list方法结果:

 运行edit方法结果:



3.3. 案例二(获取类属性上的注解属性值)   

Demo2测试类

/**
 * 获取类属性上的注解属性值
 */
public class Demo2 {
    @TestAnnotation(value = "这就是value对应的值_msg1", what = "这就是what对应的值_msg1")
    private static String msg1;

    @TestAnnotation("这就是value对应的值1")
    private static String msg2;

    @TestAnnotation(value = "这就是value对应的值2")
    private static String msg3;

    @TestAnnotation(what = "这就是what对应的值")
    private static String msg4;
}

Demo2Test测试类

public class Demo2Test {
    @Test
    public void test1() throws Exception {
        TestAnnotation msg1 = Demo2.class.getDeclaredField("msg1").getAnnotation(TestAnnotation.class);
        System.out.println(msg1.value());
        System.out.println(msg1.what());
    }

    @Test
    public void test2() throws Exception{
        TestAnnotation msg2 = Demo2.class.getDeclaredField("msg2").getAnnotation(TestAnnotation.class);
        System.out.println(msg2.value());
        System.out.println(msg2.what());
    }

    @Test
    public void test3() throws Exception{
        TestAnnotation msg3 = Demo2.class.getDeclaredField("msg3").getAnnotation(TestAnnotation.class);
        System.out.println(msg3.value());
        System.out.println(msg3.what());
    }

    @Test
    public void test4() throws Exception{
        TestAnnotation msg4 = Demo2.class.getDeclaredField("msg4").getAnnotation(TestAnnotation.class);
        System.out.println(msg4.value());
        System.out.println(msg4.what());
    }
}

  运行test1方法结果:

  运行test2方法结果:

  运行test3方法结果:

  运行test4方法结果:

总结:如果我们注解上没有指定是value还是what默认就是value,如果只想转递一个参数又不想默认是value那就需要指定what=""即可。

3.4. 案例三(获取参数修饰注解对应的属性值)

Demo3测试类

public class Demo3 {

    public void hello1(@IsNotNull(true) String name) {
        System.out.println("hello:" + name);
    }

    public void hello2(@IsNotNull String name) {
        System.out.println("hello:" + name);
    }
}

Demo3Test测试类

public class Demo3Test {

    @Test
    public void hello1() throws Exception {
        Demo3 demo3 = new Demo3();
        for (Parameter parameter : demo3.getClass().getMethod("hello1", String.class).getParameters()) {
            IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
            if(annotation != null){
                System.out.println(annotation.value());//true
            }
        }
    }

    @Test
    public void hello2() throws Exception {
        Demo3 demo3 = new Demo3();
        for (Parameter parameter : demo3.getClass().getMethod("hello2", String.class).getParameters()) {
            IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
            if(annotation != null){
                System.out.println(annotation.value());//false
            }
        }
    }

    @Test
    public void hello3() throws Exception {
//        模拟浏览器传递到后台的参数 解读@requestParam
        String name = "zs";
        Demo3 demo3 = new Demo3();
        Method method = demo3.getClass().getMethod("hello1", String.class);
        for (Parameter parameter : method.getParameters()) {
            IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
            if(annotation != null){
                System.out.println(annotation.value());//true
                if (annotation.value() && !"".equals(name)){
                    method.invoke(demo3,name);
                }
            }
        }
    }
}

运行hello1方法结果:

运行hello2方法结果:

运行hello3方法结果:

如果我们属性不为true,或者名字不为zs会怎样?

总结:这个案例像不像我们的注解@RequestParam必须传递参数,除非指定required为false就可与不传参数,我们这个案例也是如此。

四、自定义注解案例

在写项目的过程中,肯定遇到过记录日志的功能要求,这时候我们就可以根据这个要求建立一个自定义注解类,只有被该注解修饰的方法就会走AOP切面类进行日志保存。

MyLog自定义注解类

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
    String desc();
}

MyLogAspect切面类

@Component
@Aspect
public class MyLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(MyLogAspect.class);

    /**
     * 只要用到了com.javaxl.p2.annotation.springAop.MyLog这个注解的,就是目标类
     */
    @Pointcut("@annotation(com.csdn.xw.annotation.aop.MyLog)")
    private void MyValid() {
    }

    @Before("MyValid()")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        logger.debug("[" + signature.getName() + " : start.....]");
        System.out.println("[" + signature.getName() + " : start.....]");

        MyLog myLog = signature.getMethod().getAnnotation(MyLog.class);
        logger.debug("【目标对象方法被调用时候产生的日志,记录到日志表中】:"+myLog.desc());
        System.out.println("【目标对象方法被调用时候产生的日志,记录到日志表中】:" + myLog.desc());
    }
}

Controller层代码

@Component
public class LogController {

    @RequestMapping("/mylog")
    @MyLog(desc = "这是结合spring aop知识,讲解自定义注解应用的一个案例")
    public void testLogAspect(){
        System.out.println("这里随便来点啥");
    }
}

 

请添加图片描述

到这里我的分享就结束了,欢迎到评论区探讨交流!!

💖如果觉得有用的话还请点个赞吧 💖

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MMrotate_dev 1.x训练自己的数据集

因为MMRotate dev 1.x 新增了PSC角度编码器以及RTMDet目标检测算法,而之前从官网下载的MMRotate是main分支,没有新增的东西,所以重新搞了一下,以此记录。 环境配置 1.创建虚拟环境 注意:如果之前安装了MMRotate的其…

基于小程序的理发店预约系统

一、项目背景及简介 现在很多的地方都在使用计算机开发的各种管理系统来提高工作的效率,给人们带来很多的方便。计算机技术从很大的程度上解放了人们的双手,并扩大了人们的活动范围,是人们足不出户就可以通过电脑进行各种事情的管理。信息系…

pycharm安装jupyter,用德古拉主题,但是输入行全白了,看不清,怎么办?

问题描述 今天换了以下pycharm主题,但是jupyter界面输入代码行太白了,白到看不清楚这行的字,更不知道写的是什么,写到哪了,这还是挺烦人的,其他都挺正常的。 问题分析 目前来看有两个原因: 1、…

深化产教融合,知了汇智助力高校数字化人才培养

随着数字经济的不断深入和发展,数字人才短缺的问题逐渐凸显,根据相关报告,目前我国数字人才缺口在2500万到3000万左右,且缺口仍在不断扩大。为了满足数字经济的发展需求,如何培养出具备创新型、复合型、应用型能力的数…

C++学习笔记一(重载、类)

C 1、函数重载2、类2.1、类的方法和属性2.2、类的方法的定义2.3、构造器和析构器2.4、类的实例化2.5、基类与子类2.6、类的public、protected、private继承2.7、类的方法的重载2.8、子类方法的覆盖2.9、继承中的构造函数和析构函数 1、函数重载 函数重载大概可以理解为&#x…

再次理解Android账号管理体系

目录 ✅ 0. 需求 📂 1. 前言 🔱 2. 使用 2.1 账户体系前提 2.2 创建账户服务 2.3 操作账户-增删改查 💠 3. 源码流程 ✅ 0. 需求 试想,自己去实现一个账号管理体系,该如何做呢? ——————————…

竞赛 基于大数据的时间序列股价预测分析与可视化 - lstm

文章目录 1 前言2 时间序列的由来2.1 四种模型的名称: 3 数据预览4 理论公式4.1 协方差4.2 相关系数4.3 scikit-learn计算相关性 5 金融数据的时序分析5.1 数据概况5.2 序列变化情况计算 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 &…

2004-2020年中小企业板上市公司财务报表股票交易董事高管1200+变量数据及说明

2004-2020年中小企业板上市公司财务报表股票交易董事高管1200变量数据及说明 1、时间:2004-2020年 2、范围:中小企业板上市公司,具体名单参看下文链接内数据预览 3、指标:1200变量 变量说明、证券代码、证券代码-字符串、年份…

HTML基础标签 CSS选择器 JavaScript基础语法 WebAPI_ 页面设计 HTTP协议

第 1 题(简答题) 题目名称: 编写博客, 总结 HTML 中的常用标签用法 题目内容: 编写博客, 总结 HTML 中的常用标签用法 第 2 题(简答题) 题目名称: image 标签的 alt 和 title 属性有什么…

基于红黑树对map和set容器的封装

本章代码gitee仓库:map和set模拟实现、stl_map_set_tree源码 文章目录 🐱1. 红黑树的泛型🐈1.1 红黑树节点🐈1.2 红黑树迭代器🐈1.3 仿函数 🐯2. 对set的封装🦄3. 对map的封装 🐱1. …

android获取设备的IMEI号

在Android 8.0 (API级别26)和更高版本的平台上的 ,64位数字(表示为十六进制字符串),对于应用程序签名密钥、用户和设备的每个组合都是唯一的。ANDROID_ID的值由签名密钥和用户限定作用域。如果在设备上执行出厂重置或如果APK签名密钥更改,则该…

【校招VIP】前端操作系统之存储管理加密

考点介绍 加密算法有很多,如不可逆的摘要算法MD5、SHA(安全哈希算法),可逆的Base64编码,对称加密算法DES、AES,还有非对称加密算法DH、RSA等。那是不是说明我们可以使用任何一种加密算法就能保证网站的安全…

认养一头牛———众筹+合伙人商业模式解析

2016年成立以来,认养一头牛致力于打造数字化乳业第一品牌,只为一杯好牛奶。公司在创立三年内完成了10个亿销售目标,被业界称为新消费品牌黑马,一举闯入互联网新消费梯队的视线。未来三年,认养一头牛将着力打造全国最大…

【精品】将两个字符串进行加密和解密的Java工具类

原理 使用一个分隔符将两个字符串连接在一起,并对连接后的字符串进行加密。加密过程中,首先生成一个随机下标列表,然后根据随机下标打乱字符串的顺序,并使用Base64进行编码。解密过程中,根据之前生成的随机下标列表将…

Definition and properties of the Gamma function

See https://math.libretexts.org/Bookshelves/Analysis/Complex_Variables_with_Applications_(Orloff)/14%3A_Analytic_Continuation_and_the_Gamma_Function/14.02%3A_Definition_and_properties_of_the_Gamma_function 勒让德倍元公式(Legendre duplication fo…

无涯教程-JavaScript - N函数

描述 N函数返回一个转换为数字的值。 语法 N (value) 争论 Argument描述Required/OptionalValue 要转换的值或对值的引用。 N转换下表中列出的值。 Required 值 N的返回值一个数字那个数字日期,采用Microsoft Excel中可用的内置日期格式之一该日期的序列号 TRUE 1 FALSE…

微视网媒:新媒体时代的宣传与营销新范式

随着数字科技的快速发展,新媒体已经成为了现代社会中不可或缺的一部分。其中,微视网媒作为新兴的网络媒体形态,正在改变着传统的宣传和营销模式,为企业和个人提供了全新的推广平台。本文将对微视网媒的优势、应用场景以及案例进行…

免费开箱即用的微鳄任务管理系统

编者按:基于天翎低代码平台实现的微鳄365任务管理系统,包括有发起任务、重点关注、日程、项目管理等功能,支持私有化部署,免费开箱即用。任务管理系统是组织工作中不可或缺的工具,可以提高工作效率、促进协作、增强任务…

GTS 中testPeakPssOfAllApps fail 详解

0. 前言 GTS 在测试 case armeabi-v7a GtsMemoryHostTestCases 的时候出现下面异常,本文总结一下。 com.google.android.memory.gts.AllAppsMemoryHostTest#testPeakPssOfAllApps 1. error log 09-14 10:16:34 I/TestFailureListener: FailureListener.testFaile…

第十届IEEE电气工程与自动化国际学术论坛(IFEEA 2023)

第十届IEEE电气工程与自动化国际学术论坛(IFEEA 2023) 2023 10th International Forum on Electrical Engineering and Automation IFEEA论坛属一年一度的国际学术盛会。因其影响力及重要性,IFEEA论坛自创建筹办以来,便受到国内…