单元测试、反射、注解、动态代理

news2024/11/17 13:46:03

🏡个人主页 :@ 守夜人st
🚀系列专栏:Java
…持续更新中敬请关注…
🙉博主简介:软件工程专业,在校学生,写博客是为了总结回顾一些所学知识点

目录

  • 单元测试、反射、注解、动态代理
    • 单元测试
      • 单元测试概述
      • 单元测试快速入门
      • 单元测试常用注解
    • 反射
      • 反射概述
      • 反射获取类对象
      • 反射获取成员变量
      • 反射获取方法
      • 反射的作用——绕过编译阶段为集合添加数据(泛型擦除)
      • 反射的作用——通用框架的底层原理
    • 注解
      • 注解概述
      • 自定义注解
      • 元注解
      • 注解解析
      • 注解的应用场景一:JUnit框架
    • 动态代理
      • 动态代理概述、快速入门
      • 动态代理的应用案例:做性能分析,代理的好处

单元测试、反射、注解、动态代理

单元测试

单元测试概述

单元测试就是针对最小的功能单位编写测试代码,Java程序最小功能单元是方法,因此,单元测试就是针对方法的测试,进而检查方法的正确性

我们平常采用的测试存在的弊端:

  • 只有一个main方法,如果一个方法的测试失败了,其他反复测试会受到影响

  • 无法得到测试的结果报告,需要程序员自己去观察测试是否成功

  • 无法实现自动化测试

JUnit单元测试框架:

  • JUnit是使用Java语言实现的单元测试框架,他是开源的,Java开发者都应当学习并使用JUnit编写单元测试

  • 此外,几乎所有的IDE工具都集成了JUnit,这样我们就直接可以在IDE中编写并运行JUnit单元测试

    JUnit优点:

    • JUnit可以灵活的选择执行哪些测试方法,可以一键执行全部测试方法
    • 可以生成全部方法的测试报告
    • 单元测试中的某个方法测试失败了,不影响其他测试方法的测试

单元测试快速入门

需求:使用单元测试进行业务方法预期结果、正确性测试的快速入门

  1. 将JUnit的jar包导入到项目中
  • IDEA通常整合好了JUnit框架,一般不需要导入
  • 如果IDEA没有整合好,需要自己手工导入JUnit的jar包到模块
  1. 编写测试方法:该方法必须是公共的无参数无返回值的非静态方法
  2. 在测试方法上使用@Test注解:标注该方法是一个测试方法
  3. 在测试方法中完成被测试方法的预期正确性测试
  4. 选中测试方法,选择“ JUnit运行 ”,如果测试良好是绿色,测试失败是红色
package com.shouyeren.test;

public class UserService {
    public String loginName(String loginName,String passWord){
        if ("admin".equals(loginName) && "123456".equals(passWord)){
            return "登录成功";
        }else {
            return "用户名或者密码不正确";
        }
    }

    public void selectNames(){
        System.out.println("查询所有用户名成功!");
    }
}
package com.shouyeren.test;

import org.junit.Assert;
import org.junit.Test;

public class TestUserService {
    @Test
    public void testLoginName(){
        UserService userService = new UserService();
        String rs = userService.loginName("admin","123456");

        Assert.assertEquals("您的登录业务功能可能出BUG","登录成功",rs);
    }

    @Test
    public void testSelectNames(){
        UserService userService = new UserService();
        userService.selectNames();
    }
}

在这里插入图片描述

单元测试常用注解

注解说明(JUnit4)
@Test测试方法
@Before用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次
@After用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次
@BeforeClass用来修饰静态方法,该方法会在所有测试方法执行之前执行一次
@AfterClass用来修饰静态方法,该方法会在所有测试方法执行之后执行一次
  • 开始执行的方法:初始化资源
  • 执行完之后的方法:释放资源

反射

反射概述

反射是指对于任何一个Class类,在“运行的时候”都可以直接得到这个类的全部成分

构造器对象:Constructor

成员变量对象:Field

成员方法对象:Method

这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制

反射的基本作用、关键?

  • 反射是在运行时获取类的字节码文件对象,解析获得类中全部成分
  • 反射的核心思想和关键就是:得到编译后的Class文件

反射获取类对象

获取Class类对象的三种方式:

  1. Class c1 = Class.forName(“全类名”);
  2. Class c2 = 类名.class;
  3. Class c3 = 对象.getClass();

