十一,IO流
1.File类
java.io.File
1)File类的使用
1.file类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)
2.File类声明在java.io包下
*相对路径:hello.txt 相较于某个路径下,指明的路径。
绝对路径:D://temp.txt 包含盘符在内的文件或文件目录的路径。
*路径分隔符:window用\,url用/。
2)如何创建File类的实例:
public static void main(String
[] args
) {
File file
=new File("D:\\input\\input.txt.txt");
System
.out
.println(file
);
File file1
= new File("jdbc.properties");
System
.out
.println(file1
);jdbc
.properties
}
3)常用方法:
public static void main(String
[] args
) {
File file
=new File("D:\\input\\input.txt.txt");
File file1
= new File("jdbc.properties");
String path
= file
.getAbsolutePath();
System
.out
.println(path
);
System
.out
.println(file1
.getAbsolutePath());
String filePath
= file
.getPath();
System
.out
.println(filePath
);
System
.out
.println(file1
.getPath());
String name
= file
.getName();
System
.out
.println(name
);
String parent
= file
.getParent();
System
.out
.println(parent
);
long length
= file
.length();
System
.out
.println(length
);
long modified
= file
.lastModified();
System
.out
.println(modified
);
File file2
= new File("D:\\wokespace");
String
[] list
= file2
.list();
for (String s
:list
){
System
.out
.println(s
);
}
System
.out
.println("***********************************************");
File
[] files
= file2
.listFiles();
for (File f
: files
){
System
.out
.println(f
);
}
System
.out
.println("**************************");
boolean b
= file1
.renameTo(file
);
System
.out
.println(b
);
}
public static void main(String
[] args
) {
File file
= new File("jdbc.properties");
System
.out
.println(file
.isDirectory());
System
.out
.println(file
.isFile());
System
.out
.println(file
.exists());
System
.out
.println(file
.canRead());
System
.out
.println(file
.canWrite());
System
.out
.println(file
.isHidden());
}
public static void main(String
[] args
) {
File file
= new File("jdbc1.properties");
if (!file
.exists()){
try {
file
.createNewFile();
System
.out
.println("文件创建成功!");
} catch (IOException e
) {
e
.printStackTrace();
}
}else{
file
.delete();
System
.out
.println("文件删除成功!");
}
file
.mkdir();
file
.mkdirs();
}
file.delete()删除目录时,要想删除成功,该目录下不能有文件或目录。
4)面试题:
public static void main(String
[] args
) {
File file
= new File("D:\\temp\\temp1.txt");
File file1
= new File(file
.getParent() , "haha.txt");
System
.out
.println(file
.getParent());
try {
boolean newFile
= file1
.createNewFile();
if (newFile
){
System
.out
.println("创建成功!");
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
public static void main(String
[] args
) {
File file
= new File("D:\\temp");
int sum
=print(file
);
System
.out
.println(sum
);
}
public static int print(File file
){
File
[]files
=file
.listFiles();
int sum
=0;
for (File f
:files
){
if (f
.isDirectory()){
print(f
);
f
.delete();
}else{
System
.out
.println(f
.getAbsolutePath());
sum
+=f
.length();
f
.delete();
}
}
return sum
;
}
public static void main(String
[] args
) {
File file
= new File("D:\\QQ");
Find(file
);
}
public static void Find(File file
){
File
[]files
=file
.listFiles();
for (File f
: files
){
if (f
.isDirectory()){
Find(f
);
}else{
if (f
.getName().endsWith(".jpg")){
System
.out
.println(f
.getAbsolutePath());
}
}
}
2.IO流
1)概述
IO流原理及流的分类
input
/output的缩写,处理设备之间的数据传输。
input:读取外部数据
output:将程序中的数据输出
按照操作数据单位的不同,分为字节流(
8bit)和字符流(
6bit)适合于文本。
输入流:inputStream,reader
输出流:outputStream,Writer
按照流的角色不同:作用在文件上的:节点流,作用在已经有的流上的:处理流。
按照数据流向:输入流,输出流。
IO流的体系结构
抽象基类 节点流 缓冲流
InputStream FileInputStream BufferedInputStream
OutputStream FileOutputStream BufferedOutputStream
Reader FileReader BufferedReader
Writer FileWriter BufferedWriter
2)节点流-FileReader和FileWriter
FileReader读入数据的基本操作
说明点: ①read()地理解:返回读入的一个字符,如果达到文件末尾,返回-1 ②异常的处理:为了保证流资源一定可以执行关闭操作,需要使用try-catch-finally处理。 ③读入的文件一定要存在,否则就会报FileNotFoundException
public static void main(String
[] args
){
FileReader reader
=null
;
BufferedReader reader1
=null
;
try {
reader
= new FileReader(new File("jdbc.properties"));
reader1
= new BufferedReader(reader
);
int data
;
while ((data
=reader1
.read())!=-1){
System
.out
.print((char)data
);
}
} catch (FileNotFoundException e
) {
e
.printStackTrace();
} catch (IOException e
) {
e
.printStackTrace();
} finally {
if (reader
!=null
){
try {
reader
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
if(reader1
!=null
){
try {
reader1
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
}
public static void main(String
[] args
) {
FileReader reader
=null
;
BufferedReader br
=null
;
try {
reader
= new FileReader(new File("jdbc.properties"));
br
=new BufferedReader(reader
);
char []buf
=new char[1024];
int len
=0;
while ((len
=br
.read(buf
))!=-1){
String str
=new String(buf
,0,len
);
System
.out
.print(str
);
}
} catch (FileNotFoundException e
) {
e
.printStackTrace();
} catch (IOException e
) {
e
.printStackTrace();
} finally{
if (reader
!=null
){
try {
reader
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
if (br
!=null
){
try {
br
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
}
FileWriter写出数据的操作
说明: ①输出操作:对应的File可以不存在,如果不存在,在输出过程中,会自动创建此文件。 ②如果存在:如果流使用的构造器是FileWriter(file,false)/FileWriter(file):对原有文件覆盖。 如果流使用FileWriter(file,true):不会对原有文件覆盖。
public static void main(String
[] args
) {
FileWriter writer
= null
;
try {
writer
= new FileWriter(new File("hello.txt"),true);
writer
.write("I have a dream !");
} catch (IOException e
) {
e
.printStackTrace();
}finally{
if (writer
!=null
){
try {
writer
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
}
使用FileReader和FileWriter实现文本文件的复制
字符流不能处理图片文件
public static void main(String
[] args
) {
FileReader fr
=null
;
FileWriter fw
=null
;
try {
fr
=new FileReader(new File("E:\\IEDADEMO\\day07\\src\\com\\atguigu\\IO\\IO.txt"));
fw
=new FileWriter(new File("hello.txt"));
char []buf
=new char[1024];
int len
=0;
while ((len
=fr
.read(buf
))!=-1){
fw
.write(buf
,0,len
);
}
} catch (FileNotFoundException e
) {
e
.printStackTrace();
} catch (IOException e
) {
e
.printStackTrace();
}finally{
if (fw
!=null
){
try {
fw
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
if (fr
!=null
){
try {
fr
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
}
3)节点流-FileInputStream和FileOutputStream
使用FileInputStream不能读取文本文件的测试: 结论:对于文本文件,使用字符流处理 对于非文本文件,使用字节流处理
public static void main(String
[] args
) {
FileInputStream fis
=null
;
FileOutputStream fos
=null
;
try {
fis
=new FileInputStream(new File("E:\\IEDADEMO\\day07\\src\\com\\atguigu\\IO\\IO.txt"));
fos
=new FileOutputStream(new File("hello.txt"));
byte [] bytes
=new byte[1024];
int len
=0;
while ((len
=fis
.read(bytes
))!=-1){
fos
.write(bytes
,0,len
);
}
} catch (FileNotFoundException e
) {
e
.printStackTrace();
} catch (IOException e
) {
e
.printStackTrace();
}finally{
try {
if (fos
!=null
){
fos
.close();
}
if (fis
!=null
){
fis
.close();
}
}catch (IOException e
) {
e
.printStackTrace();
}
}
}
FileInputStream和FileOutputStream读写非文本文件
public static void main(String
[] args
) {
FileInputStream fis
=null
;
FileOutputStream fos
=null
;
try {
fis
=new FileInputStream(new File("E:\\IEDADEMO\\day07\\src\\下载.png"));
fos
=new FileOutputStream(new File("D:\\test.png"));
byte[] bytes
=new byte[1024*1024];
int len
=0;
while ((len
=fis
.read(bytes
))!=-1) {
fos
.write(bytes
,0,len
);
}
} catch (IOException e
) {
e
.printStackTrace();
} finally {
try {
if (fos
!=null
){
fos
.close();
}
if (fis
!=null
){
fis
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
写一个复制文件的方法,可以用来直接调用,
public static void main(String
[] args
) {
File file
= new File("hello.txt");
File file1
= new File("D://hello.txt");
Copy(file
,file1
);
}
public static void Copy(File file
,File file1
){
FileInputStream fis
=null
;
FileOutputStream fos
=null
;
try {
fis
=new FileInputStream(file
);
fos
=new FileOutputStream(file1
);
byte [] bytes
=new byte [1024];
int len
;
while((len
=fis
.read(bytes
))!=-1){
fos
.write(bytes
,0,len
);
}
System
.out
.println("复制完成!");
} catch (IOException e
) {
e
.printStackTrace();
} finally {
try {
if (fos
!=null
){
fos
.close();
}
if (fis
!=null
){
fis
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
4)处理流之一:缓冲流
缓冲流作用:提高流的读取写入速度 提高读写速度的原因:内部提供了一个缓冲区:1024*8=8192 缓冲流(字节型)实现非文本文件的复制
public static void main(String
[] args
) {
FileInputStream fis
=null
;
FileOutputStream fos
=null
;
BufferedInputStream bis
=null
;
BufferedOutputStream bos
=null
;
try {
fis
=new FileInputStream(new File("hello.txt"));
fos
=new FileOutputStream(new File("D://hello.txt"));
bis
=new BufferedInputStream(fis
);
bos
=new BufferedOutputStream(fos
);
byte [] bytes
=new byte[1024];
int len
;
while ((len
=bis
.read(bytes
))!=-1){
bos
.write(bytes
,0,len
);
}
System
.out
.println("复制完成!");
} catch (IOException e
) {
e
.printStackTrace();
} finally {
try {
if (bos
!=null
){
bos
.close();
}
if (bis
!=null
){
bis
.close();
}
if (fos
!=null
){
fos
.close();
}
if (fis
!=null
){
fis
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
缓冲流(字符型)实现文本文件的复制 处理流:就是套接在已有流的基础上
public static void main(String
[] args
) {
FileReader fr
=null
;
FileWriter fw
=null
;
BufferedReader br
=null
;
BufferedWriter bw
=null
;
try {
fr
=new FileReader(new File("hello.txt"));
fw
=new FileWriter(new File("D://hello.txt"));
br
=new BufferedReader(fr
);
bw
=new BufferedWriter(fw
);
String data
;
while ((data
=br
.readLine())!=null
){
bw
.write(data
);
bw
.newLine();
}
System
.out
.println("文本复制完成!");
} catch (IOException e
) {
e
.printStackTrace();
} finally {
try {
if (bw
!=null
){
bw
.close();
}
if (br
!=null
){
br
.close();
}
if (fw
!=null
){
fw
.close();
}
if (fr
!=null
){
fr
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
5)面试题
1.图片加密和图片解密
public static void main(String
[] args
) {
BufferedInputStream bis
=null
;
BufferedOutputStream bos
=null
;
try {
bis
=new BufferedInputStream(new FileInputStream(new File("D:\\尹会东.jpg")));
bos
=new BufferedOutputStream(new FileOutputStream(new File("D:\\copy.jpg")));
int len
=0;
byte [] bytes
=new byte[1024];
while ((len
=bis
.read(bytes
))!=-1){
for (int i
= 0; i
<len
; i
++) {
bytes
[i
]= (byte) (bytes
[i
]^5);
}
bos
.write(bytes
,0,len
);
}
System
.out
.println("加密完成!");
} catch (IOException e
) {
e
.printStackTrace();
} finally {
try {
if (bis
!=null
){
bis
.close();
}
if (bos
!=null
){
bos
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
public static void main(String
[] args
) {
BufferedInputStream bis
=null
;
BufferedOutputStream bos
=null
;
try {
bis
=new BufferedInputStream(new FileInputStream(new File("D:\\copy.jpg")));
bos
=new BufferedOutputStream(new FileOutputStream(new File("D:\\copy1.jpg")));
int len
=0;
byte [] bytes
=new byte[1024];
while ((len
=bis
.read(bytes
))!=-1){
for (int i
= 0; i
<len
; i
++) {
bytes
[i
]= (byte) (bytes
[i
]^5);
}
bos
.write(bytes
,0,len
);
}
System
.out
.println("解密完成!");
} catch (IOException e
) {
e
.printStackTrace();
} finally {
try {
if (bis
!=null
){
bis
.close();
}
if (bos
!=null
){
bos
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
2.获取文本上每个字符出现的次数
public static void main(String
[] args
) {
HashMap
<Character, Integer> map
= new HashMap<>();
BufferedReader br
=null
;
BufferedWriter bw
=null
;
try {
br
=new BufferedReader(new FileReader(new File("hello.txt")));
bw
=new BufferedWriter(new FileWriter(new File("D:\\WorldCount.txt")));
int c
=0;
while ((c
=br
.read())!=-1){
char ch
= (char) c
;
if (map
.get(ch
)==null
){
map
.put(ch
,1);
}else{
map
.put(ch
,map
.get(ch
)+1);
}
}
Set
<Map
.Entry
<Character, Integer>> set
= map
.entrySet();
Iterator
<Map
.Entry
<Character, Integer>> iterator
= set
.iterator();
while (iterator
.hasNext()){
bw
.write(iterator
.next().getKey()+"--------------"+iterator
.next().getValue());
bw
.newLine();
}
} catch (IOException e
) {
e
.printStackTrace();
} finally {
try {
if (bw
!=null
){
bw
.close();
}
if (br
!=null
){
br
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
3.将一个文件写入另一个文件
public static void main(String
[] args
) {
FileReader fr
=null
;
FileWriter fw
=null
;
try {
fr
=new FileReader(new File("E:\\IEDADEMO\\day07\\src\\com\\atguigu\\IO\\IO.txt"));
fw
=new FileWriter(new File("hello.txt"));
char []buf
=new char[1024];
int len
=0;
while ((len
=fr
.read(buf
))!=-1){
fw
.write(buf
,0,len
);
}
} catch (FileNotFoundException e
) {
e
.printStackTrace();
} catch (IOException e
) {
e
.printStackTrace();
}finally{
if (fw
!=null
){
try {
fw
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
if (fr
!=null
){
try {
fr
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
}
6)处理流之二:转换流
1.作用:提供了字节流和字符流的转换 2.转换流属于字符流 InputStreamReader:将一个字节的输入流转换为字符的输入流 OutputStreamWriter:将一个字符的输出流转换为字节的输出流 3.解码:字节,字节数组----->字符数组,字符串 编码:字符数组,字符串----->字节,字节数组 4.字符集
public static void main(String
[] args
) {
FileInputStream fis
=null
;
InputStreamReader isr
=null
;
FileOutputStream fos
=null
;
OutputStreamWriter osw
=null
;
try {
fis
= new FileInputStream(new File("hello.txt"));
isr
= new InputStreamReader(fis
, StandardCharsets
.UTF_8
);
fos
=new FileOutputStream(new File("D:\\Temps.txt"));
osw
=new OutputStreamWriter(fos
,"utf-8");
char [] chars
=new char[1024];
int len
;
while ((len
=isr
.read(chars
))!=-1){
osw
.write(chars
,0,len
);
}
} catch (FileNotFoundException e
) {
e
.printStackTrace();
} catch (IOException e
) {
e
.printStackTrace();
} finally {
try {
if (isr
!=null
){
isr
.close();
}
if (fis
!=null
){
fis
.close();
}
if (osw
!=null
){
osw
.close();
}
if (fos
!=null
){
fos
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
7)其他流(了解)
其他流(了解) 1.标准的输入输出流 1.1 System.in标准的输入流 System.out标准的输出流 1.2我们可以通过System类的setIn(InputStream)/setOut(OutputStream)方式重新指定输入和输出的流。 1.3练习:IO5
public static void main(String
[] args
) {
InputStreamReader isr
=new InputStreamReader(System
.in
);
BufferedReader br
=new BufferedReader(isr
);
while (true){
String data
= null
;
try {
data
= br
.readLine();
if (data
.equalsIgnoreCase("e")||data
.equalsIgnoreCase("exit")){
System
.out
.println("程序结束!");
break;
}else{
System
.out
.println(data
.toUpperCase());
}
} catch (IOException e
) {
e
.printStackTrace();
}finally {
try {
if (isr
!=null
){
isr
.close();
}
if (br
!=null
){
br
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
}
2.打印流 PrintStream PrintWriter 3.数据流 DataInputStream DataOutputStream 4.随机存取文件流 RandomAccessFile 既可以读,也可以写。 实现了DataInput和DataOutput接口 java.io下,但是直接继承Object类 如果RandomAccessFile作为输出流时,写出到的文件不存在,会自动创建, 如果写出到的文件存在,会对原有文件进行覆盖,(默认情况下,从头覆盖)
public static void main(String
[] args
) {
RandomAccessFile file
= null
;
RandomAccessFile file1
= null
;
try {
file
=new RandomAccessFile(new File("hello.txt"),"r");
file1
=new RandomAccessFile(new File("D:\\object.txt"),"rw");
byte []bytes
=new byte[1024];
int len
=0;
while ((len
=file
.read(bytes
))!=-1){
file1
.write(bytes
,0,len
);
}
} catch (IOException e
) {
e
.printStackTrace();
} finally {
try {
if (file
!=null
){
file
.close();
}
if (file1
!=null
){
file1
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
RandomAccessFile类实现数据插入
public static void main(String
[] args
) {
RandomAccessFile raf
=null
;
try {
raf
=new RandomAccessFile("hello.txt","rw");
raf
.seek(new File("hello.txt").length());
raf
.write("xyz".getBytes());
} catch (IOException e
) {
e
.printStackTrace();
} finally {
try {
if (raf
!=null
){
raf
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
8)对象流
ObjectInputStream用于存储和读取基本数据类型或对象的流处理。
序列化:用ObjectOutputStream将数据从内存写入硬盘
反序列化:ObjectInputStream将数据从硬盘读入内存。
要求对象所属的类是可序列化的—>实现了Seralizable接口
面试题:如何理解对象序列化机制?
把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久的保存在硬盘上,或者通过网络,
将这种二进制流传输到另一个网络节点,当其他程序获取了这种二进制流,就可以恢复成原来的Java对象。
序列化的好处在于将任何实现了Seralizable接口的对象转化为字节数据,使其在保存和传输中可被还原。
序列化
public static void main(String
[] args
) {
ObjectOutputStream oos
=null
;
try {
oos
=new ObjectOutputStream(new FileOutputStream(new File("D:\\object.txt")));
oos
.writeObject(new String("我爱北京天安门"));
oos
.flush();
} catch (IOException e
) {
e
.printStackTrace();
} finally {
if(oos
!=null
){
try {
oos
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
}
反序列化
public static void main(String
[] args
) {
ObjectInputStream ois
=null
;
try {
ois
=new ObjectInputStream(new FileInputStream(new File("D://object.txt")));
Object object
= ois
.readObject();
String str
= (String
) object
;
System
.out
.println(str
);
} catch (IOException e
) {
e
.printStackTrace();
} catch (ClassNotFoundException e
) {
e
.printStackTrace();
} finally {
if (ois
!=null
){
try {
ois
.close();
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
}
自定义类实现序列化与反序列化操作
1.需要实现java.io.Serializable接口
2. public static final long serialVersionUID= 6080347956336285349L;
3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性也必须是可序列化的。
(默认情况下基本数据类型是可序列化的)
4.不能序列化static和transient的
public class Person implements java.io.Serializable{
public static final long serialVersionUID
= 6080347956336285349L
;
private String name
;
private int age
;
public Person() {
}
public Person(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
;
}
@Override
public String
toString() {
return "Person{" +
"name='" + name
+ '\'' +
", age=" + age
+
'}';
}
}
public static void main(String
[] args
) {
ObjectOutputStream oos
=null
;
ObjectInputStream ois
=null
;
try {
oos
=new ObjectOutputStream(new FileOutputStream(new File("D://object.txt")));
Person person
= new Person("张贝贝", 25);
oos
.writeObject(person
);
ois
=new ObjectInputStream(new FileInputStream(new File("D:\\object.txt")));
Object obj
=ois
.readObject();
Person p1
= (Person
) obj
;
System
.out
.println(p1
.toString());
} catch (IOException e
) {
e
.printStackTrace();
} catch (ClassNotFoundException e
) {
e
.printStackTrace();
} finally {
try {
if (ois
!=null
){
ois
.close();
}
if (oos
!=null
){
oos
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
serialVersionUID的理解
如果不手动写,Java会自动生成一个。 如果序列化以后修改了类,serialVersionUID也会被Java修改, 反序列化会失败!
十二,网络编程
网络编程中有两个主要的问题:
1.如何准确的定位到网络上一台或者多台主机:定位主机上的特定应用
2.找到主机后如何可靠高效的进行数据传输
网络编程中的两个要素
1.对应的问题:IP和端口号
2.对应问题二:提供网络通信协议:TCP/IP参考模型
通信要素一:IP和端口号
1.IP:唯一标识Internet上的计算机(通信实体)
2.在Java中使用InetAddress类代表IP
3.IP分类:IPV4和IPV6;万维网和局域网的区别
4.域名:www.baidu.com
5.域名--》NDS--》网络服务器
6.本地回路地址:127.0.0.1 对应着localhost
7.如何实例化InetAddress:两个方法;getByName(String host),getLocalHost();
端口号:表示计算机上运行的程序
不同进程有不同的端口号
Tomcat:8080,mysql:3306,oracle:1521
端口号与IP地址组合得出一个网络套接字,Socket
范围:0-65535
public static void main(String
[] args
) {
try {
InetAddress name
= InetAddress
.getByName("127.0.0.1");
System
.out
.println(name
);
InetAddress name1
= InetAddress
.getByName("www.baidu.com");
System
.out
.println(name1
);
System
.out
.println(name
.getHostName());
} catch (UnknownHostException e
) {
e
.printStackTrace();
}
}
TCP:3次握手,UDP:封装数据包
Tcp网络编程
public class Test1 {
@Test
public void client()throws Exception
{
InetAddress address
= InetAddress
.getByName("127.0.0.1");
Socket socket
= new Socket(address
, 3307);
OutputStream os
= socket
.getOutputStream();
os
.write("你好,我是客户端".getBytes());
os
.close();
socket
.close();
}
@Test
public void server()throws Exception
{
ServerSocket serverSocket
= new ServerSocket(3307);
Socket socket
= serverSocket
.accept();
InputStream is
= socket
.getInputStream();
ByteArrayOutputStream baos
= new ByteArrayOutputStream();
int len
;
byte[] buffer
= new byte[10];
while ((len
=is
.read(buffer
))!=-1){
baos
.write(buffer
,0,len
);
}
System
.out
.println(baos
.toString());
baos
.close();
is
.close();
socket
.close();
serverSocket
.close();
}
}
public class Test2 {
@Test
public void test1() throws Exception
{
InetAddress address
= InetAddress
.getByName("127.0.0.1");
Socket socket
= new Socket(address
, 3308);
FileInputStream is
= new FileInputStream(new File("E:\\9.jpg"));
byte[] buffer
= new byte[1024 * 8];
int len
;
OutputStream os
= socket
.getOutputStream();
while ((len
= is
.read(buffer
)) != -1) {
os
.write(buffer
, 0, len
);
}
socket
.shutdownOutput();
InputStream stream
= socket
.getInputStream();
byte[] buffer2
= new byte[10];
int len2
;
ByteArrayOutputStream baos
= new ByteArrayOutputStream();
while ((len2
= stream
.read(buffer2
)) != -1) {
baos
.write(buffer2
, 0, len2
);
}
System
.out
.println(baos
.toString());
baos
.close();
stream
.close();
os
.close();
is
.close();
socket
.close();
}
@Test
public void test2() throws Exception
{
ServerSocket serverSocket
= new ServerSocket(3308);
Socket socket
= serverSocket
.accept();
InputStream is
= socket
.getInputStream();
FileOutputStream fos
= new FileOutputStream(new File("E:\\10.jpg"));
int len
;
byte[] buffer
= new byte[1024 * 8];
while ((len
= is
.read(buffer
)) != -1) {
fos
.write(buffer
, 0, len
);
}
OutputStream stream
= socket
.getOutputStream();
stream
.write("接收文件成功".getBytes());
stream
.close();
fos
.close();
is
.close();
socket
.close();
serverSocket
.close();
}
}
UDP网络编程
/**
* @author yinhuidong
* @createTime 2020-04-10-23:03
* UDP网络编程
*/
public class Test4 {
//发送端
@Test
public void send()throws Exception{
DatagramSocket socket = new DatagramSocket();
byte []data="我是UDP方式的发送端".getBytes();
InetAddress inet = InetAddress.getLocalHost();
DatagramPacket packet = new DatagramPacket(data, 0, data.length,inet, 8081);
socket.send(packet);
}
//接收端
@Test
public void receiver()throws Exception{
DatagramSocket socket = new DatagramSocket(8081);
byte[] buffer = new byte[100];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet);
System.out.println(new String(packet.getData(), 0, buffer.length));
}
}
URL类的理解与实例化
URL:统一资源定位符,他表示internet上某一资源的地址。 格式:协议,主机名,端口号,片段名,参数列表
public static void main(String
[] args
) throws IOException
{
URL url
= new URL("www.baidu.com");
HttpURLConnection connection
= (HttpURLConnection
) url
.openConnection();
connection
.connect();
connection
.getInputStream();
}
十三,反射
1.概述
反射
反射机制允许程序在执行时借助于反射API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
反射相关的主要API
java.lang.Class
java.lang.reflect.
关于java.lang.Class类的理解:*
1.类的加载过程:程序在经过javac.exe命令后,会生成一个或多个字节码文件(.class结尾),接着我们
使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程称为类的加载。
加载到内存中的类,我们就称为运行时类,此运行的类,就作为Class的一个实例。
2.换句话说:Class的实例就对应着一个运行时类。
类的加载过程(了解)
①类的加载:将类的class文件读入内存,并为之创建一个java.lang.Class对象,此过程由类的加载器完成。
②类的链接:将类的二进制数据合并到JRE中,赋默认值。
③类的初始化:JVM负责对类进行初始化。将静态代码块和类中赋值操作的语句读取,给变量/常量赋值。
类的加载器ClassLoader的理解:(了解)
作用:把类加载进内存。
2.获取Class的实例的方式(重点)
加载到内存中的运行时类,会缓存一定的时间,在此时间内,我们可以通过不同的方式来获取此运行时的类。
Class实例对应的结构说明:
①claass,②interface,③数组④枚举类⑤注解⑥基本数据类型⑦void
/**
* @author yinhuidong
* @createTime 2020-04-11-9:57
* 获取Class实例的四种方式
*/
public class Test1 {
//通过对象.getClass()的方式
@Test
public void test1() {
Class<? extends Person> clazz = new Person().getClass();
}
//通过类.class
@Test
public void test2() {
Class<Person> clazz = Person.class;
}
//通过Class的静态方法
@Test
public void test3() throws Exception {
Class<?> clazz = Class.forName("com.atguigui.java1.Person");
}
//通过类加载器
@Test
public void test4() throws Exception{
ClassLoader classLoader = Person.class.getClassLoader();
classLoader.loadClass("com.atguigui.java1.Person");
}
}
class Person {
private String name;
private Integer age;
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
3.使用ClassLoader加载配置文件
@Test
public void test4() throws Exception
{
Properties prop
=new Properties();
ClassLoader classLoader
=Test1
.class.getClassLoader();
InputStream is
= classLoader
.getResourceAsStream("driud.properties");
prop
.load(is
);
String user
=prop
.getProperty("user");
String password
=prop
.getProperty("password");
System
.out
.println(user
+" "+password
);
}
4.创建运行时类对象与反射的动态性
通过反射,创建运行时类对象
newInstance()调用此方法,创建对应的运行时类的对象,内部调用了运行时类的空参构造器。
要想此方法正常运行:
①运行时类必须提供空参的构造器
②空参构造器访问权限得够。
在JavaBean中要求提供一个空参构造器的原因:
①便于通过反射,创建运行时类的对象。
②便于子类继承此运行类时,默认调用super方法时,保证父类有此构造器。
@Test
public void test5() throws IllegalAccessException
, InstantiationException
{
Class
<Person>clazz
=Person
.class;
Person obj
=clazz
.newInstance();
System
.out
.println(obj
);
}
反射的动态性举例
@Test
public void test6() throws Exception
{
Object instance
= getInstance("java.util.Date");
System
.out
.println(instance
);
}
public Object
getInstance(String classPath
)throws Exception
{
Class
clazz=Class
.forName(classPath
);
return clazz
.newInstance();
}
5.调用运行时类的指定结构
属性,
@Test
public void test() throws Exception
{
Class
clazz=Person
.class;
Object o
= clazz
.newInstance();
Field name
= clazz
.getField("name");
name
.set(o
,"yinhuidong");
String o1
= (String
) name
.get(o
);
System
.out
.println(o1
);
}
@Test
public void test2() throws Exception
{
Class
clazz=Person
.class;
Object o
= clazz
.newInstance();
Field age
= clazz
.getDeclaredField("age");
age
.setAccessible(true);
age
.set(o
,20);
Object obj
= age
.get(o
);
System
.out
.println(obj
);
}
方法,
@Test
public void test3()throws Exception
{
Class
<Person> clazz
= Person
.class;
Person person
= clazz
.newInstance();
Method show
= clazz
.getDeclaredMethod("show");
show
.setAccessible(true);
Object obj
= show
.invoke(person
);
Method add
= clazz
.getDeclaredMethod("add", int.class, int.class);
add
.setAccessible(true);
Integer invoke
= (Integer
) add
.invoke(person
, 1, 1);
System
.out
.println(invoke
);
}
@Test
public void test4() throws Exception
{
Class
clazz=Person
.class;
Method eat
= clazz
.getDeclaredMethod("eat");
eat
.setAccessible(true);
eat
.invoke(Person
.class);
}
构造器
@Test
public void test5() throws Exception
{
Class
clazz=Person
.class;
Constructor constructor
= clazz
.getDeclaredConstructor(String
.class, Integer
.class);
constructor
.setAccessible(true);
Object obj
= constructor
.newInstance("Tom",22);
System
.out
.println(obj
);
}
6.代理
代理设计模式的原理:使用一个代理将对象包装起来,然后用该代理对象取代原始对象。 任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
静态代理举例
特点:编译期间,代理类和被代理类就被确定下来了。
interface ClothFactory{
void produceCloth();
}
class ProxyClothFactory implements ClothFactory{
private ClothFactory factory
;
public ProxyClothFactory(ClothFactory factory
) {
this.factory
= factory
;
}
@Override
public void produceCloth() {
System
.out
.println("代理工厂进行准备工作");
factory
.produceCloth();
System
.out
.println("代理工厂做后续工作!");
}
}
class Nike implements ClothFactory{
@Override
public void produceCloth() {
System
.out
.println("耐克工厂生产一批运动服!");
}
}
@Test
public void test(){
Nike nike
=new Nike();
ProxyClothFactory proxyClothFactory
= new ProxyClothFactory(nike
);
proxyClothFactory
.produceCloth();
}
动态代理示例
动态代理:可以通过一个代理类完成全部的代理功能。 要求:理解过程。
public class Test1 {
private PersonDao dao
=new PersonDaoImpl();
@Test
public void test(){
PersonDao personDao
= (PersonDao
) Proxy
.newProxyInstance(
dao
.getClass().getClassLoader(),
dao
.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object
invoke(Object proxy
, Method method
, Object
[] args
) throws Throwable
{
Object o
=null
;
if (!method
.getName().equals("show")){
Integer a
= (Integer
) args
[0];
Integer b
= (Integer
) args
[1];
o
=method
.invoke(dao
,a
*2,b
*2);
return o
;
}
o
=method
.invoke(dao
);
return o
;
}
}
);
System
.out
.println(personDao
.add(1, 1));
personDao
.del(2,1);
personDao
.show();
}
}
interface PersonDao{
int add(int a
,int b
);
void del(int a
,int b
);
void show();
}
class PersonDaoImpl implements PersonDao{
@Override
public int add(int a
, int b
) {
return a
+b
;
}
@Override
public void del(int a
, int b
) {
System
.out
.println(a
-b
);
}
@Override
public void show() {
System
.out
.println("show()....");
}
}
7.总结
import java
.util
.Properties
;
public class Test3 {
@Test
public void test1() throws ClassNotFoundException
{
Class
<Person> clazz
= Person
.class;
System
.out
.println(clazz
);
Person person
= new Person();
Class
<? extends Person> clazz1
= person
.getClass();
System
.out
.println(clazz1
);
Class
<?> clazz2
= Class
.forName("com.atguigu.java3.Person");
System
.out
.println(clazz2
);
ClassLoader loader
= Test3
.class.getClassLoader();
Class
<?> clazz3
= loader
.loadClass("com.atguigu.java3.Person");
System
.out
.println(clazz3
);
}
@Test
public void test2() throws IOException
{
InputStream is
= Test3
.class.getClassLoader().getResourceAsStream("xxx.properties");
Properties prop
= new Properties();
prop
.load(is
);
}
@Test
public void test3() throws IllegalAccessException
, InstantiationException
{
Class
<Person> clazz
= Person
.class;
Person person
= clazz
.newInstance();
System
.out
.println(person
.toString());
}
@Test
public void test4() {
try {
Object p
= GetInstance("com.atguigu.java3.Person");
System
.out
.println(p
.toString());
} catch (ClassNotFoundException e
) {
e
.printStackTrace();
}
}
public Object
GetInstance(String path
) throws ClassNotFoundException
{
Class
<?> clazz
= Class
.forName(path
);
return clazz
;
}
@Test
public void test5() throws IllegalAccessException
, InstantiationException
, NoSuchFieldException
{
Class
<Person> clazz
= Person
.class;
Person p
= clazz
.newInstance();
Field name
= clazz
.getField("name");
name
.set(p
,"张");
System
.out
.println(name
.get(p
));
}
@Test
public void test6() throws IllegalAccessException
, InstantiationException
, NoSuchFieldException
{
Class
<Person> clazz
= Person
.class;
Person p
= clazz
.newInstance();
Field name
= clazz
.getDeclaredField("name");
name
.setAccessible(true);
name
.set(p
,"张");
System
.out
.println(name
.getName());
Field age
= clazz
.getDeclaredField("age");
age
.setAccessible(true);
age
.set(p
,12);
System
.out
.println(age
.get(p
));
System
.out
.println(p
.toString());
}
@Test
public void test7() throws IllegalAccessException
, InstantiationException
, NoSuchMethodException
, InvocationTargetException
{
Class
<Person> clazz
= Person
.class;
Person p
= clazz
.newInstance();
Method show
= clazz
.getDeclaredMethod("show", String
.class);
show
.setAccessible(true);
Object args
= show
.invoke(p
, "args");
System
.out
.println(args
);
}
@Test
public void test8() throws IllegalAccessException
, InstantiationException
, NoSuchMethodException
, InvocationTargetException
{
Class
<Person> clazz
= Person
.class;
Person p
= clazz
.newInstance();
Method eat
= clazz
.getDeclaredMethod("eat", String
.class);
eat
.setAccessible(true);
Object o
= eat
.invoke(Person
.class, "可比克");
System
.out
.println(o
);
}
}
class Person {
private String name
;
private int age
;
public Person() {
}
private int show(String args
){
System
.out
.println(args
);
return 1;
}
private static void eat(String food
){
System
.out
.println("正在吃。。。"+food
);
}
public Person(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
;
}
@Override
public String
toString() {
return "Person{" +
"name='" + name
+ '\'' +
", age=" + age
+
'}';
}
}
十四,jdk8新特性
1.Lambda表达式
Lambda表达式的使用
1.举例:Comparator<Integer> c= Comparator.comparingInt(o -> o);
2.格式:->:Lambda操作符
左边叫做形参列表,其实就是接口中的抽象方法的形参列表
右边叫做Lambda体(重写的抽象方法的方法体)
3.关于Lambda表达式的使用
总结:
-> 左边:lambda形参列表的参数类型可以省略(类型推断),如果形参列表只有一个参数,()可以省略。
-> 右边:Lambda体应该使用一对{}包裹,如果Lambda体只有一条执行语句(可能是return语句),{}和return也可以省略。
要求接口只有一个抽象方法。
4.Lambda表达式的本质:作为函数式接口的实例。
5.如果一个接口中只声明了一个抽象方法,则此接口称为函数式接口。
可以使用注解@FunctionalInterface检查是否是一个函数式接口。
用匿名实现类表示的现在都可以用Lambda表达式表示。
public class LambdaTest1 {
@Test
public void test() {
Runnable r
= () -> System
.out
.println("语法格式一:无参数,无返回值");
r
.run();
}
@Test
public void test2() {
Consumer
<String> c
= (String s
) -> {
System
.out
.println(s
);
};
c
.accept("语法格式二:一个参数,无返回值");
}
@Test
public void test3() {
Consumer
<String> c
= (s
) -> {
System
.out
.println(s
);
};
c
.accept("语法格式:类型推断");
}
@Test
public void test4() {
Consumer
<String> c
= s
-> {
System
.out
.println(s
);
};
c
.accept("语法格式四:只一个参数时,省略小括号");
}
@Test
public void test5() {
Comparator
<Integer> c
= (o1
, o2
) -> {
System
.out
.println("语法格式五:Lambda 需要两个以上参数,多条执行语句,并且有返回值。");
return o1
.compareTo(o2
);
};
int compare
= c
.compare(32, 21);
System
.out
.println(compare
);
}
@Test
public void test6() {
Comparator
<Integer> c
= (o1
, o2
) -> o1
.compareTo(o2
);
int compare
= c
.compare(32, 21);
System
.out
.println(compare
);
}
}
Java内置四大核心函数式接口(要求能看懂)
消费性接口 Consumer<T> void accept(T t)
供给型接口 Supplier<T> T get()
函数型接口 Function<T,R> R apply(T t)
断定型接口 Predicate<T> boolean test(T t)
test()
使用情景:当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用。
方法引用:本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例,
所以方法引用,也是函数式接口的实例。
使用格式: 类(对象)::方法名
具体分为如下三种情况:
对象::非静态方法
类::静态方法
类::非静态方法
方法引用的使用要求,要求接口中的抽象方法的形参列表和返回值类型与方法引用
的方法的形参列表和返回值类型相同!
2.Stream API
1.Stream关注的是数据的运算,与CPU打交道。
集合关注的是是数据的存储,与内存打交道。
2.
①Stream自己不会存储元素。
②Stream不会改变源对象,相反,他们会返回一个持有结果的新Stream。
③Stream操作是延迟执行的,这意味着它们会等到需要结果的时候才执行。
3.Stream的执行流程
①Stream的实例化
②一系列的中间操作(过滤,映射,。。。)
③终止操作
4.说明:
①一个中间链操作,对数据源的数据进行处理。
②一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用。
Stream的实例化:
@Test
public void test() {
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
Stream
<Employee> employeeStream
= employees
.parallelStream();
}
@Test
public void test2() {
int[] arr
= new int[]{1, 2, 3, 4, 5, 6};
IntStream stream
= Arrays
.stream(arr
);
}
@Test
public void test3() {
Stream
<Integer> stream
= Stream
.of(1, 2, 3, 4, 5, 6);
}
@Test
public void test4() {
Stream
.iterate(0, t
-> t
+ 2).limit(10).forEach(System
.out
::println
);
Stream
.generate(Math
::random
).limit(10).forEach(System
.out
::println
);
}
Stream的中间操作:
1.筛选与切片
@Test
public void test(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
stream
.filter(e
->e
.getAge()>25).forEach(System
.out
::println
);
}
@Test
public void test2(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
stream
.limit(5).forEach(System
.out
::println
);
}
@Test
public void test3(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
stream
.skip(5).forEach(System
.out
::println
);
}
@Test
public void test4(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
stream
.distinct().forEach(System
.out
::println
);
}
2.映射
@Test
public void test() {
int a
[] = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
IntStream stream
= Arrays
.stream(a
);
stream
.map(str
-> str
+ str
).forEach(System
.out
::println
);
}
@Test
public void test2() {
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
stream
.map(Employee
::getAge
).filter(age
-> age
> 25).forEach(System
.out
::println
);
}
3.排序
@Test//自然排序
public void test() {
int a[] = new int[]{1, 2, 3, 5, 9, 7, 6, 45, 65};
IntStream stream = Arrays.stream(a);
stream.sorted().forEach(System.out::print);
}
@Test//定制排序
public void test2() {
List<Employee> employees = EmployeeData.getEmployees();
Stream<Employee> stream = employees.stream();
stream.sorted((o1, o2) -> {
return -o1.getAge().compareTo(o2.getAge());
}).forEach(System.out::println);
}
@Test//定制排序
public void test3() {
List<Employee> employees = EmployeeData.getEmployees();
Stream<Employee> stream = employees.stream();
stream.sorted((o1, o2) -> {
if (o1.getAge() != o2.getAge()) {
return o1.getAge().compareTo(o2.getAge());
} else {
return o1.getId().compareTo(o2.getId());
}
}).forEach(System.out::println);
}
Stream的终止操作
1.匹配与查找
@Test
public void test(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
boolean b
= stream
.allMatch(e
-> e
.getAge() > 23);
System
.out
.println(b
);
}
@Test
public void test2(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
boolean b
= stream
.anyMatch(e
-> e
.getAge() > 23);
System
.out
.println(b
);
}
@Test
public void test3(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
boolean b
= stream
.noneMatch(e
-> e
.getName().contains("java"));
System
.out
.println(b
);
}
@Test
public void test4(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
Optional
<Employee> first
= stream
.findFirst();
System
.out
.println(first
);
}
@Test
public void test5(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
Optional
<Employee> any
= stream
.findAny();
System
.out
.println(any
);
}
@Test
public void test6(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
long count
= stream
.count();
System
.out
.println(count
);
}
@Test
public void test7(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
Optional
<Employee> max
= stream
.max((e1
, e2
) -> e1
.getAge().compareTo(e2
.getAge()));
System
.out
.println(max
);
}
@Test
public void test8(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
Optional
<Employee> min
= stream
.max((e1
, e2
) -> -(e1
.getAge().compareTo(e2
.getAge())));
System
.out
.println(min
);
}
2.归约
@Test
public void test(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
Optional
<Integer> reduce
= stream
.map(e
-> e
.getAge()).reduce((d1
, d2
) -> d1
+ d2
);
System
.out
.println(reduce
);
}
@Test
public void test2(){
Integer a
[]=new Integer []{1,2,3,4,5,6,7,8,9};
Stream
<Integer> stream
= Arrays
.stream(a
);
Integer reduce
= stream
.reduce(0, Integer
::sum
);
System
.out
.println(reduce
);
}
3.收集
@Test
public void test(){
List
<Employee> employees
= EmployeeData
.getEmployees();
Stream
<Employee> stream
= employees
.stream();
List
<Employee> collect
= stream
.collect(Collectors
.toList());
for (Employee employee
: collect
) {
System
.out
.print(employee
+" ");
}
}
3.Optional类
Optional类:为了在程序中避免出现空指针异常而创建的。
常用的方法:
ofNullable(T t
)
ofElse(T t
)
get()://如果调用对象包含值,返回调用对象,否则抛出异常。
public class OptionalTest {
@Test
public void test() {
Person p
=new Person();
String boyName
= getBoyName(p
);
System
.out
.println(boyName
);
}
@Test
public void test2(){
Person p
=null
;
String boyName
= getBoyName(p
);
System
.out
.println(boyName
);
}
@Test
public void test3(){
Person p
=null
;
System
.out
.println(getName(p
));
}
public String
getBoyName(Person person
){
return person
.getBoy().getName();
}
public String
getName(Person person
){
Optional
<Person> person1
= Optional
.ofNullable(person
);
Person person2
= person1
.orElse(new Person());
Optional
<Boy> boy
= Optional
.ofNullable(person2
.getBoy());
Boy boy1
= boy
.orElse(new Boy("Tom"));
return boy1
.getName();
}
}
class Person {
private Boy boy
;
public Person() {
}
public Person(Boy boy
) {
this.boy
= boy
;
}
public Boy
getBoy() {
return boy
;
}
public void setBoy(Boy boy
) {
this.boy
= boy
;
}
}
class Boy {
private String name
;
public Boy() {
}
public Boy(String name
) {
this.name
= name
;
}
public String
getName() {
return name
;
}
public void setName(String name
) {
this.name
= name
;
}
}
十五,JDBC核心技术
1.概述
软件架构方式: B/S:浏览器 C/S:客户端
数据的持久化
把数据保存到可掉电式存储设备中以供之后使用
JDBC的理解:
JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API)
简单理解为:JDBC,是SUN提供的一套 API,使用这套API可以实现对具体数据库的操作(获取连接、关闭连接、DML、DDL、DCL)
图示理解:
2.获取连接
驱动和url
Driver driver
=new com.mysql.jdbc.Driver();
String url
="jdbc:mysql://localhost:3306/test";
jdbc
:mysql
:协议
localhost
:ip地址
3306 :端口号
test:数据库
方式一
@Test
public void test() throws SQLException
{
Driver driver
= new com.mysql.jdbc.Driver();
String url
= "jdbc:mysql://localhost:3306/test";
Properties prop
= new Properties();
prop
.setProperty("user", "root");
prop
.setProperty("password", "yhd666");
Connection connect
= driver
.connect(url
, prop
);
}
上述代码中显式出现了第三方数据库的API
方拾二
@Test
public void test2() throws Exception
{
Class
clazz = Class
.forName("com.mysql.jdbc.Driver");
Driver driver
= (Driver
) clazz
.newInstance();
String url
= "jdbc:mysql://localhost:3306/test";
Properties prop
= new Properties();
prop
.setProperty("user", "root");
prop
.setProperty("password", "yhd666");
Connection connect
= driver
.connect(url
, prop
);
System
.out
.println(connect
);
}
方式三
@Test
public void test3() throws Exception
{
DriverManager
.registerDriver((Driver
) Class
.forName("com.mysql.jdbc.Driver").newInstance());
Connection connection
= DriverManager
.getConnection("jdbc:mysql://localhost:3306/test", "root", "yhd666");
System
.out
.println(connection
);
}
使用DriverManager实现数据库的连接。体会获取连接必要的4个基本要素。
方式四
@Test
public void testConnection4() throws Exception
{
String url
= "jdbc:mysql://localhost:3306/test";
String user
= "root";
String password
= "yhd666";
String driverName
= "com.mysql.jdbc.Driver";
Class
.forName(driverName
);
Connection conn
= DriverManager
.getConnection(url
, user
, password
);
System
.out
.println(conn
);
}
方式五
@Test
public void test5() throws Exception
{
InputStream is
= Test1
.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties prop
= new Properties();
prop
.load(is
);
String user
= prop
.getProperty("user");
String password
= prop
.getProperty("password");
String url
= prop
.getProperty("url");
String driverClass
= prop
.getProperty("driverClass");
Class
.forName(driverClass
);
Connection connection
= DriverManager
.getConnection(url
, user
, password
);
System
.out
.println(connection
);
}
其中,配置文件声明在工程的src目录下:【jdbc.properties】
```properties
user=root
password=yhd666
url=jdbc:mysql://localhost:3306/test
driverClass=com.mysql.jdbc.Driver
3.PreparedStatement
Statement
数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。
- 在 java
.sql 包中有
3 个接口分别定义了对数据库的调用的不同方式:
- Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。
- PrepatedStatement:SQL 语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。
- CallableStatement:用于执行 SQL 存储过程
使用Statement操作数据表的弊端
- 通过调用 Connection 对象的
createStatement() 方法创建该对象。该对象用于执行静态的 SQL 语句,并且返回执行结果。
- Statement 接口中定义了下列方法用于执行 SQL 语句:
```sql
int excuteUpdate(String sql
):执行更新操作INSERT、UPDATE、DELETE
ResultSet
executeQuery(String sql
):执行查询操作SELECT
```
- 但是使用Statement操作数据表存在弊端:
- **问题一:存在拼串操作,繁琐
**
- **问题二:存在SQL注入问题
**
其他问题:
Statement没办法操作Blob类型变量
Statement实现批量插入时,效率较低
- SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令
(如:SELECT user
, password FROM user_table WHERE user
='a' OR
1 = ' AND password = ' OR
'1' = '1') ,从而利用系统的 SQL 引擎完成恶意行为的做法。
- 对于 Java 而言,要防范 SQL 注入,只要用
PreparedStatement(从Statement扩展而来
) 取代 Statement 就可以了。
JDBCUtils封装获取连接和关闭资源
public class JDBCUtils {
public static Connection
getConnection()throws Exception
{
InputStream is
= JDBCUtils
.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties prop
= new Properties();
prop
.load(is
);
String driverClass
=prop
.getProperty("driverClass");
String url
=prop
.getProperty("url");
String user
= prop
.getProperty("user");
String password
= prop
.getProperty("password");
Class
.forName(driverClass
);
Connection connection
= DriverManager
.getConnection(url
, user
, password
);
return connection
;
}
public static void closeResource(Connection co
, PreparedStatement ps
, ResultSet rs
){
try {
if (co
!=null
){
co
.close();
}
if (ps
!=null
){
ps
.close();
}
if (rs
!=null
){
rs
.close();
}
} catch (SQLException e
) {
e
.printStackTrace();
}
}
}
增删改操作
添加操作
@Test
public void add(){
Connection co
=null
;
PreparedStatement ps
=null
;
try {
co
=JDBCUtils
.getConnection();
String sql
="insert into customers(name,email,birth) values(?,?,?);";
ps
= co
.prepareStatement(sql
);
ps
.setObject(1,"yinhuidong");
ps
.setObject(2,"1972039773@qq.com");
SimpleDateFormat format
= new SimpleDateFormat("yyyy-MM-dd");
java
.util
.Date date
= format
.parse("1998-11-16");
ps
.setObject(3,new Date(date
.getTime()));
ps
.execute();
} catch (Exception e
) {
e
.printStackTrace();
} finally {
JDBCUtils
.closeResource(co
,ps
,null
);
}
}
删除操作
@Test
public void delete(){
Connection co
=null
;
PreparedStatement ps
=null
;
try {
co
=JDBCUtils
.getConnection();
String sql
="delete from customers where id = ?;";
ps
=co
.prepareStatement(sql
);
ps
.setObject(1,20);
ps
.execute();
} catch (Exception e
) {
e
.printStackTrace();
} finally {
JDBCUtils
.closeResource(co
,ps
,null
);
}
}
修改操作:
@Test
public void update(){
Connection co
=null
;
PreparedStatement ps
=null
;
try {
co
=JDBCUtils
.getConnection();
String sql
="update customers set name=? where id =?;";
ps
=co
.prepareStatement(sql
);
ps
.setObject(1,"尹会东");
ps
.setObject(2,1);
ps
.execute();
} catch (Exception e
) {
e
.printStackTrace();
} finally {
JDBCUtils
.closeResource(co
,ps
,null
);
}
}
通用增删改:
public static void update(String sql
,Object
...args
){
Connection conn
=null
;
PreparedStatement ps
=null
;
try {
conn
=getConnection();
ps
=conn
.prepareStatement(sql
);
for (int i
= 0; i
<args
.length
; i
++) {
ps
.setObject(i
+1,args
[i
]);
}
ps
.execute();
} catch (Exception e
) {
e
.printStackTrace();
} finally {
closeResource(conn
,ps
,null
);
}
}
通用查询操作
public static <T>List
<T> find1(Class
<T>clazz
,String sql
,Object
...args
) {
Connection co
=null
;
PreparedStatement ps
=null
;
ResultSet rs
=null
;
try {
co
=getConnection();
ps
=co
.prepareStatement(sql
);
for (int i
= 0; i
<args
.length
; i
++) {
ps
.setObject(i
+1,args
[i
]);
}
rs
=ps
.executeQuery();
ResultSetMetaData data
= rs
.getMetaData();
int count
= data
.getColumnCount();
ArrayList
<T> list
= new ArrayList<>();
while (rs
.next()){
T t
= clazz
.newInstance();
for (int i
= 0; i
<count
; i
++) {
Object value
=rs
.getObject(i
+1);
String name
= data
.getColumnLabel(i
+ 1);
Field field
= clazz
.getDeclaredField(name
);
field
.setAccessible(true);
field
.set(t
,value
);
}
list
.add(t
);
}
return list
;
} catch (Exception e
) {
e
.printStackTrace();
} finally {
closeResource(co
,ps
,rs
);
}
return null
;
}
表的列名和对象的属性名不一致的解决办法
Java与SQL对应数据类型转换表
| Java类型
| SQL类型
|
| ------------------ | ------------------------ |
| boolean | BIT
|
| byte | TINYINT
|
| short | SMALLINT
|
| int | INTEGER
|
| long | BIGINT
|
| String
| CHAR
,VARCHAR
,LONGVARCHAR
|
| byte array
| BINARY
, VAR BINARY
|
| java
.sql
.Date
| DATE
|
| java
.sql
.Time
| TIME
|
| java
.sql
.Timestamp
| TIMESTAMP
|
1. **如何获取 ResultSetMetaData
**: 调用 ResultSet 的
getMetaData() 方法即可
2. **获取 ResultSet 中有多少列
**:调用 ResultSetMetaData 的
getColumnCount() 方法
3. **获取 ResultSet 每一列的列的别名是什么
**:调用 ResultSetMetaData 的
getColumnLabel() 方法
JDBC API小结
- 两种思想
- 面向接口编程的思想
- ORM思想
(object relational mapping
)
- 一个数据表对应一个java类
- 表中的一条记录对应java类的一个对象
- 表中的一个字段对应java类的一个属性
> sql是需要结合列名和表的属性名来写。注意起别名。
- 两种技术
- JDBC结果集的元数据:ResultSetMetaData
- 获取列数:
getColumnCount()
- 获取列的别名:
getColumnLabel()
- 通过反射,创建指定类的对象,获取指定的属性并赋值
面试题:statement和preparedStatement的区别
操作Blob类型的变量
@Test
public void test(){
Connection co
=null
;
PreparedStatement ps
=null
;
try {
co
=JDBCUtils
.getConnection();
String sql
="insert into customers(name,email,birth,photo)values(?,?,?,?);";
ps
=co
.prepareStatement(sql
);
ps
.setObject(1,"宋红康");
ps
.setObject(2,"shk@126.com");
ps
.setObject(3,"1988-11-13");
FileInputStream fis
= new FileInputStream("D:\\copy1.jpg");
ps
.setObject(4,fis
);
ps
.execute();
} catch (SQLException e
) {
e
.printStackTrace();
} catch (FileNotFoundException e
) {
e
.printStackTrace();
} finally {
JDBCUtils
.closeResource(co
,ps
,null
);
}
}
@Test
public void test2(){
Connection co
=null
;
PreparedStatement ps
=null
;
ResultSet rs
=null
;
InputStream bs
=null
;
FileOutputStream fos
=null
;
try {
co
=JDBCUtils
.getConnection();
String sql
="select * from customers where id=?;";
ps
=co
.prepareStatement(sql
);
ps
.setObject(1,22);
rs
=ps
.executeQuery();
while (rs
.next()) {
Integer id
= (Integer
) rs
.getObject(1);
String name
= (String
) rs
.getObject(2);
String email
= (String
) rs
.getObject(3);
Date birth
= (Date
) rs
.getObject(4);
Customer customer
= new Customer(id
,name
,email
,birth
);
System
.out
.println(customer
);
Blob photo
=rs
.getBlob(5);
bs
= photo
.getBinaryStream();
fos
= new FileOutputStream("2.jpg");
byte[]bytes
=new byte[1024];
int len
;
while ((len
=bs
.read(bytes
))!=-1) {
fos
.write(bytes
,0,len
);
}
}
} catch (SQLException e
) {
e
.printStackTrace();
} catch (IOException e
) {
e
.printStackTrace();
} finally {
JDBCUtils
.closeResource(co
,ps
,rs
);
try {
if (bs
!=null
){
bs
.close();
}
if (fos
!=null
){
fos
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
}
插入中遇到的问题:
批处理
@Test
public void test() {
Connection conn
= null
;
PreparedStatement ps
= null
;
try {
conn
= JDBCUtils
.getConnection();
String sql
= "insert into goods(name)values(?)";
ps
= conn
.prepareStatement(sql
);
for (int i
= 1; i
<= 20000; i
++) {
ps
.setString(1, "name_" + i
);
ps
.executeUpdate();
}
} catch (SQLException e
) {
e
.printStackTrace();
} finally {
JDBCUtils
.closeResource(conn
, ps
, null
);
}
}
@Test
public void test3(){
Connection conn
= null
;
PreparedStatement ps
= null
;
try {
conn
= JDBCUtils
.getConnection();
conn
.setAutoCommit(false);
String sql
= "insert into goods(name)values(?)";
ps
= conn
.prepareStatement(sql
);
for (int i
= 0; i
<=20000 ; i
++) {
ps
.setString(1, "name_" + i
);
ps
.addBatch();
if (i
%500==0){
ps
.executeBatch();
ps
.clearBatch();
}
}
conn
.commit();
} catch (SQLException e
) {
e
.printStackTrace();
} finally {
JDBCUtils
.closeResource(conn
,ps
,null
);
}
}
4.事务
1.事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。
* > 一组逻辑操作单元:一个或多个DML操作。
> 2.事务处理的原则:
> 保证所事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。
> 当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存
> 下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态。
说明:
1.数据一旦提交,就不可回滚
* 2.哪些操作会导致数据的自动提交?
* >DDL操作一旦执行,都会自动提交。
* >set autocommit = false 对DDL操作失效
* >DML默认情况下,一旦执行,就会自动提交。
* >我们可以通过set autocommit = false的方式取消DML操作的自动提交。
* >默认在关闭连接时,会自动的提交数据
考虑事务以后的转账问题
@Test
public void test() {
Connection co
= null
;
try {
co
= JDBCUtils
.getConnection();
co
.setAutoCommit(false);
String sql1
= "update user_table set balance=balance-? where user=?";
String sql2
= "update user_table set balance=balance+? where user=?";
update(co
,sql1
,100,"AA");
update(co
,sql2
,100,"BB");
co
.commit();
System
.out
.println("转账成功!");
} catch (SQLException e
) {
try {
co
.rollback();
System
.out
.println("转账失败!");
} catch (SQLException e1
) {
e1
.printStackTrace();
}
} finally {
JDBCUtils
.closeResource(co
,null
,null
);
}
}
public static int update(Connection co
, String sql
, Object
... args
) {
PreparedStatement ps
= null
;
try {
ps
= co
.prepareStatement(sql
);
for (int i
= 0; i
< args
.length
; i
++) {
ps
.setObject(i
+ 1, args
[i
]);
}
return ps
.executeUpdate();
} catch (SQLException e
) {
e
.printStackTrace();
} finally {
JDBCUtils
.closeResource(null
, ps
, null
);
}
return 0;
}
事务的属性
ACID
数据操作过程中可能出现的问题:(针对隔离性)
数据库的四种隔离级别:(一致性和并发性:一致性越好,并发性越差)
如何查看并设置隔离级别:
5.连接池技术
传统连接存在的问题:
使用数据库连接池大的好处
1.提高程序的响应速度(减少了创建连接相应的时间)
2.降低资源的消耗(可以重复使用已经提供好的连接)
3.便于连接的管理
c3p0连接池
private static DataSource cpds
= new ComboPooledDataSource("helloc3p0");
public static Connection
getConnection() throws SQLException
{
Connection conn
= cpds
.getConnection();
return conn
;
}
c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="helloc3p0">
<property name="driverClass">com.mysql.jdbc.Driver
</property>
<property name="jdbcUrl">jdbc:mysql:///test
</property>
<property name="user">root
</property>
<property name="password">yhd666
</property>
<property name="acquireIncrement">5
</property>
<property name="initialPoolSize">10
</property>
<property name="minPoolSize">10
</property>
<property name="maxPoolSize">100
</property>
<property name="maxStatements">50
</property>
<property name="maxStatementsPerConnection">2
</property>
</named-config>
</c3p0-config>
dbcp连接池
private static DataSource source
= null
;
static{
try {
Properties pros
= new Properties();
InputStream is
= ClassLoader
.getSystemClassLoader().getResourceAsStream("dbcp.properties");
pros
.load(is
);
source
= BasicDataSourceFactory
.createDataSource(pros
);
} catch (Exception e
) {
e
.printStackTrace();
}
}
public static Connection
getConnection2() throws SQLException
{
Connection conn
= source
.getConnection();
return conn
;
}
dbcp.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///test
username=root
password=yhd666
initialSize=10
druid连接池
private static DataSource ds
= null
;
static {
try {
Properties pro
= new Properties();
pro
.load(ClassLoader
.getSystemClassLoader().getResourceAsStream("druid.properties"));
ds
= DruidDataSourceFactory
.createDataSource(pro
);
} catch (Exception e
) {
e
.printStackTrace();
}
}
public static Connection
getConnection3() {
return ds
.getConnection();
}
druid.properties
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
username=root
password=yhd666
driverClassName=com.mysql.jdbc.Driver
#初始化时的连接数
initialSize=10
#最大连接池数量
maxActive=20
#获取连接时最大等待时间,单位毫秒。
maxWait=1000
#防御sql注入的filter:wall
filters=wall
#mysql下建议关闭
poolPreparedStatements=false
#建议配置为true,不影响性能,并且保证安全性。
testWhileIdle=true
6.DBUtils工具类
通用增删改
使用现成的jar中的QueryRunner测试增、删、改的操作
:
@Test
public void testInsert() {
Connection conn
= null
;
try {
QueryRunner runner
= new QueryRunner();
conn
= JDBCUtils
.getConnection3();
String sql
= "insert into customers(name,email,birth)values(?,?,?)";
int insertCount
= runner
.update(conn
, sql
, "蔡徐坤","caixukun@126.com","1997-09-08");
System
.out
.println("添加了" + insertCount
+ "条记录");
} catch (SQLException e
) {
e
.printStackTrace();
}finally{
JDBCUtils
.closeResource(conn
, null
);
}
}
查询操作1
使用现成的jar中的QueryRunner测试查询的操作
:
@Test
public void testQuery1(){
Connection conn
= null
;
try {
QueryRunner runner
= new QueryRunner();
conn
= JDBCUtils
.getConnection3();
String sql
= "select id,name,email,birth from customers where id = ?";
BeanHandler
<Customer> handler
= new BeanHandler<>(Customer
.class);
Customer customer
= runner
.query(conn
, sql
, handler
, 23);
System
.out
.println(customer
);
} catch (SQLException e
) {
e
.printStackTrace();
}finally{
JDBCUtils
.closeResource(conn
, null
);
}
}
查询操作2
@Test
public void testQuery2() {
Connection conn
= null
;
try {
QueryRunner runner
= new QueryRunner();
conn
= JDBCUtils
.getConnection3();
String sql
= "select id,name,email,birth from customers where id < ?";
BeanListHandler
<Customer> handler
= new BeanListHandler<>(Customer
.class);
List
<Customer> list
= runner
.query(conn
, sql
, handler
, 23);
list
.forEach(System
.out
::println
);
} catch (SQLException e
) {
e
.printStackTrace();
}finally{
JDBCUtils
.closeResource(conn
, null
);
}
}
查询操作3
@Test
public void testQuery3(){
Connection conn
= null
;
try {
QueryRunner runner
= new QueryRunner();
conn
= JDBCUtils
.getConnection3();
String sql
= "select id,name,email,birth from customers where id = ?";
MapHandler handler
= new MapHandler();
Map
<String, Object> map
= runner
.query(conn
, sql
, handler
, 23);
System
.out
.println(map
);
} catch (SQLException e
) {
e
.printStackTrace();
}finally{
JDBCUtils
.closeResource(conn
, null
);
}
}
查询操作4
@Test
public void testQuery4(){
Connection conn
= null
;
try {
QueryRunner runner
= new QueryRunner();
conn
= JDBCUtils
.getConnection3();
String sql
= "select id,name,email,birth from customers where id < ?";
MapListHandler handler
= new MapListHandler();
List
<Map
<String, Object>> list
= runner
.query(conn
, sql
, handler
, 23);
list
.forEach(System
.out
::println
);
} catch (SQLException e
) {
e
.printStackTrace();
}finally{
JDBCUtils
.closeResource(conn
, null
);
}
}
查询操作5
@Test
public void testQuery5(){
Connection conn
= null
;
try {
QueryRunner runner
= new QueryRunner();
conn
= JDBCUtils
.getConnection3();
String sql
= "select count(*) from customers";
ScalarHandler handler
= new ScalarHandler();
Long count
= (Long
) runner
.query(conn
, sql
, handler
);
System
.out
.println(count
);
} catch (SQLException e
) {
e
.printStackTrace();
}finally{
JDBCUtils
.closeResource(conn
, null
);
}
}
@Test
public void testQuery6(){
Connection conn
= null
;
try {
QueryRunner runner
= new QueryRunner();
conn
= JDBCUtils
.getConnection3();
String sql
= "select max(birth) from customers";
ScalarHandler handler
= new ScalarHandler();
Date maxBirth
= (Date
) runner
.query(conn
, sql
, handler
);
System
.out
.println(maxBirth
);
} catch (SQLException e
) {
e
.printStackTrace();
}finally{
JDBCUtils
.closeResource(conn
, null
);
}
}
自定义ResultSetHandler的实现类
@Test
public void testQuery7(){
Connection conn
= null
;
try {
QueryRunner runner
= new QueryRunner();
conn
= JDBCUtils
.getConnection3();
String sql
= "select id,name,email,birth from customers where id = ?";
ResultSetHandler
<Customer> handler
= new ResultSetHandler<Customer>(){
@Override
public Customer
handle(ResultSet rs
) throws SQLException
{
if(rs
.next()){
int id
= rs
.getInt("id");
String name
= rs
.getString("name");
String email
= rs
.getString("email");
Date birth
= rs
.getDate("birth");
Customer customer
= new Customer(id
, name
, email
, birth
);
return customer
;
}
return null
;
}
};
Customer customer
= runner
.query(conn
, sql
, handler
,23);
System
.out
.println(customer
);
} catch (SQLException e
) {
e
.printStackTrace();
}finally{
JDBCUtils
.closeResource(conn
, null
);
}
}
资源关闭
使用dbutils
.jar包中的DbUtils工具类实现连接等资源的关闭:
public static void closeResource1(Connection conn
,Statement ps
,ResultSet rs
){
DbUtils
.closeQuietly(conn
);
DbUtils
.closeQuietly(ps
);
DbUtils
.closeQuietly(rs
);
}
7.DAO设计模式
BaseDao类
package com
.atguigu
.utils
;
import org
.apache
.commons
.dbutils
.QueryRunner
;
import org
.apache
.commons
.dbutils
.handlers
.*
;
import java
.lang
.reflect
.ParameterizedType
;
import java
.lang
.reflect
.Type
;
import java
.sql
.Connection
;
import java
.sql
.SQLException
;
import java
.util
.List
;
import java
.util
.Map
;
public class BaseDao<T> {
private Class
<T> type
;
public BaseDao() {
ParameterizedType parameterizedType
= (ParameterizedType
) this.getClass().getGenericSuperclass();
Type
[] types
= parameterizedType
.getActualTypeArguments();
this.type
= (Class
<T>) types
[0];
}
private QueryRunner runner
= new QueryRunner();
public int update(Connection co
, String sql
, Object
... args
) throws SQLException
{
return runner
.update(co
, sql
, args
);
}
public <T> T
select1(Connection co
, String sql
, Object
... args
) throws SQLException
{
BeanHandler
<T> handler
= new BeanHandler<>((Class
<T>) type
);
return runner
.query(co
, sql
, handler
, args
);
}
public <T> List
<T> select2(Connection co
, String sql
, Object
... args
) throws SQLException
{
BeanListHandler
<T> handler
= new BeanListHandler<>((Class
<T>) type
);
return runner
.query(co
, sql
, handler
, args
);
}
public Map
<String, Object> select3(Connection co
, String sql
, Object
... args
) throws SQLException
{
MapHandler handler
= new MapHandler();
return runner
.query(co
, sql
, handler
, args
);
}
public List
<Map
<String, Object>> select4(Connection co
, String sql
, Object
... args
) throws SQLException
{
MapListHandler handler
= new MapListHandler();
return runner
.query(co
, sql
, handler
, args
);
}
public Object
select5(Connection co
, String sql
, Object
... args
) throws SQLException
{
ScalarHandler handler
= new ScalarHandler();
return runner
.query(co
, sql
, handler
, args
);
}
}
Dao接口
public interface CustomerDao {
int add(Connection co
,Object
...args
) throws SQLException
;
int delete(Connection co
,Object
...args
) throws SQLException
;
int updates(Connection co
,Object
...args
) throws SQLException
;
Customer
FindByValue(Connection co
,Object
...args
) throws SQLException
;
List
<Customer> FindMore(Connection co
, Object
...args
) throws SQLException
;
Long
count(Connection co
,Object
...args
) throws SQLException
;
}
DaoImpl实现类
public class CustomerDaoImpl extends BaseDao<Customer> implements CustomerDao {
@Override
public int add(Connection co
, Object
... args
) throws SQLException
{
String sql
="insert into customers (name,email,birth)values(?,?,?);";
return update(co
,sql
,args
);
}
@Override
public int delete(Connection co
, Object
... args
) throws SQLException
{
String sql
="delete from customers where id=?;";
return update(co
,sql
,args
);
}
@Override
public int updates(Connection co
, Object
... args
) throws SQLException
{
String sql
="update customers set name=?,email=?,birth=? where id=?;";
return update(co
,sql
,args
);
}
@Override
public Customer
FindByValue(Connection co
, Object
... args
) throws SQLException
{
String sql
="select id,name,email,birth from customers where id=?;";
return selectById(co
,sql
,args
);
}
@Override
public List
<Customer> FindMore(Connection co
, Object
... args
) throws SQLException
{
String sql
="select id,name,email,birth from customers ;";
return selectMore(co
,sql
,args
);
}
@Override
public Long
count(Connection co
,Object
...args
) throws SQLException
{
String sql
="select count(*) from customers ;";
return (Long
) selectOne(co
,sql
,args
);
}
}
测试类
public class TestDao {
private CustomerDao dao
=new CustomerDaoImpl();
@Test
public void test(){
Connection co
=null
;
try {
co
=JDBCUtils
.getConnection();
co
.setAutoCommit(false);
SimpleDateFormat format
= new SimpleDateFormat("yyyy-MM-dd");
Date date
= format
.parse("2017-02-21");
int add
= dao
.add(co
, "name", "email", new java.sql.Date(date
.getTime()));
co
.commit();
if (add
>0){
System
.out
.println("添加成功!");
}else{
System
.out
.println("添加失败!");
}
} catch (SQLException e
) {
try {
co
.rollback();
} catch (SQLException e1
) {
e1
.printStackTrace();
}
} catch (ParseException e
) {
e
.printStackTrace();
} finally {
JDBCUtils
.closeResource(co
);
}
}
@Test
public void test2(){
Connection co
=null
;
try {
co
=JDBCUtils
.getConnection();
co
.setAutoCommit(false);
Customer customer
= dao
.FindByValue(co
, 21);
co
.commit();
System
.out
.println(customer
);
} catch (SQLException e
) {
e
.printStackTrace();
} finally {
JDBCUtils
.closeResource(co
);
}
}
}
JDBCUtils工具类
package com
.atguigu
.java6
;
import com
.alibaba
.druid
.pool
.DruidDataSourceFactory
;
import com
.alibaba
.druid
.util
.JdbcUtils
;
import com
.mchange
.v2
.c3p0
.ComboPooledDataSource
;
import org
.apache
.commons
.dbcp
.BasicDataSourceFactory
;
import javax
.sql
.DataSource
;
import java
.io
.InputStream
;
import java
.sql
.Connection
;
import java
.sql
.SQLException
;
import java
.util
.Properties
;
public class JDBCUtils {
private static DataSource source1
=new ComboPooledDataSource("helloc3p0");
public static Connection
getConnection() throws SQLException
{
return source1
.getConnection();
}
private static DataSource source2
=null
;
static{
try {
InputStream is
= JDBCUtils
.class.getClassLoader().getResourceAsStream("dbcp.properties");
Properties prop
= new Properties();
prop
.load(is
);
source2
=BasicDataSourceFactory
.createDataSource(prop
);
} catch (Exception e
) {
e
.printStackTrace();
}
}
public static Connection
getConnection2() throws SQLException
{
return source2
.getConnection();
}
private static DataSource source3
=null
;
static {
try {
Properties prop
= new Properties();
InputStream is
= JDBCUtils
.class.getClassLoader().getResourceAsStream("druid.properties");
prop
.load(is
);
source3
=DruidDataSourceFactory
.createDataSource(prop
);
} catch (Exception e
) {
e
.printStackTrace();
}
}
public static Connection
getConnection3() throws SQLException
{
return source3
.getConnection();
}
public static void closeResource(Connection co
){
JdbcUtils
.close(co
);
}
}