一.配置文件
1.定义:
在企业,我们常把一些需要灵活配置的数据放在一些文本中,而不是在代码中写死,把这些存储配置信息的文件叫做配置文件.
2.Properties
它是一个map集合,核心作用:Properties是用来代表属性文件的,通过Properties可以读写属性文件里的内容.
(1).常用方法和构造器
import java.io.*;
import java.util.Properties;
/*
properties配置文件
特点:
1、都只能是键值对
2、键不能重复
3、文件后缀一般是.properties结尾的
Properties
这是一个Map集合(键值对集合),但是我们一般不会当集合使用
主要用来代表属性文件,通过Properties可以读写属性文件里的内容
读取
public Properties() 创建Properties集合对象
public void load(InputStream is/Reader reader) 通过输入流读取文件中的键值对数据
public String getProperty(String key) 根据键获取值(其实就是get方法的效果)
public Set<String> stringPropertyNames() 获取全部键的集合(其实就是ketSet方法的效果)
写出
public Properties() 创建Properties集合对象
public Object setProperty(String key, String value) 保存键值对数据到Properties对象中去。
public void store(OutputStream os/Writer writer, String comments) 把键值对数据,通过输出流写出到属性文件里去
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
//1. 创建一个配置文件对象
Properties properties = new Properties();
//2. 读取
properties.load(new FileReader("F:\\study\\code\\day-10\\user.porperties"));
String pwd = properties.getProperty("admin");
//3. 写出
System.out.println("admin");
System.out.println(pwd);
Properties properties1 = new Properties();
properties1.setProperty("阿吉 ", "123456");
properties1.store(new FileWriter("F:\\study\\code\\day-10\\user.porperties"),"张家齐二货");
}
}
2.XML
本质是一种数据的格式,可以用来存储复杂的数据结构,和数据关系,可扩展
<?xml version="1.0" encoding="UTF-8" ?>
<!--这是注释,以下是XML文件的内容,都是开始标签,结尾标签的形式-->
<!--这是注释XML文件的后缀一般是.xml-->
<!-- /*
XML
全称 Extensible Markup Language, 可扩展标记语言
本质是一种数据的格式,可以用来存储复杂的数据结构,和数据关系。
特点
XML中的“<标签名>” 称为一个标签或一个元素,一般是成对出现的。
XML中的标签名可以自己定义(可扩展),但必须要正确的嵌套。
XML中只能有一个根标签。
XML中的标签可以有属性。
如果一个文件中放置的是XML格式的数据,这个文件就是XML文件,后缀一般要写成.xml。
语法
XML文件的后缀名为:xml,文档声明必须是第一行
XML中可以定义注释信息:<!–- 注释内容 –>,快捷键是Ctrl+shift+/
XML中书写”<”、“&”等,可能会出现冲突,导致报错,此时可以用如下特殊字符替代。
XML中可以写一个叫CDATA的数据区: <![CDATA[ …内容… ]]>,里面的内容可以随便写。
XML的作用和应用场景
经常用来做为系统的配置文件
或者作为一种特殊的数据结构,在网络中进行传输。
*/-->
<users>
<user id="1">
<name>张无忌</name>
</user>
<user id="2">
<name>赵敏</name>
</user>
</users>
(1)引用场景
经常用来做为系统的配置文件;或者作为一种特殊的数据结构,在网络中进行传输。
(2)解析XML----框架Dom4j
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
/*
需求: 解析b-2.xml,将内容封装到一个List<User对象的集合>
XML解析
DOM解析思想
DOM (document Object Model)文档对象模型
将文档的各个组成部分看做是对应的对象
首先会将xml文件全部加载到内存,在内存中形成一个树状结构,在获取对应的值
DOM解析思想就是一层一层的进入,一层一层的解析
对象分类
Document:整个xml文档对象
Element: 标签对象
Attribute:属性对象
Text标签体:文本对象
DOM4J解析XML准备工作
1、将dom4j的jar包加入到项目中
2、创建DOM4]解析器对象SAXReader,获取Document文档对象,获取根标签对象
3、从根标签对象开始往下层层解析
详细API
SAXReader:Dom4j提供的解析器,可以认为是代表整个Dom4j框架
public SAXReader() 构建Dom4J的解析器对象
public Document read(String path) 把XML文件读成Document对象
Element getRootElement() 获得根元素对象
public String getName() 得到元素名字
public List<Element> elements() 得到当前元素下所有子元素
public List<Element> elements(String name) 得到当前元素下指定名字的子元素返回集合
public Element element(String name) 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个
public String attributeValue(String name) 通过属性名直接得到属性值
public String elementText(子元素名) 得到指定名称的子元素的文本
public String getText() 得到文本
*/
public class Demo2 {
public static void main(String[] args) throws Exception {
ArrayList<User> users = new ArrayList<>();
//构建saxreader解析器对象
SAXReader reader = new SAXReader();
//将文件读成Document对象
Document document = reader.read(new FileReader("F:\\study\\code\\day-10\\b-2.xml"));
//得到根标签元素对象
Element rootElement = document.getRootElement();
//得到根标签的名字
String rootname = rootElement.getName();
System.out.println("rootname="+rootname);
//将根标签下的所有子标签放入集合返回
List<Element> elements = rootElement.elements();
System.out.println(elements.size());//2
//遍历子标签的集合,得到想要的元素
for (Element element : elements) {
System.out.println("=======");
String name = element.getName();
String id = element.attributeValue("id");
System.out.println("子标签名字"+name+"-"+id);
List<Element> elements1 = element.elements();
System.out.println(elements1.size());//elements1子标签下几个子标签 4
String username = element.element("name").getText();//先得到名字整个标签,再只拿文本
System.out.println("name"+username);
String password = element.element("password").getText();//先得到名字整个标签,再只拿文本
System.out.println("password"+password);
String address = element.element("address").getText();//先得到名字整个标签,再只拿文本
System.out.println("address"+address);
String gender = element.element("gender").getText();//先得到名字整个标签,再只拿文本
System.out.println("gender"+gender);
System.out.println("=======");
User user = new User(username,password,address,gender);
users.add(user);
for (User u : users) {
System.out.println(u);
}
}
}
}
class User{
private String name;
private String password;
private String adress;
private String gender;
public User() {
}
public User(String name, String password, String adress, String gender) {
this.name = name;
this.password = password;
this.adress = adress;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAdress() {
return adress;
}
public void setAdress(String adress) {
this.adress = adress;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
", adress='" + adress + '\'' +
", gender='" + gender + '\'' +
'}';
}
}
(3)方法
3.日志
记录程序运行的点点滴滴
(1)日志技术
可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)。
可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改。
(2)体系结构
(3)Logback日志框架
(4)Logbacku快速入门
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
需求
使用Logback日志框架,纪录系统的运行信息。
实现步骤
1. 导入Logback框架到项目中去。
2. 将Logback框架的核心配置文件logback.xml直接拷贝到src目录下(必须是src下)。
4. 创建Logback框架提供的Logger对象,然后用Logger对象调用其提供的方法就可以记录系统的日志信息。
public static final Logger LOGGER = LoggerFactory.getLogger("当前类类名");
5. 打印日志
LOGGER.info("日志信息")
LOGGER.debug("日志信息")
LOGGER.error("日志信息")
*/
public class Demo1 {
public static final Logger LOGGER = LoggerFactory.getLogger("Demo1");
public static void main(String[] args) {
/* LOGGER.info();//输出重要东西
LOGGER.debug();//测试
LOGGER.warn();//
LOGGER.error();//输出错误*/
LOGGER.info("开始执行div方法");
LOGGER.warn("b不能是0");
div(2,1);
div(2,0);
}
public static int div(int a,int b){
LOGGER.debug("方法执行了,a={},b={}",a,b);
try {
int c =a/b;
return c;
} catch (Exception e) {
LOGGER.error("{}/{}出错了",a,b);
throw new RuntimeException(e);
}
}
}
(5)日志级别
(6)为什么要学习日志级别
只有日志的级别是大于或等于核心配置文件配置的日志级别,才会被记录,否则不记录。
二.多线程
1.定义
简单来说就是电脑在做一件事,单线程,在做一件事;多线程,在做多件事
2.多线程的创建方式
(1)继承Thread类
定义一个子类继承线程类java.lang.Thread,重写run()方法
创建子类的对象
调用子类对象的start()方法启动线程(底层会自动去执行run方法)
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
多线程
让程序同时做多件事
多线程的创建方式一:继承Thread类
1. 定义一个子类继承线程类java.lang.Thread,重写run()方法
2. 创建子类的对象
3. 调用子类对象的start()方法启动线程(底层会自动去执行run方法)
优缺点
优点:编码简单
缺点:线程类已经继承Thread,无法继承其他类,不利于功能的扩展。
注意事项
1、启动线程必须是调用start方法,不是调用run方法。
2、直接调用run方法会当成普通方法执行,只有调用start方法才是启动一个新的线程执行。
3、不要将主线任务放在start方法之前,这样主线程一直是先跑完的,相当于是一个单线程的效果了。
扩展
对于单核cpu来讲, 多线程是一种假象
*/
public class Demo1 {
public static final Logger LOGGER=LoggerFactory.getLogger("Demo1");
public static void main(String[] args) {
//需求:创建两个线程,分别用于打印10个A和10个B,最后观察下输出顺序
LOGGER.debug("开始");
Athraed athraed = new Athraed();
Bthread bthread = new Bthread();
athraed.start();
bthread.start();
}
}
class Athraed extends Thread{
public static final Logger LOGGER=LoggerFactory.getLogger("Athraed");
@Override
public void run() {
for(int i=0;i<10;i++){
LOGGER.debug("A-"+i);
}
}
}
class Bthread extends Thread{
public static final Logger LOGGER=LoggerFactory.getLogger("Bthread");
@Override
public void run() {
for(int i=0;i<10;i++){
LOGGER.debug("B-"+i);
}
}
}
1.优缺点
优点:编码简单
缺点:线程类已经继承Thread,无法继承其他类,不利于功能的扩展。
(3)实现Runnable接口
定义一个线程任务类实现Runnable接口,重写run()方法
创建任务类对象
把任务类对象交给Thread处理
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
多线程的创建方式二:实现Runnable接口
1. 定义一个线程任务类实现Runnable接口,重写run()方法
2. 创建任务类对象
3. 把任务类对象交给Thread处理
public Thread(Runnable target)
4. 调用线程对象的start()方法启动线程
优缺点
优点:任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强。
缺点:需要多一个Runnable对象。
*/
public class Demo1 {
public static final Logger LOGGER= LoggerFactory.getLogger("Demo1");
public static void main(String[] args) {
LOGGER.info("奥利给,干了兄弟们");
//需求:创建两个线程,分别用于打印10个A和10个B,最后观察下输出顺序
Arunable arunable = new Arunable();
Brunable brunable = new Brunable();
//把任务类对象交给Thread处理
Thread thread1 = new Thread(arunable);
//设置thread的名字
thread1.setName("t1-a");
Thread thread2 = new Thread(brunable);
thread1.start();
thread2.start();
}
}
//任务类
class Arunable implements Runnable{
public static final Logger LOGGER= LoggerFactory.getLogger("Arunable");
@Override
public void run() {
//获取当前线程
System.out.println("执行run当前线程的名字"+Thread.currentThread());
for (int i=0;i<10;i++){
LOGGER.debug("A-"+i);
}
}
}
class Brunable implements Runnable{
public static final Logger LOGGER= LoggerFactory.getLogger("Brunable");
@Override
public void run() {
System.out.println("执行run当前线程的名字"+Thread.currentThread());
for (int i=0;i<10;i++){
LOGGER.debug("B-"+i);
}
}
}
1.优缺点
优点:任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强。
缺点:需要多一个Runnable对象。
(3)实现Callable接口
创建任务对象 定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据。 把Callable类型的对象封装成FutureTask(线程任务对象)。
把线程任务对象交给Thread对象。 调用Thread对象的start方法启动线程。
线程执行完毕后、通过FutureTask对象的的get方法去获取线程任务执行的结果。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/*
多线程的创建方式三:实现Callable接口
1. 创建任务对象
定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据
把Callable类型的对象封装成FutureTask(线程任务对象)
public FutureTask<>(Callable call) 把Callable对象封装成FutureTask对象
public V get() throws Exception 获取线程执行call方法返回的结果
2. 把线程任务对象交给Thread对象。
3. 调用Thread对象的start方法启动线程。
4. 线程执行完毕后、通过FutureTask对象的的get方法去获取线程任务执行的结果
优缺点
优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;可以在线程执行完毕后去获取线程执行的结果
缺点:编码复杂一点。
*/
public class Demo1 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//需求:启动两个子线程,分别计算100之内的奇数的和和偶数的和,然后在主线程中再做个汇总,得到总和
Athead athead = new Athead();
Bthead bthead = new Bthead();
FutureTask<Integer> aFuturetask = new FutureTask<Integer>(athead);
FutureTask<Integer> bFuturetask = new FutureTask<Integer>(bthead);
Thread t1= new Thread(aFuturetask);
Thread t2= new Thread(bFuturetask);
t1.start();
t2.start();
Integer asum = aFuturetask.get();
Integer bsum = bFuturetask.get();
int sum=asum+bsum;
System.out.println(sum);
}
}
class Athead implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum=0;
for(int i=1;i<=100;i+=2){
sum+=i;
}
return sum;
}
}
class Bthead implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int sum=0;
for(int i=0;i<=100;i+=1){
sum+=i;
}
return sum;
}
}
1.优缺点
优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;可以在线程执行完毕后去获取线程执行的结果。
缺点:编码复杂一点。