Class类中用于获取构造器的方法

方法说明
Constructor<?>[ ] getConstructors()返回所有构造器对象的数组(只能拿public的)
Constructor<?>[ ] getDeclaredConstructors()返回所有构造器对象的数组
Constructor<?>[ ] getConstructor(Class<?>…parmeterTypes)返回单个构造器对象(只能拿public的)
Constructor<?>[ ] getDeclaredConstructors(getConstructor(Class<?>…parmeterTypes)返回单个构造器对象
package com.shouyeren.reflect;

import org.junit.Test;

import java.lang.reflect.Constructor;

public class TestStudent {
    /**
     * 获取类中的全部构造器对象(public)
     */
    @Test
    public void getConstructors(){
        Class<Student> c = Student.class;
        Constructor[] constructors = c.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "==>" + constructor.getParameterCount());
        }
    }

    /**
     * 获取类中的全部构造器对象
     */
    @Test
    public void getDeclaredConstructors(){
        Class<Student> c = Student.class;
        Constructor[] constructors = c.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "==>" + constructor.getParameterCount());
        }
    }

    /**
     * 获取某个构造器对象(public)
     */
    @Test
    public void getConstructor() throws NoSuchMethodException {
        Class<Student> c = Student.class;
        //可以添加参数
        Constructor cons = c.getConstructor(String.class,int.class);
            System.out.println(cons.getName() + "==>" + cons.getParameterCount());
    }

    /**
     * 获取某个构造器对象
     */
    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException {
        Class<Student> c = Student.class;
        //可以添加参数类型
        Constructor cons = c.getDeclaredConstructor();
        System.out.println(cons.getName() + "==>" + cons.getParameterCount());
        Constructor cons1 = c.getDeclaredConstructor(String.class,int.class);
        System.out.println(cons.getName() + "==>" + cons1.getParameterCount());
    }
}

package com.shouyeren.reflect;

public class Student {
    private String name;
    private int age;

    private Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

使用反射技术获取构造器对象并使用

  • 获取构造器的作用依然是初始化一个对象返回
符号说明
T newInstance(Object… initargs)根据指定的构造器创建对象
public void setAccessible(boolean flag)设置为true,表示取消访问检查,进行暴力反射
package com.shouyeren.reflect;

import org.junit.Test;

import java.lang.reflect.Constructor;

public class TestStudent1 {
    @Test
    public void getDeclaredConstructor() throws Exception {
        Class<Student> c = Student.class;
        //可以添加参数类型
        Constructor cons = c.getDeclaredConstructor();
        System.out.println(cons.getName() + "==>" + cons.getParameterCount());
        //私有构造器无法访问时,可以暴力反射
        cons.setAccessible(true);
        Student s = (Student) cons.newInstance();
        System.out.println(s);
        Constructor cons1 = c.getDeclaredConstructor(String.class,int.class);
        System.out.println(cons.getName() + "==>" + cons1.getParameterCount());
        Student s1 = (Student) cons1.newInstance("叶文洁", 58);
        System.out.println(s1.getName() + s1.getAge());
    }
}

反射获取成员变量

使用反射技术获取成员变量对象并使用

  • 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
  • Class类中用于获取成员变量的方法
方法说明
Field[] getFields()返回所有成员变量对象的数组(public)
Field[] getDeclaredFields()返回所有成员变量对象的数组
Field[] getField(String name)返回单个成员变量对象(public)
Field[] getDeclaredField(String name)返回单个成员变量对象
package com.shouyeren.reflect;

import org.junit.Test;

import java.lang.reflect.Field;
/**
 * | Field[] getFields()                   | 返回所有成员变量对象的数组(**public**) |
 * | Field[] getDeclaredFields()           | 返回所有成员变量对象的数组             |
 * | Field[] getField(String name)         | 返回单个成员变量对象(**public**)      |
 * | Field[] getDeclaredField(String name) | 返回单个成员变量对象                  |
 */
public class FieldDemo {

