下面的案例中只是做一个简单的了解,不做深入理解啦
目录
一.使用Logback写日志
二.类加载器
三.XML
四.XML编写规定:DTD与schema
五.XML解析
六.XPath
七.单元测试
七.Assert(断言):检验方法结果
八.使用before与after注解备份与还原数据
九.注解
十.自定义注解
十一.注解案例:用注解模拟JUnit
使用到的部分jar包版本如下:
使用Logback写日志 把输出语句保存到文件当中 接口规范:Commons Logging(JCL)与Simple Logging Facade for java(slf4j) 日志实现框架:JUL(Java自带)、log4j、Logback(现在学习的,基于slf4j) 在使用Logger前应该做的准备工作有哪些? 1.需要导入的jar包:slf4j(规范)logback-core(核心)logback-classic(实现了完整的slf4j)logback-access(与汤猫服务器继承,提供了日志访问功能) 2.将配置文件logback.xml拷贝到src目录下 在测试类中如何使用logback产生日志文件? 1.通过LoggerFactory类的静态方法getLogger,传入本类对象创建Logger对象 2.通过Logger的info(或者其他方法记录信息)写入日志信息
配置文件:
System.out
%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%c] [%thread] : %msg%n
%d{yyyy-MM-dd HH:mm:ss} : %msg%n
D:/IDEACode/demo1/JAVA基础/src/Day36/MyLog/data%d{yyyy-MMdd}.log
public class Demo361Logback {
final static Logger LOGGER = LoggerFactory.getLogger("Demo361Logback.class");
public static void main(String[] args) {
LOGGER.info("SunCoya学习日志");
}
}
类加载器:把字节码class文件搬运到虚拟机里面 类加载时机-用到才加载 1.创建对象 2.调用静态方法 3.访问静态变量 4.使用反射创建class对象 5.初始化子类 6.java.exe 类加载过程 加载: 通过全限定名获取定义此类的二进制流 把静态存储结构转化为运行时数据结构 加载完毕则创建一个class对象 连接: 验证:检查信息有没有安全隐患 准备:为静态变量初始化值—默认 解析:加载把引用型变量需要用到的类,把符号引用变为直接引用 初始化: 初始化静态变量:变为被复制的值 加载器分类 所有加载请求都会被送到最顶层的启动类加载器,然后往下送,看那个加载器能加载 启动类加载器:虚拟机内置类加载器 平台类加载器:加载JDK特殊模块 系统类加载器:加载用户类路径上所指定的类库 自定义加载器
public class Demo362ClassLoader {
final static String FILE_STR = "Day35_Reflect_DynamicAgent\\message.properties";
public static void main(String[] args) throws IOException {
//获得系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
ClassLoader platformClassLoader = systemClassLoader.getParent();
ClassLoader bootStrapClassLoader = platformClassLoader.getParent();
System.out.println(systemClassLoader);
System.out.println(platformClassLoader);
System.out.println(bootStrapClassLoader);
//加载某一个资源文件:只能设置本模块中的路径
InputStream stream = systemClassLoader.getResourceAsStream(FILE_STR);
Properties properties = new Properties();
properties.load(stream);
System.out.println(properties);
stream.close();
}
}
XML(EXtensible markup language,可扩展(标签名字随便写)的标记性语言) 一般用来保存配置文件,缺点就是解析起来比较复杂 使用properties配置文件时遇到同键多值的情况会出现问题 xml声明规则: 1.文档声明必须是第一行,声明版本号码,编码: 2.标签必须要有一对或者是不成对的标签: 3.必须要有根标签(最外面的标签),且只能有一个 4.在标签里面可以设置属性,要与标签名隔开,属性值要用引号引起来:
zhangsan
23
小于< 大于> 且& 单引' 双引"
]]>
DTD(Document Type Definition):约束文档,后缀必须是.dtd 元素根标签必须叫书架,书架里面的元素必须是书,书能写多个 书里面有三个子标签 代表里面的元素只能是文本数据, 缺点就是不能限定数据类型 而schema可以约束具体数类型,约束能力更加强大,其本身也是一个xml文件,也受到其他xml文件的约束 编写schema约束文档,后缀名必须是xsd
dtd文件:
chema文件:
引入DTD: 1.引入本地: 2.内部引入: 3.引入网络:
XML导入DTD:
<书架>
<书>
<书名>Java从入门到起飞书名>
<作者>阿玮作者>
<售价>100w售价>
书>
<书>
<书名>Java算法真经书名>
<作者>????作者>
<售价>100w售价>
书>
书架>
使用dom4j.jar去解析xml文档 SAX解析(Simple API for XML):逐行读取,只能查不能改,但是查询效率高 DOM解析:整体加载到内存,形成树型结构,可查可改,我们学习的也是DOM解析工具 在dom思想中:attribute是属性
public class Demo363XMLoad {
final static String FILE_STR = "JAVA基础\\src\\Day36\\MyXML\\students2.xml";
public static void main(String[] args) throws DocumentException {
System.out.println("1.创建SAXReader对象");
SAXReader saxReader = new SAXReader();
System.out.println("2.调用saxReader的read方法,传入需要读取的文件,获取dom对象");
Document document = saxReader.read(new File(FILE_STR));
System.out.println(document);
System.out.println("3.通过dom获取根标签对象");
Element rootElement = document.getRootElement();
System.out.println(rootElement.getName());
System.out.println("4.通过根标签获取子标签,传入参数代表限制标签名");
List elements = rootElement.elements();
for (Element element : elements)System.out.println(element.getName());
System.out.println("5.通过标签获取属性,内容,把数据放到集合中");
ArrayList arrayList = new ArrayList<>();
for (Element element : elements) {
//获取标签属性
Attribute attribute = element.attribute("id");
String id = attribute.getText();
//获取标签
String name = element.element("name").getText();
String age = element.element("age").getText();
arrayList.add(new Student(Integer.parseInt(id),name,Integer.parseInt(age)));
}
System.out.println(arrayList);
}
}
public class Student {
private int id;
private String name;
private int age;
public Student() {
}
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
public String toString() {
return "Student{id = " + id + ", name = " + name + ", age = " + age + "}";
}
}
zhangsan
23
lisi
24
wangwu
25
Xpath技术:获取xml文档中的单个元素,依赖于dom4j 其提供了比较独特的路径思想:使用路径来定位元素节点或者是属性节点 导入jaxen.jar包(暂时未用到)
public class Demo364XPath {
public static void main(String[] args) throws DocumentException {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File(Demo363XMLoad.FILE_STR));
System.out.println("1.获取到DOM对象之后使用selectNodes方法获取节点元素");
System.out.println("2.绝对路径:从头开始一级一级往下,可以检索多个符合这一条路径的元素,用多个/表示");
List nodes = document.selectNodes("/students/student/name");
for (Node node : nodes) {System.out.println(node.getText());}
System.out.println("如果是获取单个标签,则得到第一个");
Node node = document.selectSingleNode("students/student/name");
System.out.println(node.getText());
System.out.println("3.相对路径:需要找到一个当前节点,用.表示");
Element rootElement = document.getRootElement();
nodes = rootElement.selectNodes("./student/name");
for (Node node1 : nodes) {System.out.println(node1.getText()); }
System.out.println("""
4.全文检索:直接搜索元素名,使用//,比如我的案例中可以直接使用//name
下面的写法则是搜索所有students路径下的name,不必严格一级一级往下
也可以写//student/name:表示搜索到的name一定要在student下一级
也就是说有两条杠就可以随意玩,只有一条杠就需要遵守层级规则
""");
nodes = document.selectNodes("//students//name");
for (Node node1 : nodes) {System.out.println(node1.getText()); }
System.out.println("5.属性检索,使用//@属性名检索所有的属性");
nodes = document.selectNodes("//@id");
for (Node node1 : nodes) { System.out.println(node1.getText()); }
System.out.println("6.通过特定属性检索标签:在标签后添加[@属性名]");
nodes=document.selectNodes("//student[@id]");
for (Node node1 : nodes) { System.out.println(node1.getName()); }
System.out.println("7.通过固定属性检索标签,在上面的案例基础上给属性赋值即可,下面字符串中只能用单引");
nodes = document.selectNodes("//student[@id='1']");
for (Node node1 : nodes) { System.out.println(node1.getName()); }
}
}
单元测试:针对Java中的方法的测试 编写测试方法:public void method(),一定要是非静态方法,在测试方法上使用@Test注解 左边的External Libraries中出现JUnit4 点击类名左边的绿色箭头可测试多个方法
public class Demo365JUnitTest {
@Test
public void method1(){
System.out.println("测试方法一");
}
@Test
public void method2(){
System.out.println("测试方法二");
}
@Test
public void method3(){
System.out.println("测试方法三");
}
}
public class Demo366JUnitAssert {
@Test
public void method1(){
Demo366JUnitAssert jt = new Demo366JUnitAssert();
int res = jt.add(1, 1);
//参数一:两个结果不一样的提示消息
Assert.assertEquals("这个方法出错了",2,res);
}
public int add(int a,int b){
return a*b;
}
}
public class Demo367BeforeAfter {
//在测试单元中,相对路径是在当前模块中,和类加载器一样
final static String FILE_STR = "src\\Day36\\MyLog\\a.txt";
final static String FILE_COPY ="src\\Day36\\MyLog\\aCopy.txt";
@Test
public void test(){
boolean b = new File(FILE_STR).delete();
Assert.assertTrue(b);
b=new File(FILE_STR).exists();
Assert.assertFalse(b);
System.out.println("Test,在这个方法里面做测试");
}
@Before
public void before(){
FileUtil.copy(new File(FILE_STR),new File(FILE_COPY),false);
System.out.println("before,使用这个方法初始化数据,比如数据的删除");
}
@After
public void after(){
FileUtil.copy(new File(FILE_COPY),new File(FILE_STR),false);
new File(FILE_COPY).delete();
System.out.println("after,使用这个方法还原数据,删除备份数据");
}
}
注解主要是给编译器看的,用来检测 @Deprecated:表示方法已经过时:也会给你提示替代方案 @SuppressWarnings("all"):压制(去除)警告
@SuppressWarnings("all")
public class Demo368Annotation {
public static void main(String[] args) {
int a;
}
@Deprecated
public static void method(){
System.out.println("haihai");
}
}
自定义注解:结合反射使用 能在变量上使用,也能在方法中使用
public @interface MyAnno {
//可以不写默认值
public String name()default "???";
public int age();
}
public class Demo369MyAnno {
//如果注解中只有一个属性,就可以只写值,如压制警告
@MyAnno(name = "啊?",age=20)
String aaa;
String bbb;
@MyAnno(name = "啊?",age=20)
public void method(){
System.out.println("方法一");
}
public void method2(){
System.out.println("方法二");
}
}
元注解:注解的注解 @Target:约束注解使用的地方 @Retention:申明注解的生命周期
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {}
public class Main {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException {
Class> aClass = Class.forName("Day36.Demo3610.Main");
//补个对象
Main main = new Main();
Method[] methods = aClass.getMethods();
for (Method method : methods) {
method.setAccessible(true);
if (method.isAnnotationPresent(MyTest.class)){
method.invoke(main);
}
}
}
@MyTest
public void method1(){
System.out.println("方法一");
}
@MyTest
public void method2(){
System.out.println("方法二");
}
public void method3(){
System.out.println("方法三");
}
}