下面的案例中只是做一个简单的了解,不做深入理解啦
目录
一.使用Logback写日志
二.类加载器
三.XML
四.XML编写规定:DTD与schema
五.XML解析
六.XPath
七.单元测试
七.Assert(断言):检验方法结果
八.使用before与after注解备份与还原数据
九.注解
十.自定义注解
十一.注解案例:用注解模拟JUnit
使用到的部分jar包版本如下:
文章来源地址https://www.toymoban.com/news/detail-766853.html
一.使用Logback写日志
使用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(或者其他方法记录信息)写入日志信息
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- appender标签用于设置输出位置与输出格式 -->
<!-- 控制台输出,CONSOLE表示可以输出到控制台 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--可以改为error-->
<target>System.out</target>
<encoder charset="UTF-8">
<!-- 输出日志记录格式 %d是日期 level表示日志级别 c表示当前操作的类 thread是线程名 %msg%n是显示消息加换行 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%c] [%thread] : %msg%n</pattern>
</encoder>
</appender>
<!-- 输出文件日志 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder charset="UTF-8">
<pattern>%d{yyyy-MM-dd HH:mm:ss} : %msg%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志输出路径,每天产生一个文件-->
<fileNamePattern>D:/IDEACode/demo1/JAVA基础/src/Day36/MyLog/data%d{yyyy-MMdd}.log</fileNamePattern>
</rollingPolicy>
</appender>
<!--
level设置日志输出级别 ref标识输出位置,表示可以输出到控制台与File文件
All表示全打印,OFF表示全部不打印(也可以用来关闭日志)
一般写INFO与DEBUG,高于这个级别的,比如ERROR也会输出
-->
<root level="All">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
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
XML(EXtensible markup language,可扩展(标签名字随便写)的标记性语言) 一般用来保存配置文件,缺点就是解析起来比较复杂 使用properties配置文件时遇到同键多值的情况会出现问题 xml声明规则: 1.文档声明必须是第一行,声明版本号码,编码:<?xml version="1.0" encoding="UTF-8" ?> 2.标签必须要有一对<name></name>或者是不成对的标签:<name/> 3.必须要有根标签(最外面的标签),且只能有一个 4.在标签里面可以设置属性,要与标签名隔开,属性值要用引号引起来:<student id="1"><student/>
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<student id="1">
<name>zhangsan</name>
<age>23</age>
<!--特殊符号-->
<special>小于< 大于> 且& 单引' 双引"</special>
<!--使用CD快捷键加入CDATA模块-->
<special><![CDATA[<&'">]]></special>
</student>
</students>
四.XML编写规定:DTD与schema
DTD(Document Type Definition):约束文档,后缀必须是.dtd <!ELEMENT 书架 (书+)> 元素根标签必须叫书架,书架里面的元素必须是书,书能写多个 <!ELEMENT 书 (书名,作者,售价)> 书里面有三个子标签 <!ELEMENT 书名 (#PCDATA)> 代表里面的元素只能是文本数据, 缺点就是不能限定数据类型 而schema可以约束具体数类型,约束能力更加强大,其本身也是一个xml文件,也受到其他xml文件的约束 编写schema约束文档,后缀名必须是xsd
dtd文件:
<!ELEMENT 书架 (书+)>
<!ELEMENT 书 (书名,作者,售价)>
<!ELEMENT 书名 (#PCDATA)>
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>
chema文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!--xmlns:当前schema文件被谁约束 targetNamespace:地址名字-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.itcast.cn/"
elementFormDefault="qualified">
<xs:element name="书架">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="书">
<xs:complexType>
<xs:sequence>
<xs:element name="书名" type="xs:string"/>
<xs:element name="作者" type="xs:string"/>
<xs:element name="售价" type="xs:double"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
引入DTD: 1.引入本地:<!DOCTYPE 根元素名 SYSTEM 'DTD文件的路径'> 2.内部引入:<!DOCTYPE 根元素名称[dtd文件内容]> 3.引入网络:<!DOCTYPE 根元素名称 PUBLIC "DTD文件名称" "DTD文档的URL"
XML导入DTD:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE 书架 SYSTEM 'book.dtd'>
<!--引入之后直接左尖括号就能生成-->
<书架>
<书>
<书名>Java从入门到起飞</书名>
<作者>阿玮</作者>
<售价>100w</售价>
</书>
<书>
<书名>Java算法真经</书名>
<作者>????</作者>
<售价>100w</售价>
</书>
</书架>
五.XML解析
使用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<Element> elements = rootElement.elements();
for (Element element : elements)System.out.println(element.getName());
System.out.println("5.通过标签获取属性,内容,把数据放到集合中");
ArrayList<Student> 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 + "}";
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<student id="1">
<name>zhangsan</name>
<age>23</age>
</student>
<student id="2">
<name>lisi</name>
<age>24</age>
</student>
<student id="3">
<name>wangwu</name>
<age>25</age>
</student>
</students>
六.XPath
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<Node> 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("测试方法三");
}
}
七.Assert(断言):检验方法结果
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;
}
}
八.使用before与after注解备份与还原数据
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("方法二");
}
}
文章来源:https://www.toymoban.com/news/detail-766853.html
十一.注解案例:用注解模拟JUnit
元注解:注解的注解 @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("方法三");
}
}
到了这里,关于[Java学习日记]日志、类加载器、XML、DTD与schema、XML解析、XPath、单元测试、Assert、BeforeAfter、注解、自定义注解、注解案例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!