    /**
     * Field[] getDeclaredFields()           | 返回所有成员变量对象的数组             |
     */
    @Test
    public void getDeclaredFields(){
        //定位Class对象
        Class<Student> s = Student.class;
        //定位所有成员变量对象
        Field[] fields = s.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName() + "==>" + field.getType());
        }
    }


    /**
     * Field[] getFields()                   | 返回所有成员变量对象的数组(**public**) |
     */
    @Test
    public void getFields(){
        //定位Class对象
        Class<Student> s = Student.class;
        //定位所有成员变量对象
        Field[] fields = s.getFields();
        for (Field field : fields) {
            System.out.println(field.getName() + "==>" + field.getType());
        }
    }


    /**
     * Field[] getField(String name)         | 返回单个成员变量对象(**public**)
     * @throws Exception
     */
    @Test
    public void getField() throws Exception {
        //定位Class对象
        Class<Student> s = Student.class;
        //成员变量对象
        Field field = s.getField("schoolName");
        System.out.println(field.getName() + "==>" + field.getType());
    }

    /**
     * Field[] getDeclaredField(String name) | 返回单个成员变量对象                  |
     * @throws Exception
     */
    @Test
    public void getDeclaredField() throws Exception {
        //定位Class对象
        Class<Student> s = Student.class;
        //成员变量对象
        Field field = s.getDeclaredField("age");           //打开权限
        field.setAccessible(true);
        Student student = new Student("张三",20);
        //赋值
        field.set(student,18);
        //取值
        System.out.println(field.get(student));
    }

}

反射获取方法

使用反射技术获取方法对象并使用

  • 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
  • Class类中用于获取成员方法的方法
方法说明
Method[ ] getMethods()返回所有成员方法对象的数组(public)
Method[ ] getDeclaredMethods()返回所有成员方法对象的数组
Method[ ] getMethod()返回单个成员方法对象的数组(public)
Method[ ] getDeclaredMethod()返回单个指定成员方法对象的数组

反射的作用——绕过编译阶段为集合添加数据(泛型擦除)

反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素的

ArrayList<Integer> list = new ArrayList<>();
list.add(100);
list.add("字符串");//报错

泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList,泛型相当于被擦除了

package com.shouyeren.reflect;

import java.lang.reflect.Method;
import java.util.ArrayList;

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        ArrayList<Integer> list1 = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        System.out.println(list1.getClass() == list2.getClass());
        System.out.println("--------------------------------------");

        ArrayList<Integer> list3 = new ArrayList<>();
        list3.add(18);
        list3.add(20);
        //list3.add("字符串");

        Class c = list3.getClass();
        Method add = c.getDeclaredMethod("add", Object.class);
        boolean rs = (boolean) add.invoke(list3,"字符串");
        System.out.println(list3);
        System.out.println(rs);
    }
}

在这里插入图片描述

反射的作用——通用框架的底层原理

需求:给你任意一个对象,在不清楚对象字段的情况下,可以把对象的字段名称和对应值存储到文件中去

  1. 定义一个方法,可以接收任意类对象
  2. 每次收到一个对象后,需要解析这个对象的全部成员变量名称。
  3. 这个对象可能是任意的,那么怎么样才可以知道这个对象的全部成员变量名称呢
  4. 使用反射获取对象的Class文件,然后获取全部成员变量信息
  5. 遍历全部成员变量信息,然后提取本成员变量在对象中的具体值
  6. 存入成员变量名称和值到文件中
package com.shouyeren.reflect.framework;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

public class MybatisUtil {
    /**
     * 保存任意类型的对象
     * @param obj
     */
    public static void save(Object obj){
        try(PrintStream ps = new PrintStream(new FileOutputStream
                ("src/data.txt",true))) {
            //获取这个对象的全部成员变量
            Class c = obj.getClass();
            ps.println("----------------" + c.getSimpleName() + "----------------");
            Field[] fields = c.getDeclaredFields();
            for (Field field : fields) {
                String name = field.getName();
                field.setAccessible(true);
                String value = field.get(obj) + "";
                ps.println(name + " = " + value);
            }
        } catch (Exception e) {
                e.printStackTrace();
        }
    }
}
package com.shouyeren.reflect.framework;

/**
 * 提供一个通用框架,支持保存所有对象的具体信息
 */
public class ReflectDemo {
    public static void main(String[] args) {
        Student student = new Student();
        student.setName("张三");
        student.setClassName("实验一班");
        student.setAge(20);
        student.setHobby("打球");
        student.setSex('男');
        MybatisUtil.save(student);

        Teacher teacher = new Teacher();
        teacher.setName("苍老师");
        teacher.setSex('女');
        teacher.setSalary(12000);
        MybatisUtil.save(teacher);
    }
}

反射的作用:

  • 可以在运行阶段得到一个类的全部成分然后操作
  • 可以破坏封装性
  • 可以破坏泛型约束
  • 更重要的用途是适合:做Java高级框架

注解

注解概述

Java注解(Annotation)又称Java标注,是JDK5.0引入的一种注释机制

Java语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注

例如:JUnit框架中,标记了注解@Test的方法就可以被当成测试方法执行

自定义注解

自定义注解格式:

public @interface 注解名称{
    public 属性类型 属性名() default 默认值;
}

特殊属性:

  • value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写
  • 但是如果有多个属性,且多个属性没有默认值,那么value名称是不能省略的

元注解

元注解就是注解的注解

元注解有两个:

  • @Target:约束自定义注解只能在哪些地方使用
  • @Retention:声明注解的生命周期

@Target:

  • TYPE,类,接口
  • FIELD,成员变量
  • METHOD,成员方法
  • PARAMETER,方法参数
  • CONSTRUCTOR,构造器
  • LOCAL_VARIABLE,局部变量

@Retention中可使用的值定义在RetentionPolicy枚举类中,常用值如下:

  • SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
  • CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值
  • RUNTIME:注释在源码阶段、字节码文件阶段,运行阶段(开发常用)

注解解析

注解的操作中经常需要进行解析,注解的解析就是判断是否存在注解,存在注解就解析出内容

与注解解析相关的接口:

  • Annotation:注解的顶级接口,注解都是Annotation类型的对象
  • AnnotatedElement:该接口定义了与注解解析相关的解析方法

注解解析的技巧:

  • 注解在哪个成分上,就先拿哪个成分对象
  • 比如注解作用成员方法,则要获得该成员方法对应的Method对象,再拿上面的注解

注解的应用场景一:JUnit框架

模拟JUnit框架

定义若干个方法,只要加了MyTest注解,就可以在启动时被触发执行

分析:

  1. 定义一个自定义注解MyTest,只能注解方法,存活范围是一直在
  2. 定义若干个方法,只要有@MyTest注解的方法就能在启动时被触发执行,没有该注解则不能执行
package com.shouyeren.annotation;

import java.lang.annotation.*;

@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {

}
package com.shouyeren.annotation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class AnnotationTest {
    @MyTest
    public void test1(){
        System.out.println("===test1===");
    }

    public void test2(){
        System.out.println("===test2===");
    }
    @MyTest
    public void test3(){
        System.out.println("===test3===");
    }

    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        AnnotationTest test = new AnnotationTest();
        Class c = AnnotationTest.class;
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(MyTest.class)){
                method.invoke(test);
            }
        }
    }
}

动态代理

动态代理概述、快速入门

如何创建代理对象:

  • Java中代理的代表类是:java.lang.reflect.Proxy
  • Proxy提供了一个静态方法,用于为对象产生一个代理对象返回

动态代理的应用案例:做性能分析,代理的好处

需求:

模拟某企业用户管理业务,需包含用户登录,用户删除,用户查询功能,并统计每个功能的耗时

分析:

  1. 定义一个UserService表示用户业务接口,规定必须完成用户登录,用户删除,用户查询功能
  2. 定义一个UserServiceImpl实现UserService,并完成相关功能,且统计每个功能的耗时
  3. 定义测试类,创建实现类对象,调用方法
package com.shouyeren.proxy;

public interface UserService {
    String login(String loginName,String passWord);
    void deleteUsers();
    String selectUsers();
}
package com.shouyeren.proxy;

public class UserServiceImpl implements UserService{
    @Override
    public String login(String loginName, String passWord) {
        String rs = "登录名和密码错误";
        if ("admin".equals(loginName) && "132456".equals(passWord)){
            rs = "登录成功";
        }
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return rs;
    }

    @Override
    public void deleteUsers() {
        System.out.println("正在删除用户数据。。。");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String selectUsers() {
        String rs = "正在查询10000个用户数据。。。";
        try {
            Thread.sleep(2500);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return rs;
    }
}
package com.shouyeren.proxy;

import java.lang.reflect.Proxy;

public class ProxyUtil {
    public static UserService getProxy(UserService obj){

        return (UserService) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(), (proxy, method, args) -> {
                    long startTime = System.currentTimeMillis();

                    Object rs = method.invoke(obj, args);

                    long endTime = System.currentTimeMillis();
                    System.out.println(method.getName() + "方法耗时:" + (endTime-startTime)/1000 + "S");
                    return rs;
                });
    }
}
package com.shouyeren.proxy;

public class Test {
    public static void main(String[] args) {
        UserService userService = ProxyUtil.getProxy(new UserServiceImpl());
        System.out.println(userService.login("admin", "132456"));
        System.out.println(userService.selectUsers());
        userService.deleteUsers();
    }
}

动态代理的优点:

  • 可以在不改变方法源码的情况下,实现对方法功能的增加,提高了代码的复用。
  • 简化了编程 工作、提高了开发效率、同时提高了软件系统的可扩展性
  • 可以为被代理对象的所有方法做代理
    • 非常的灵活,支持任意接口类型的实现类对象做代理,也可以直接为接口本身做代理

在这里插入图片描述

感觉不错的话,动手点个赞吧!

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

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

相关文章

一篇文综合分析Fuse!

FUSE需求 究竟什么样的需求才能用到用户文件系统&#xff1f;来看一个小例子&#xff1a; 需求是这样的。在deepin的安装器中&#xff0c;安装器就会给多分出一个分区&#xff1a;数据盘。 数据盘的主要作用是让用户存放数据文件&#xff0c;也就是以前用Windows的时候D盘或者…

YoloV7

总体来说&#xff0c;YoLoV7主要可分为主干特征提取网络&#xff08;backbone&#xff09;&#xff0c;加强特征提取网络以及SPPCSPC三个部分&#xff0c;然后再加上RepConv和YoLoHead部分。输入图片640*640*3的RGB图片&#xff0c;然后卷积、标准化&#xff08;BN&#xff09;…

QT学习笔记-QT多项目系统中如何指定各项目的编译顺序

QT学习笔记-QT多项目系统中如何指定各项目的编译顺序背景环境解决思路具体操作背景 为了更好的复用程序功能以及更优雅的管理程序&#xff0c;有经验的程序员通常要对程序进行分层和模块化设计。在QT/C这个工具中同样可以通过创建子项目的方式对程序进行模块化&#xff0c;在这…

浅谈Linux下的shell--BASH

环境&#xff1a;centos7.6&#xff0c;腾讯云服务器Linux文章都放在了专栏&#xff1a;【Linux】欢迎支持订阅&#x1f339;shell的概念与作用我们已经学习并知道了操作系统实际上就是一款软件&#xff0c;一款用来管理计算机软硬件资源&#xff0c;为用户提供良好的执行环境的…

擎创喜报 | 名单公布!恭喜入选!

前言&#xff1a;企业数字化转型作为一种经营策略&#xff0c;指的是利用数字技术和数字化流程来改变企业的运营、管理、销售和服务方式&#xff0c;以适应数字化时代的发展趋势。一般来说&#xff0c;企业进行数字化出于以下几点考虑。提高效率&#xff1a;数字化改进了业务流…

人口老龄化背景下家政服务网络平台【附源码】

1 毕业论文&#xff08;设计&#xff09;版权使用授权书 本毕业论文&#xff08;设计&#xff09;作者同意学校保留并向国家有关部门或机构送交论文&#xff08;设计&#xff09;的复印件和电子版&#xff0c;允许论文&#xff08;设计&#xff09;被查阅和借阅。本人授权广西…

JAVA中比较对象是否相等的方式是什么?为什么重写equals就一定要重写hashcode?百天百题(3/100)

目录 JAVA中比较对象是否相等的方式是什么&#xff1f; 为什么重写equals就一定要重写hashcode&#xff1f; JAVA中比较对象是否相等的方式是什么&#xff1f; 在了解这个问题之前需要先知道&#xff1a; 1.如果对象相同&#xff0c;那么hashcode是一定相同的。 2.对象不同的…

哈希表

文章目录什么是哈希问题引入哈希函数直接定址法除留余数法 &#xff08;常用、重点&#xff09;哈希冲突哈希冲突的解决方法闭散列开散列unordered_map && unordered_set 封装实现哈希的应用位图布隆过滤器哈希经典面试题哈希切分位图应用布隆过滤器什么是哈希 在上一…

阿里巴巴商品详情爬虫数据字段解析 源代码分享 调用示例

返回数据代码段1"item": {"num_iid": "60840463360","title": "Slip-on Daily Urban Walking Shoes","desc_short": "","price": "$47.70","nick": "cn1522808546p…

TypeScript深度剖析:TypeScript 中类的理解?应用场景?

一、是什么 类&#xff08;Class&#xff09;是面向对象程序设计&#xff08;OOP&#xff0c;Object-Oriented Programming&#xff09;实现信息封装的基础 类是一种用户定义的引用数据类型&#xff0c;也称类类型 传统的面向对象语言基本都是基于类的&#xff0c;JavaScript …

好友管理系统--课后程序(Python程序开发案例教程-黑马程序员编著-第4章-课后作业)

实例3&#xff1a;好友管理系统 如今的社交软件层出不穷&#xff0c;虽然功能千变万化&#xff0c;但都具有好友管理系统的基本功能&#xff0c;包括添加好友、删除好友、备注好友、展示好友等。下面是一个简单的好友管理系统的功能菜单&#xff0c;如图1所示。 图1 好友管理系…

api接口详解大全

api接口详解大全?优秀的设计是产品变得卓越的原因设计API意味着提供有效的接口&#xff0c;可以帮助API使用者更好地了解、使用和集成&#xff0c;同时帮助人们有效地维护它每个产品都需要使用手册&#xff0c;API也不例外在API领域&#xff0c;可以将设计视为服务器和客户端之…

【SpringCloud】SpringCloud教程之Nacos实战(三集群配置)

目录前言一.Nacos集群逻辑图二.Nacos集群搭建1.搭建数据库&#xff0c;初始化数据库表结构2.下载Nacos3.配置Nacos3.启动Nacos4.配置启动nginx5.测试是否成功6.设置服务的nacos地址7.新增一个配置&#xff0c;查看数据看是否进行持久化了前言 在我前面两篇讲的都是单个nacos&a…

Activity的启动和结束

onCreate&#xff1a;创建活动。此时会把页面布局加载进内存&#xff0c;进入了初始状态。onStart&#xff1a;开启活动。此时会把活动页面显示在屏幕上&#xff0c;进入了就绪状态。onResume&#xff1a;恢复活动。此时活动页面进入活跃状态&#xff0c;能够与用户正常交互&am…

Vulnhub系列:FristLeaks

一、配置靶机环境以往的靶机&#xff0c;本人是在virtual box中&#xff0c;去配置&#xff0c;和vm上的kali进行联动&#xff0c;但是这个靶机需要DHCP&#xff0c;以往的方式可能不太行了&#xff0c;或者可以在virtual box中桥接成统一网卡。下面介绍下本人最有用的方法&…

2021牛客OI赛前集训营-提高组(第三场) T4扑克

2021牛客OI赛前集训营-提高组&#xff08;第三场&#xff09; 题目大意 小A和小B在玩扑克牌游戏&#xff0c;规则如下&#xff1a; 从一副52张牌&#xff08;没有大小王&#xff09;的扑克牌中随机发3张到每个玩家手上&#xff0c;每个玩家可以任意想象另外两张牌&#xff0…

Allegro如何知道单个操作命令的拼写

Allegro如何知道单个操作命令的拼写 在用Allegro做PCB设计的时候,时常需要给某些命令设置一些快捷键,但是有时候无法知道命令的拼写是什么,就无法定义到env文件里面去 如下图 如何知道上方图标的命令拼写,下面介绍两种方法 方法一 鼠标左键移动到图标的位置,就会出现命令…

【动态规划】背包问题(01背包,完全背包)

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…

JavaWeb学习-Tomcat

常用的Web服务器 ①IIS&#xff1a;Microsoft的Web服务器产品为Internet Information Services &#xff08;IIS&#xff09;&#xff0c;IIS 是允许在公共Intranet或Internet上发布信息的Web服务器。ⅡS是目前最流行的Web服务器产品之一&#xff0c;很多著名的网站都是建立在…

二进制转换之命理学习

什么是十神 运用儒家学说&#xff1a; 克我者官也&#xff1a;古代没有民主思想&#xff0c;官不是为民服务的&#xff0c;官就是克的。 对男命来说克我的是儿女&#xff0c;女儿是正官&#xff0c;儿子是偏官&#xff08;七杀&#xff09;克的厉害&#xff0c;对父亲来说有了…