十一,IO流

1.File类

java.io.File

1)File类的使用

  1. 1.file类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)
  2. 2.File类声明在java.io包下
  3. *相对路径:hello.txt 相较于某个路径下,指明的路径。
  4. 绝对路径:D://temp.txt 包含盘符在内的文件或文件目录的路径。
  5. *路径分隔符:window\,url用/。

2)如何创建File类的实例:

  1. public static void main(String[] args) {
  2. File file=new File("D:\\input\\input.txt.txt");
  3. System.out.println(file);//输出文件路径 D:\input\input.txt.txt
  4. File file1 = new File("jdbc.properties");
  5. System.out.println(file1);jdbc.properties
  6. }

3)常用方法:

  1. public static void main(String[] args) {
  2. File file=new File("D:\\input\\input.txt.txt");
  3. File file1 = new File("jdbc.properties");
  4. String path = file.getAbsolutePath();//获取绝对路径
  5. System.out.println(path);//D:\input\input.txt.txt
  6. System.out.println(file1.getAbsolutePath());//E:\IEDADEMO\jdbc.properties
  7. String filePath = file.getPath();//获取路径
  8. System.out.println(filePath);//D:\input\input.txt.txt
  9. System.out.println(file1.getPath());//jdbc.properties
  10. String name = file.getName();//获取名字
  11. System.out.println(name);//input.txt.txt
  12. String parent = file.getParent();//获取上一层目录
  13. System.out.println(parent);//D:\input
  14. long length = file.length();//长度,字节
  15. System.out.println(length);//292
  16. long modified = file.lastModified();//最近修改时间
  17. System.out.println(modified);//1572326293899
  18. /**
  19. * 仅适用于目录
  20. */
  21. File file2 = new File("D:\\wokespace");
  22. String[] list = file2.list();//列出其下一级文件目录
  23. for (String s:list){
  24. System.out.println(s);
  25. }
  26. System.out.println("***********************************************");
  27. File[] files = file2.listFiles();//列出其下一级文件目录的绝对路径
  28. for (File f: files){
  29. System.out.println(f);
  30. }
  31. System.out.println("**************************");
  32. boolean b = file1.renameTo(file);//把file1重命名为file的名字
  33. //要想保证成功,file1在硬盘中是真实存在的,file在硬盘中是不存在的
  34. System.out.println(b);
  35. }
  1. public static void main(String[] args) {
  2. File file = new File("jdbc.properties");
  3. //判断功能
  4. System.out.println(file.isDirectory());//判断是不是一个目录 false
  5. System.out.println(file.isFile());//判断是不是一个文件true
  6. System.out.println(file.exists());//判断是否真实存在true
  7. System.out.println(file.canRead());//判断是否可读true
  8. System.out.println(file.canWrite());//判断是否可写true
  9. System.out.println(file.isHidden());//判读是否隐藏 false
  10. }
  1. public static void main(String[] args) {
  2. //File的创建功能和删除功能
  3. File file = new File("jdbc1.properties");
  4. if (!file.exists()){
  5. try {
  6. file.createNewFile();//创建文件
  7. System.out.println("文件创建成功!");
  8. } catch (IOException e) {
  9. e.printStackTrace();
  10. }
  11. }else{
  12. file.delete();//删除文件,不走回收站,直接删除
  13. System.out.println("文件删除成功!");
  14. }
  15. file.mkdir();//创建单层目录
  16. file.mkdirs();//创建多层目录
  17. }

file.delete()删除目录时,要想删除成功,该目录下不能有文件或目录。

4)面试题:

  1. /**
  2. * 创建一个与File同目录下的另外一个文件,文件名为:haha.txt
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. File file = new File("D:\\temp\\temp1.txt");
  7. File file1 = new File(file.getParent() , "haha.txt");
  8. System.out.println(file.getParent());
  9. try {
  10. boolean newFile = file1.createNewFile();
  11. if (newFile){
  12. System.out.println("创建成功!");
  13. }
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. }
  17. }
  1. /**
  2. * 遍历指定目录下所文件名称,包括子文件目录中的文件
  3. * 1.并计算指定目录占用空间的大小
  4. * 2.删除指定文件下的目录及其下的文件夹
  5. */
  6. public static void main(String[] args) {
  7. File file = new File("D:\\temp");
  8. int sum=print(file);
  9. System.out.println(sum);
  10. }
  11. //遍历指定目录下所文件名称,包括子文件目录中的文件,并计算指定目录占用空间的大小
  12. public static int print(File file){
  13. File []files=file.listFiles();
  14. int sum=0;
  15. for (File f:files){
  16. if (f.isDirectory()){
  17. print(f);
  18. f.delete();
  19. }else{
  20. System.out.println(f.getAbsolutePath());
  21. sum+=f.length();
  22. f.delete();
  23. }
  24. }
  25. return sum;
  26. }
  1. public static void main(String[] args) {
  2. /**
  3. * 判断指定目录下是否存在后缀名为.jpg的文件,如果就输出该文件名;
  4. */
  5. File file = new File("D:\\QQ");
  6. Find(file);
  7. }
  8. public static void Find(File file){
  9. File []files=file.listFiles();
  10. for (File f: files){
  11. if (f.isDirectory()){
  12. Find(f);
  13. }else{
  14. if (f.getName().endsWith(".jpg")){
  15. System.out.println(f.getAbsolutePath());
  16. }
  17. }
  18. }

2.IO流

1)概述

  1. IO流原理及流的分类
  2. input/output的缩写,处理设备之间的数据传输。
  3. input:读取外部数据
  4. output:将程序中的数据输出
  5. 按照操作数据单位的不同,分为字节流(8bit)和字符流(6bit)适合于文本。
  6. 输入流:inputStreamreader
  7. 输出流:outputStreamWriter
  8. 按照流的角色不同:作用在文件上的:节点流,作用在已经有的流上的:处理流。
  9. 按照数据流向:输入流,输出流。
  10. IO流的体系结构
  11. 抽象基类 节点流 缓冲流
  12. InputStream FileInputStream BufferedInputStream
  13. OutputStream FileOutputStream BufferedOutputStream
  14. Reader FileReader BufferedReader
  15. Writer FileWriter BufferedWriter

2)节点流-FileReader和FileWriter

FileReader读入数据的基本操作

说明点:
①read()地理解:返回读入的一个字符,如果达到文件末尾,返回-1
②异常的处理:为了保证流资源一定可以执行关闭操作,需要使用try-catch-finally处理。
③读入的文件一定要存在,否则就会报FileNotFoundException

  1. /**
  2. * FileReader读取硬盘文件
  3. * @param args
  4. */
  5. public static void main(String[] args){
  6. FileReader reader=null;
  7. BufferedReader reader1=null;
  8. try {
  9. reader = new FileReader(new File("jdbc.properties"));//相较于当前工程
  10. reader1 = new BufferedReader(reader);
  11. int data ;//返回读入的一个字符,如果达到文件末尾,返回-1.
  12. while ((data=reader1.read())!=-1){//循环读取数据
  13. System.out.print((char)data);
  14. }
  15. } catch (FileNotFoundException e) {
  16. e.printStackTrace();
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. } finally {//关闭流
  20. if (reader!=null){
  21. try {
  22. reader.close();
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. if(reader1!=null){
  28. try {
  29. reader1.close();
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. }
  35. }
  1. public static void main(String[] args) {
  2. //对read(的升级,使用read的重载方法
  3. FileReader reader=null;
  4. BufferedReader br=null;
  5. try {
  6. reader = new FileReader(new File("jdbc.properties"));
  7. br=new BufferedReader(reader);
  8. char []buf=new char[1024];
  9. int len=0;
  10. while ((len=br.read(buf))!=-1){//返回每次读入buf[]数组中的字符个数,如果达到文件末尾,返回-1
  11. // for(int i=0;i<len;i++){
  12. // System.out.print(buf[i]);
  13. // }
  14. String str=new String(buf,0,len);
  15. System.out.print(str);
  16. }
  17. } catch (FileNotFoundException e) {
  18. e.printStackTrace();
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. } finally{
  22. if (reader!=null){
  23. try {
  24. reader.close();
  25. } catch (IOException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. if (br!=null){
  30. try {
  31. br.close();
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. }
  37. }

FileWriter写出数据的操作

说明:
①输出操作:对应的File可以不存在,如果不存在,在输出过程中,会自动创建此文件。
②如果存在:如果流使用的构造器是FileWriter(file,false)/FileWriter(file):对原有文件覆盖。
如果流使用FileWriter(file,true):不会对原有文件覆盖。

  1. /**
  2. * 从内存写出数据到硬盘文件
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. FileWriter writer = null;
  7. try {
  8. writer= new FileWriter(new File("hello.txt"),true);
  9. //true时表示对原文件的追加,false或不写表示对原文件的覆盖
  10. writer.write("I have a dream !");//写入文件
  11. } catch (IOException e) {
  12. e.printStackTrace();
  13. }finally{
  14. if (writer!=null){
  15. try {
  16. writer.close();
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }
  22. }

使用FileReader和FileWriter实现文本文件的复制

字符流不能处理图片文件

  1. /**
  2. * 将一个文件写入另一个文件
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. FileReader fr=null;
  7. FileWriter fw=null;
  8. try {
  9. fr=new FileReader(new File("E:\\IEDADEMO\\day07\\src\\com\\atguigu\\IO\\IO.txt"));
  10. fw=new FileWriter(new File("hello.txt"));
  11. //数据的读入和写出操作
  12. char []buf=new char[1024];
  13. int len=0;//记录每次读入到数组的数据多少个
  14. while ((len=fr.read(buf))!=-1){
  15. fw.write(buf,0,len);
  16. }
  17. } catch (FileNotFoundException e) {
  18. e.printStackTrace();
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. }finally{
  22. if (fw!=null){
  23. try {
  24. fw.close();
  25. } catch (IOException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. if (fr!=null){
  30. try {
  31. fr.close();
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. }
  37. }

3)节点流-FileInputStream和FileOutputStream

使用FileInputStream不能读取文本文件的测试:
结论:对于文本文件,使用字符流处理
对于非文本文件,使用字节流处理

  1. /**
  2. * 使用FileInputStream不能读取文本文件的测试
  3. */
  4. public static void main(String[] args) {
  5. FileInputStream fis=null;
  6. FileOutputStream fos=null;
  7. try {
  8. fis=new FileInputStream(new File("E:\\IEDADEMO\\day07\\src\\com\\atguigu\\IO\\IO.txt"));
  9. fos=new FileOutputStream(new File("hello.txt"));
  10. byte [] bytes=new byte[1024];
  11. int len=0;
  12. while ((len=fis.read(bytes))!=-1){
  13. fos.write(bytes,0,len);
  14. }
  15. } catch (FileNotFoundException e) {
  16. e.printStackTrace();
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. }finally{
  20. try {
  21. if (fos!=null){
  22. fos.close();
  23. }
  24. if (fis!=null){
  25. fis.close();
  26. }
  27. }catch (IOException e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. }

FileInputStream和FileOutputStream读写非文本文件

  1. /**
  2. * FileInputStream和FileOutputStream读写非文本文件
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. FileInputStream fis=null;
  7. FileOutputStream fos=null;
  8. try {
  9. fis=new FileInputStream(new File("E:\\IEDADEMO\\day07\\src\\下载.png"));
  10. fos=new FileOutputStream(new File("D:\\test.png"));
  11. byte[] bytes=new byte[1024*1024];
  12. int len=0;
  13. while ((len=fis.read(bytes))!=-1) {
  14. fos.write(bytes,0,len);
  15. }
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. } finally {
  19. try {
  20. if (fos!=null){
  21. fos.close();
  22. }
  23. if (fis!=null){
  24. fis.close();
  25. }
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }

写一个复制文件的方法,可以用来直接调用,

  1. public static void main(String[] args) {
  2. File file = new File("hello.txt");
  3. File file1 = new File("D://hello.txt");
  4. Copy(file,file1);
  5. }
  6. public static void Copy(File file,File file1){
  7. FileInputStream fis=null;
  8. FileOutputStream fos=null;
  9. try {
  10. fis=new FileInputStream(file);
  11. fos=new FileOutputStream(file1);
  12. byte [] bytes=new byte [1024];
  13. int len;
  14. while((len=fis.read(bytes))!=-1){
  15. fos.write(bytes,0,len);
  16. }
  17. System.out.println("复制完成!");
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. } finally {
  21. try {
  22. if (fos!=null){
  23. fos.close();
  24. }
  25. if (fis!=null){
  26. fis.close();
  27. }
  28. } catch (IOException e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. }

4)处理流之一:缓冲流

缓冲流作用:提高流的读取写入速度
提高读写速度的原因:内部提供了一个缓冲区:1024*8=8192
缓冲流(字节型)实现非文本文件的复制

  1. public static void main(String[] args) {
  2. FileInputStream fis=null;
  3. FileOutputStream fos=null;
  4. BufferedInputStream bis=null;
  5. BufferedOutputStream bos=null;
  6. try {
  7. fis=new FileInputStream(new File("hello.txt"));
  8. fos=new FileOutputStream(new File("D://hello.txt"));
  9. bis=new BufferedInputStream(fis);
  10. bos=new BufferedOutputStream(fos);
  11. byte [] bytes=new byte[1024];
  12. int len;
  13. while ((len=bis.read(bytes))!=-1){
  14. bos.write(bytes,0,len);
  15. }
  16. System.out.println("复制完成!");
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. } finally {
  20. try {
  21. if (bos!=null){
  22. bos.close();
  23. }
  24. if (bis!=null){
  25. bis.close();
  26. }
  27. if (fos!=null){
  28. fos.close();
  29. }
  30. if (fis!=null){
  31. fis.close();
  32. }
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. }

缓冲流(字符型)实现文本文件的复制
处理流:就是套接在已有流的基础上

  1. public static void main(String[] args) {
  2. FileReader fr=null;
  3. FileWriter fw=null;
  4. BufferedReader br=null;
  5. BufferedWriter bw=null;
  6. try {
  7. fr=new FileReader(new File("hello.txt"));
  8. fw=new FileWriter(new File("D://hello.txt"));
  9. br=new BufferedReader(fr);
  10. bw=new BufferedWriter(fw);
  11. //方式一:
  12. // char [] chars=new char[1024];
  13. // int len=0;
  14. // while ((len=br.read(chars))!=-1){
  15. // bw.write(chars,0,len);
  16. // }
  17. //方式二:
  18. String data;
  19. while ((data=br.readLine())!=null){
  20. bw.write(data);//一次读取一行
  21. bw.newLine();//换行
  22. }
  23. System.out.println("文本复制完成!");
  24. } catch (IOException e) {
  25. e.printStackTrace();
  26. } finally {
  27. try {
  28. if (bw!=null){
  29. bw.close();
  30. }
  31. if (br!=null){
  32. br.close();
  33. }
  34. if (fw!=null){
  35. fw.close();
  36. }
  37. if (fr!=null){
  38. fr.close();
  39. }
  40. } catch (IOException e) {
  41. e.printStackTrace();
  42. }
  43. }
  44. }

5)面试题

1.图片加密和图片解密

  1. /***
  2. * 图片加密
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. BufferedInputStream bis=null;
  7. BufferedOutputStream bos=null;
  8. try {
  9. bis=new BufferedInputStream(new FileInputStream(new File("D:\\尹会东.jpg")));
  10. bos=new BufferedOutputStream(new FileOutputStream(new File("D:\\copy.jpg")));
  11. int len=0;
  12. byte [] bytes=new byte[1024];
  13. while ((len=bis.read(bytes))!=-1){
  14. for (int i = 0; i <len ; i++) {
  15. bytes[i]= (byte) (bytes[i]^5);//加密操作
  16. }
  17. bos.write(bytes,0,len);
  18. }
  19. System.out.println("加密完成!");
  20. } catch (IOException e) {
  21. e.printStackTrace();
  22. } finally {
  23. try {
  24. if (bis!=null){
  25. bis.close();
  26. }
  27. if (bos!=null){
  28. bos.close();
  29. }
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. }
  1. /**
  2. * 图片解密
  3. */
  4. public static void main(String[] args) {
  5. BufferedInputStream bis=null;
  6. BufferedOutputStream bos=null;
  7. try {
  8. bis=new BufferedInputStream(new FileInputStream(new File("D:\\copy.jpg")));
  9. bos=new BufferedOutputStream(new FileOutputStream(new File("D:\\copy1.jpg")));
  10. int len=0;
  11. byte [] bytes=new byte[1024];
  12. while ((len=bis.read(bytes))!=-1){
  13. for (int i = 0; i <len ; i++) {
  14. bytes[i]= (byte) (bytes[i]^5);//解密操作
  15. }
  16. bos.write(bytes,0,len);
  17. }
  18. System.out.println("解密完成!");
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. } finally {
  22. try {
  23. if (bis!=null){
  24. bis.close();
  25. }
  26. if (bos!=null){
  27. bos.close();
  28. }
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. }

2.获取文本上每个字符出现的次数

  1. /**
  2. * 获取文本上每个字符出现的次数
  3. */
  4. public static void main(String[] args) {
  5. HashMap<Character, Integer> map = new HashMap<>();
  6. BufferedReader br=null;
  7. BufferedWriter bw=null;
  8. try {
  9. br=new BufferedReader(new FileReader(new File("hello.txt")));
  10. bw=new BufferedWriter(new FileWriter(new File("D:\\WorldCount.txt")));
  11. int c=0;
  12. while ((c=br.read())!=-1){
  13. char ch= (char) c;
  14. if (map.get(ch)==null){
  15. map.put(ch,1);
  16. }else{
  17. map.put(ch,map.get(ch)+1);
  18. }
  19. }
  20. Set<Map.Entry<Character, Integer>> set = map.entrySet();
  21. Iterator<Map.Entry<Character, Integer>> iterator = set.iterator();
  22. while (iterator.hasNext()){
  23. bw.write(iterator.next().getKey()+"--------------"+iterator.next().getValue());
  24. bw.newLine();
  25. }
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. } finally {
  29. try {
  30. if (bw!=null){
  31. bw.close();
  32. }
  33. if (br!=null){
  34. br.close();
  35. }
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. }

3.将一个文件写入另一个文件

  1. /**
  2. * 将一个文件写入另一个文件
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. FileReader fr=null;
  7. FileWriter fw=null;
  8. try {
  9. fr=new FileReader(new File("E:\\IEDADEMO\\day07\\src\\com\\atguigu\\IO\\IO.txt"));
  10. fw=new FileWriter(new File("hello.txt"));
  11. //数据的读入和写出操作
  12. char []buf=new char[1024];
  13. int len=0;//记录每次读入到数组的数据多少个
  14. while ((len=fr.read(buf))!=-1){
  15. fw.write(buf,0,len);
  16. }
  17. } catch (FileNotFoundException e) {
  18. e.printStackTrace();
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. }finally{
  22. if (fw!=null){
  23. try {
  24. fw.close();
  25. } catch (IOException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. if (fr!=null){
  30. try {
  31. fr.close();
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. }
  37. }

6)处理流之二:转换流

1.作用:提供了字节流和字符流的转换
2.转换流属于字符流
InputStreamReader:将一个字节的输入流转换为字符的输入流
OutputStreamWriter:将一个字符的输出流转换为字节的输出流
3.解码:字节,字节数组——->字符数组,字符串
编码:字符数组,字符串——->字节,字节数组
4.字符集

  1. public static void main(String[] args) {
  2. FileInputStream fis=null;
  3. InputStreamReader isr=null;
  4. FileOutputStream fos=null;
  5. OutputStreamWriter osw=null;
  6. try {
  7. fis = new FileInputStream(new File("hello.txt"));
  8. // InputStreamReader isr = new InputStreamReader(fis);//使用系统默认字符集
  9. isr = new InputStreamReader(fis, StandardCharsets.UTF_8);//指定字符集
  10. fos=new FileOutputStream(new File("D:\\Temps.txt"));
  11. osw=new OutputStreamWriter(fos,"utf-8");
  12. char [] chars=new char[1024];
  13. int len;
  14. while ((len=isr.read(chars))!=-1){
  15. osw.write(chars,0,len);
  16. }
  17. // while ((len=isr.read(chars))!=-1){
  18. // String str=new String(chars,0,len);
  19. // System.out.println(str);
  20. // }
  21. } catch (FileNotFoundException e) {
  22. e.printStackTrace();
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. } finally {
  26. try {
  27. if (isr!=null){
  28. isr.close();
  29. }
  30. if (fis!=null){
  31. fis.close();
  32. }
  33. if (osw!=null){
  34. osw.close();
  35. }
  36. if (fos!=null){
  37. fos.close();
  38. }
  39. } catch (IOException e) {
  40. e.printStackTrace();
  41. }
  42. }
  43. }

7)其他流(了解)

其他流(了解)
1.标准的输入输出流
1.1
System.in标准的输入流
System.out标准的输出流
1.2我们可以通过System类的setIn(InputStream)/setOut(OutputStream)方式重新指定输入和输出的流。
1.3练习:IO5

  1. public static void main(String[] args) {
  2. /**
  3. * 键盘输入字符,如果是e或exit程序结束,否则转化为大写输出
  4. */
  5. InputStreamReader isr=new InputStreamReader(System.in);
  6. BufferedReader br=new BufferedReader(isr);
  7. while (true){
  8. String data= null;
  9. try {
  10. data = br.readLine();
  11. if (data.equalsIgnoreCase("e")||data.equalsIgnoreCase("exit")){
  12. System.out.println("程序结束!");
  13. break;
  14. }else{
  15. System.out.println(data.toUpperCase());
  16. }
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. }finally {
  20. try {
  21. if (isr!=null){
  22. isr.close();
  23. }
  24. if (br!=null){
  25. br.close();
  26. }
  27. } catch (IOException e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. }
  32. }

2.打印流
PrintStream
PrintWriter
3.数据流
DataInputStream
DataOutputStream
4.随机存取文件流
RandomAccessFile
既可以读,也可以写。
实现了DataInput和DataOutput接口
java.io下,但是直接继承Object类
如果RandomAccessFile作为输出流时,写出到的文件不存在,会自动创建,
如果写出到的文件存在,会对原有文件进行覆盖,(默认情况下,从头覆盖)

  1. public static void main(String[] args) {
  2. RandomAccessFile file = null;
  3. RandomAccessFile file1 = null;
  4. try {
  5. file=new RandomAccessFile(new File("hello.txt"),"r");
  6. file1=new RandomAccessFile(new File("D:\\object.txt"),"rw");
  7. byte []bytes=new byte[1024];
  8. int len=0;
  9. while ((len=file.read(bytes))!=-1){
  10. file1.write(bytes,0,len);
  11. }
  12. } catch (IOException e) {
  13. e.printStackTrace();
  14. } finally {
  15. try {
  16. if (file!=null){
  17. file.close();
  18. }
  19. if (file1!=null){
  20. file1.close();
  21. }
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }

RandomAccessFile类实现数据插入

  1. public static void main(String[] args) {
  2. RandomAccessFile raf=null;
  3. try {
  4. raf=new RandomAccessFile("hello.txt","rw");
  5. //raf.seek(3);//指定开始覆盖的位置
  6. raf.seek(new File("hello.txt").length());//最后面插入
  7. /**
  8. * 如果想要在中间插入,可以先将后面的内容读取到内存的某个变量,
  9. * 然后写入要插入的数据,再将变量中的内容插入末尾。
  10. */
  11. raf.write("xyz".getBytes());
  12. } catch (IOException e) {
  13. e.printStackTrace();
  14. } finally {
  15. try {
  16. if (raf!=null){
  17. raf.close();
  18. }
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. }

8)对象流

  1. ObjectInputStream用于存储和读取基本数据类型或对象的流处理。
  2. 序列化:用ObjectOutputStream将数据从内存写入硬盘
  3. 反序列化:ObjectInputStream将数据从硬盘读入内存。

要求对象所属的类是可序列化的—->实现了Seralizable接口

面试题:如何理解对象序列化机制?

  1. 把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久的保存在硬盘上,或者通过网络,
  2. 将这种二进制流传输到另一个网络节点,当其他程序获取了这种二进制流,就可以恢复成原来的Java对象。
  3. 序列化的好处在于将任何实现了Seralizable接口的对象转化为字节数据,使其在保存和传输中可被还原。

序列化

  1. public static void main(String[] args) {
  2. //序列化过程:
  3. ObjectOutputStream oos=null;
  4. try {
  5. oos=new ObjectOutputStream(new FileOutputStream(new File("D:\\object.txt")));
  6. oos.writeObject(new String("我爱北京天安门"));
  7. oos.flush();
  8. } catch (IOException e) {
  9. e.printStackTrace();
  10. } finally {
  11. if(oos!=null){
  12. try {
  13. oos.close();
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. }
  19. }

反序列化

  1. //反序列化
  2. public static void main(String[] args) {
  3. ObjectInputStream ois =null;
  4. try {
  5. ois=new ObjectInputStream(new FileInputStream(new File("D://object.txt")));
  6. Object object = ois.readObject();
  7. String str= (String) object;
  8. System.out.println(str);
  9. } catch (IOException e) {
  10. e.printStackTrace();
  11. } catch (ClassNotFoundException e) {
  12. e.printStackTrace();
  13. } finally {
  14. if (ois!=null){
  15. try {
  16. ois.close();
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }
  22. }

自定义类实现序列化与反序列化操作

  1. 1.需要实现java.io.Serializable接口
  2. 2. public static final long serialVersionUID= 6080347956336285349L;
  3. 3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性也必须是可序列化的。
  4. (默认情况下基本数据类型是可序列化的)
  5. 4.不能序列化statictransient
  1. public class Person implements java.io.Serializable{
  2. public static final long serialVersionUID= 6080347956336285349L;
  3. private String name;
  4. private int age;
  5. public Person() {
  6. }
  7. public Person(String name, int age) {
  8. this.name = name;
  9. this.age = age;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public int getAge() {
  18. return age;
  19. }
  20. public void setAge(int age) {
  21. this.age = age;
  22. }
  23. @Override
  24. public String toString() {
  25. return "Person{" +
  26. "name='" + name + '\'' +
  27. ", age=" + age +
  28. '}';
  29. }
  30. }
  1. public static void main(String[] args) {
  2. //序列化
  3. ObjectOutputStream oos =null;
  4. ObjectInputStream ois=null;
  5. try {
  6. oos=new ObjectOutputStream(new FileOutputStream(new File("D://object.txt")));
  7. Person person = new Person("张贝贝", 25);
  8. oos.writeObject(person);
  9. //反序列化
  10. ois=new ObjectInputStream(new FileInputStream(new File("D:\\object.txt")));
  11. Object obj=ois.readObject();
  12. Person p1= (Person) obj;
  13. System.out.println(p1.toString());
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. } catch (ClassNotFoundException e) {
  17. e.printStackTrace();
  18. } finally {
  19. try {
  20. if (ois!=null){
  21. ois.close();
  22. }
  23. if (oos!=null){
  24. oos.close();
  25. }
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }

serialVersionUID的理解

如果不手动写,Java会自动生成一个。
如果序列化以后修改了类,serialVersionUID也会被Java修改,
反序列化会失败!

十二,网络编程

网络编程中有两个主要的问题:

  1. 1.如何准确的定位到网络上一台或者多台主机:定位主机上的特定应用
  2. 2.找到主机后如何可靠高效的进行数据传输

网络编程中的两个要素

  1. 1.对应的问题:IP和端口号
  2. 2.对应问题二:提供网络通信协议:TCP/IP参考模型

通信要素一:IP和端口号

  1. 1.IP:唯一标识Internet上的计算机(通信实体)
  2. 2.Java中使用InetAddress类代表IP
  3. 3.IP分类:IPV4IPV6;万维网和局域网的区别
  4. 4.域名:www.baidu.com
  5. 5.域名--》NDS--》网络服务器
  6. 6.本地回路地址:127.0.0.1 对应着localhost
  7. 7.如何实例化InetAddress:两个方法;getByName(String host),getLocalHost();

端口号:表示计算机上运行的程序

  1. 不同进程有不同的端口号
  2. Tomcat8080mysql3306oracle1521
  3. 端口号与IP地址组合得出一个网络套接字,Socket
  4. 范围:0-65535
  1. public static void main(String[] args) {
  2. try {
  3. InetAddress name = InetAddress.getByName("127.0.0.1");
  4. System.out.println(name);
  5. InetAddress name1 = InetAddress.getByName("www.baidu.com");
  6. System.out.println(name1);
  7. System.out.println(name.getHostName());
  8. } catch (UnknownHostException e) {
  9. e.printStackTrace();
  10. }
  11. }

TCP:3次握手,UDP:封装数据包

Tcp网络编程

  1. /**
  2. * @author yinhuidong
  3. * @createTime 2020-04-10-21:24
  4. * TCP网络编程1:客户端向服务端发送消息,服务端将消息显示在控制台上
  5. */
  6. public class Test1 {
  7. //客户端
  8. @Test
  9. public void client()throws Exception{
  10. InetAddress address = InetAddress.getByName("127.0.0.1");
  11. Socket socket = new Socket(address, 3307);
  12. OutputStream os = socket.getOutputStream();
  13. os.write("你好,我是客户端".getBytes());
  14. os.close();
  15. socket.close();
  16. }
  17. //服务端
  18. @Test
  19. public void server()throws Exception{
  20. ServerSocket serverSocket = new ServerSocket(3307);
  21. Socket socket = serverSocket.accept();
  22. InputStream is = socket.getInputStream();
  23. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  24. int len;
  25. byte[] buffer = new byte[10];
  26. while ((len=is.read(buffer))!=-1){
  27. baos.write(buffer,0,len);
  28. }
  29. System.out.println(baos.toString());
  30. baos.close();
  31. is.close();
  32. socket.close();
  33. serverSocket.close();
  34. }
  35. }
  1. /**
  2. * @author yinhuidong
  3. * @createTime 2020-04-10-21:40
  4. * 客户端给服务端发送文件,服务端保存文件并告诉客户端自己接收成功
  5. * //如果不关闭资源,会抛出:java.net.SocketException: Connection reset异常
  6. */
  7. public class Test2 {
  8. //客户端
  9. @Test
  10. public void test1() throws Exception {
  11. //获取IP地址
  12. InetAddress address = InetAddress.getByName("127.0.0.1");
  13. //获取socket对象
  14. Socket socket = new Socket(address, 3308);
  15. //写入本地图片
  16. FileInputStream is = new FileInputStream(new File("E:\\9.jpg"));
  17. byte[] buffer = new byte[1024 * 8];
  18. int len;
  19. //将本地图片写出到服务端
  20. OutputStream os = socket.getOutputStream();
  21. while ((len = is.read(buffer)) != -1) {
  22. os.write(buffer, 0, len);
  23. }
  24. socket.shutdownOutput();
  25. //获取输入流准备接受服务端的消息
  26. InputStream stream = socket.getInputStream();
  27. byte[] buffer2 = new byte[10];
  28. int len2;
  29. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  30. while ((len2 = stream.read(buffer2)) != -1) {
  31. baos.write(buffer2, 0, len2);
  32. }
  33. //输出消息到控制台
  34. System.out.println(baos.toString());
  35. baos.close();
  36. stream.close();
  37. os.close();
  38. is.close();
  39. socket.close();
  40. }
  41. @Test
  42. public void test2() throws Exception {
  43. //创建一个服务端ServerSocket
  44. ServerSocket serverSocket = new ServerSocket(3308);
  45. //获取socket
  46. Socket socket = serverSocket.accept();
  47. //获取输入流
  48. InputStream is = socket.getInputStream();
  49. //指定输出流输出文件位置
  50. FileOutputStream fos = new FileOutputStream(new File("E:\\10.jpg"));
  51. int len;
  52. byte[] buffer = new byte[1024 * 8];
  53. while ((len = is.read(buffer)) != -1) {
  54. fos.write(buffer, 0, len);
  55. }
  56. //获取输出流
  57. OutputStream stream = socket.getOutputStream();
  58. //输出内容
  59. stream.write("接收文件成功".getBytes());
  60. stream.close();
  61. fos.close();
  62. is.close();
  63. socket.close();
  64. serverSocket.close();
  65. }
  66. }

UDP网络编程

  1. /**
  2. * @author yinhuidong
  3. * @createTime 2020-04-10-23:03
  4. * UDP网络编程
  5. */
  6. public class Test4 {
  7. //发送端
  8. @Test
  9. public void send()throws Exception{
  10. DatagramSocket socket = new DatagramSocket();
  11. byte []data="我是UDP方式的发送端".getBytes();
  12. InetAddress inet = InetAddress.getLocalHost();
  13. DatagramPacket packet = new DatagramPacket(data, 0, data.length,inet, 8081);
  14. socket.send(packet);
  15. }
  16. //接收端
  17. @Test
  18. public void receiver()throws Exception{
  19. DatagramSocket socket = new DatagramSocket(8081);
  20. byte[] buffer = new byte[100];
  21. DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
  22. socket.receive(packet);
  23. System.out.println(new String(packet.getData(), 0, buffer.length));
  24. }
  25. }

URL类的理解与实例化

URL:统一资源定位符,他表示internet上某一资源的地址。
格式:协议,主机名,端口号,片段名,参数列表

  1. public static void main(String[] args) throws IOException {
  2. URL url = new URL("www.baidu.com");
  3. HttpURLConnection connection= (HttpURLConnection) url.openConnection();//获取连接
  4. connection.connect();//连接
  5. connection.getInputStream();//获取流
  6. }

十三,反射

1.概述

反射

  1. 反射机制允许程序在执行时借助于反射API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
  2. 反射相关的主要API
  3. java.lang.Class
  4. java.lang.reflect.

关于java.lang.Class类的理解:*

  1. 1.类的加载过程:程序在经过javac.exe命令后,会生成一个或多个字节码文件(.class结尾),接着我们
  2. 使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程称为类的加载。
  3. 加载到内存中的类,我们就称为运行时类,此运行的类,就作为Class的一个实例。
  4. 2.换句话说:Class的实例就对应着一个运行时类。

类的加载过程(了解)

  1. ①类的加载:将类的class文件读入内存,并为之创建一个java.lang.Class对象,此过程由类的加载器完成。
  2. ②类的链接:将类的二进制数据合并到JRE中,赋默认值。
  3. ③类的初始化:JVM负责对类进行初始化。将静态代码块和类中赋值操作的语句读取,给变量/常量赋值。

类的加载器ClassLoader的理解:(了解)

  1. 作用:把类加载进内存。

2.获取Class的实例的方式(重点)

  1. 加载到内存中的运行时类,会缓存一定的时间,在此时间内,我们可以通过不同的方式来获取此运行时的类。
  2. Class实例对应的结构说明:
  3. claass,②interface,③数组④枚举类⑤注解⑥基本数据类型⑦void
  1. /**
  2. * @author yinhuidong
  3. * @createTime 2020-04-11-9:57
  4. * 获取Class实例的四种方式
  5. */
  6. public class Test1 {
  7. //通过对象.getClass()的方式
  8. @Test
  9. public void test1() {
  10. Class<? extends Person> clazz = new Person().getClass();
  11. }
  12. //通过类.class
  13. @Test
  14. public void test2() {
  15. Class<Person> clazz = Person.class;
  16. }
  17. //通过Class的静态方法
  18. @Test
  19. public void test3() throws Exception {
  20. Class<?> clazz = Class.forName("com.atguigui.java1.Person");
  21. }
  22. //通过类加载器
  23. @Test
  24. public void test4() throws Exception{
  25. ClassLoader classLoader = Person.class.getClassLoader();
  26. classLoader.loadClass("com.atguigui.java1.Person");
  27. }
  28. }
  29. class Person {
  30. private String name;
  31. private Integer age;
  32. public Person() {
  33. }
  34. public String getName() {
  35. return name;
  36. }
  37. public void setName(String name) {
  38. this.name = name;
  39. }
  40. public Integer getAge() {
  41. return age;
  42. }
  43. public void setAge(Integer age) {
  44. this.age = age;
  45. }
  46. @Override
  47. public String toString() {
  48. return "Person{" +
  49. "name='" + name + '\'' +
  50. ", age=" + age +
  51. '}';
  52. }
  53. }

3.使用ClassLoader加载配置文件

  1. @Test
  2. public void test4() throws Exception {
  3. Properties prop=new Properties();
  4. //读取配置文件的方式一:
  5. //此时配置文件默认在当前module下
  6. // FileInputStream fis = new FileInputStream("jdbc.properties");
  7. // prop.load(fis);
  8. //读取配置文件的方式二:使用ClassLoader
  9. //配置文件默认识别为:当前module的src下
  10. ClassLoader classLoader=Test1.class.getClassLoader();
  11. InputStream is = classLoader.getResourceAsStream("driud.properties");
  12. prop.load(is);
  13. String user=prop.getProperty("user");
  14. String password=prop.getProperty("password");
  15. System.out.println(user+" "+password);
  16. }

4.创建运行时类对象与反射的动态性

通过反射,创建运行时类对象

  1. newInstance()调用此方法,创建对应的运行时类的对象,内部调用了运行时类的空参构造器。
  2. 要想此方法正常运行:
  3. ①运行时类必须提供空参的构造器
  4. ②空参构造器访问权限得够。
  5. JavaBean中要求提供一个空参构造器的原因:
  6. ①便于通过反射,创建运行时类的对象。
  7. ②便于子类继承此运行类时,默认调用super方法时,保证父类有此构造器。
  1. @Test
  2. public void test5() throws IllegalAccessException, InstantiationException {
  3. Class<Person>clazz=Person.class;
  4. Person obj=clazz.newInstance();
  5. System.out.println(obj);
  6. }

反射的动态性举例

  1. @Test
  2. public void test6() throws Exception {
  3. Object instance = getInstance("java.util.Date");
  4. System.out.println(instance);
  5. }
  6. //创建一个指定类的对象。classPath:指定类的全类名。
  7. public Object getInstance(String classPath)throws Exception{
  8. Class clazz=Class.forName(classPath);
  9. return clazz.newInstance();
  10. }

5.调用运行时类的指定结构

属性,

  1. @Test
  2. public void test() throws Exception {
  3. Class clazz=Person.class;
  4. //创建运行时类的对象
  5. Object o = clazz.newInstance();
  6. //获取指定的属性:public
  7. Field name = clazz.getField("name");
  8. name.set(o,"yinhuidong");
  9. String o1 = (String) name.get(o);
  10. System.out.println(o1);
  11. }
  12. @Test//掌握
  13. public void test2() throws Exception {
  14. Class clazz=Person.class;
  15. //创建运行时类的对象
  16. Object o = clazz.newInstance();
  17. //获取指定的属性:无关权限修饰符,不包含父类
  18. Field age = clazz.getDeclaredField("age");
  19. age.setAccessible(true);//给与修改权限
  20. age.set(o,20);
  21. Object obj = age.get(o);
  22. System.out.println(obj);
  23. }

方法,

  1. @Test//掌握
  2. public void test3()throws Exception{
  3. //如何操作运行时类中的指定非静态方法
  4. Class<Person> clazz = Person.class;
  5. Person person = clazz.newInstance();
  6. Method show = clazz.getDeclaredMethod("show");
  7. show.setAccessible(true);
  8. Object obj = show.invoke(person);
  9. Method add = clazz.getDeclaredMethod("add", int.class, int.class);
  10. add.setAccessible(true);
  11. Integer invoke = (Integer) add.invoke(person, 1, 1);
  12. System.out.println(invoke);
  13. }
  14. @Test
  15. public void test4() throws Exception{
  16. //如何操作运行时类中的指定静态方法
  17. Class clazz=Person.class;
  18. Method eat = clazz.getDeclaredMethod("eat");
  19. eat.setAccessible(true);
  20. eat.invoke(Person.class);
  21. }

构造器

  1. @Test//不是很常用,了解
  2. public void test5() throws Exception{
  3. //调用运行时类中的指定构造器
  4. Class clazz=Person.class;
  5. Constructor constructor = clazz.getDeclaredConstructor(String.class, Integer.class);
  6. constructor.setAccessible(true);
  7. Object obj = constructor.newInstance("Tom",22);
  8. System.out.println(obj);
  9. }

6.代理

代理设计模式的原理:使用一个代理将对象包装起来,然后用该代理对象取代原始对象。
任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。

静态代理举例

特点:编译期间,代理类和被代理类就被确定下来了。

  1. interface ClothFactory{
  2. void produceCloth();
  3. }
  4. //代理类
  5. class ProxyClothFactory implements ClothFactory{
  6. private ClothFactory factory;//就拿被代理对象进行实例化
  7. public ProxyClothFactory(ClothFactory factory) {
  8. this.factory = factory;
  9. }
  10. @Override
  11. public void produceCloth() {
  12. System.out.println("代理工厂进行准备工作");
  13. factory.produceCloth();
  14. System.out.println("代理工厂做后续工作!");
  15. }
  16. }
  17. //被代理类
  18. class Nike implements ClothFactory{
  19. @Override
  20. public void produceCloth() {
  21. System.out.println("耐克工厂生产一批运动服!");
  22. }
  23. }
  1. @Test
  2. public void test(){
  3. Nike nike=new Nike();
  4. ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nike);
  5. proxyClothFactory.produceCloth();
  6. }

动态代理示例

动态代理:可以通过一个代理类完成全部的代理功能。
要求:理解过程。

  1. /**
  2. * @author yinhuidong
  3. * @createTime 2020-04-11-11:17
  4. * 基于接口的动态代理
  5. */
  6. public class Test1 {
  7. private PersonDao dao=new PersonDaoImpl();
  8. @Test
  9. public void test(){
  10. //动态代理
  11. PersonDao personDao = (PersonDao) Proxy.newProxyInstance(
  12. //被代理类的类加载器
  13. dao.getClass().getClassLoader(),
  14. //被代理类实现的接口
  15. dao.getClass().getInterfaces(),
  16. //InvocationHandler接口的实现类
  17. new InvocationHandler() {
  18. @Override
  19. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  20. Object o=null;
  21. if (!method.getName().equals("show")){
  22. Integer a= (Integer) args[0];
  23. Integer b= (Integer) args[1];
  24. //对方法进行增强
  25. o=method.invoke(dao,a*2,b*2);
  26. return o;
  27. }
  28. o=method.invoke(dao);
  29. return o;
  30. }
  31. }
  32. );
  33. System.out.println(personDao.add(1, 1));
  34. personDao.del(2,1);
  35. personDao.show();
  36. }
  37. }
  38. //被代理类实现的接口
  39. interface PersonDao{
  40. int add(int a,int b);
  41. void del(int a,int b);
  42. void show();
  43. }
  44. //被代理类
  45. class PersonDaoImpl implements PersonDao{
  46. @Override
  47. public int add(int a, int b) {
  48. return a+b;
  49. }
  50. @Override
  51. public void del(int a, int b) {
  52. System.out.println(a-b);
  53. }
  54. @Override
  55. public void show() {
  56. System.out.println("show()....");
  57. }
  58. }

7.总结

  1. import java.util.Properties;
  2. /**
  3. * @author yinhuidong
  4. * @createTime 2020-02-25-23:36
  5. */
  6. public class Test3 {
  7. /**
  8. * 第二轮复习
  9. * 获取运行时类的Class实例
  10. */
  11. @Test
  12. public void test1() throws ClassNotFoundException {
  13. //方式一:
  14. Class<Person> clazz = Person.class;
  15. System.out.println(clazz);
  16. //方式二:
  17. Person person = new Person();
  18. Class<? extends Person> clazz1 = person.getClass();
  19. System.out.println(clazz1);
  20. //方式:
  21. Class<?> clazz2 = Class.forName("com.atguigu.java3.Person");
  22. System.out.println(clazz2);
  23. //方式四:
  24. ClassLoader loader = Test3.class.getClassLoader();
  25. Class<?> clazz3 = loader.loadClass("com.atguigu.java3.Person");
  26. System.out.println(clazz3);
  27. }
  28. /**
  29. * 使用ClassLoader加载配置文件
  30. */
  31. @Test
  32. public void test2() throws IOException {
  33. InputStream is = Test3.class.getClassLoader().getResourceAsStream("xxx.properties");
  34. Properties prop = new Properties();
  35. prop.load(is);
  36. }
  37. /**
  38. * 通过反射,创建运行时类的对象
  39. */
  40. @Test
  41. public void test3() throws IllegalAccessException, InstantiationException {
  42. Class<Person> clazz = Person.class;
  43. Person person = clazz.newInstance();
  44. System.out.println(person.toString());
  45. }
  46. /**
  47. * 反射的动态性举例
  48. */
  49. @Test
  50. public void test4() {
  51. try {
  52. Object p = GetInstance("com.atguigu.java3.Person");
  53. System.out.println(p.toString());
  54. } catch (ClassNotFoundException e) {
  55. e.printStackTrace();
  56. }
  57. }
  58. public Object GetInstance(String path) throws ClassNotFoundException {
  59. Class<?> clazz = Class.forName(path);
  60. return clazz;
  61. }
  62. /**
  63. * 调用运行时类的指定结构
  64. * 1.属性
  65. */
  66. @Test//只能获取公的属性
  67. public void test5() throws IllegalAccessException, InstantiationException, NoSuchFieldException {
  68. Class<Person> clazz = Person.class;
  69. Person p = clazz.newInstance();
  70. Field name = clazz.getField("name");
  71. name.set(p,"张");
  72. System.out.println(name.get(p));
  73. }
  74. @Test//可以获取私的属性
  75. public void test6() throws IllegalAccessException, InstantiationException, NoSuchFieldException {
  76. Class<Person> clazz = Person.class;
  77. Person p = clazz.newInstance();
  78. //可以获取所属性
  79. Field name = clazz.getDeclaredField("name");
  80. name.setAccessible(true);
  81. name.set(p,"张");
  82. System.out.println(name.getName());
  83. Field age = clazz.getDeclaredField("age");
  84. age.setAccessible(true);
  85. age.set(p,12);
  86. System.out.println(age.get(p));
  87. System.out.println(p.toString());
  88. }
  89. @Test//调用非静态方法
  90. public void test7() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
  91. Class<Person> clazz = Person.class;
  92. Person p = clazz.newInstance();
  93. Method show = clazz.getDeclaredMethod("show", String.class);//方法名和形参类型
  94. show.setAccessible(true);
  95. Object args = show.invoke(p, "args");//对象,实参
  96. System.out.println(args);//方法的返回值
  97. }
  98. @Test//调用静态方法
  99. public void test8() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
  100. Class<Person> clazz = Person.class;
  101. Person p = clazz.newInstance();
  102. Method eat = clazz.getDeclaredMethod("eat", String.class);
  103. eat.setAccessible(true);
  104. Object o = eat.invoke(Person.class, "可比克");
  105. System.out.println(o);
  106. }
  107. }
  108. class Person {
  109. private String name;
  110. private int age;
  111. public Person() {
  112. }
  113. private int show(String args){
  114. System.out.println(args);
  115. return 1;
  116. }
  117. private static void eat(String food){
  118. System.out.println("正在吃。。。"+food);
  119. }
  120. public Person(String name, int age) {
  121. this.name = name;
  122. this.age = age;
  123. }
  124. public String getName() {
  125. return name;
  126. }
  127. public void setName(String name) {
  128. this.name = name;
  129. }
  130. public int getAge() {
  131. return age;
  132. }
  133. public void setAge(int age) {
  134. this.age = age;
  135. }
  136. @Override
  137. public String toString() {
  138. return "Person{" +
  139. "name='" + name + '\'' +
  140. ", age=" + age +
  141. '}';
  142. }
  143. }

十四,jdk8新特性

1.Lambda表达式

  1. Lambda表达式的使用
  2. 1.举例:Comparator<Integer> c= Comparator.comparingInt(o -> o);
  3. 2.格式:->:Lambda操作符
  4. 左边叫做形参列表,其实就是接口中的抽象方法的形参列表
  5. 右边叫做Lambda体(重写的抽象方法的方法体)
  6. 3.关于Lambda表达式的使用
  7. 总结:
  8. -> 左边:lambda形参列表的参数类型可以省略(类型推断),如果形参列表只有一个参数,()可以省略。
  9. -> 右边:Lambda体应该使用一对{}包裹,如果Lambda体只有一条执行语句(可能是return语句),{}和return也可以省略。
  10. 要求接口只有一个抽象方法。
  11. 4.Lambda表达式的本质:作为函数式接口的实例。
  12. 5.如果一个接口中只声明了一个抽象方法,则此接口称为函数式接口。
  13. 可以使用注解@FunctionalInterface检查是否是一个函数式接口。
  14. 用匿名实现类表示的现在都可以用Lambda表达式表示。
  1. public class LambdaTest1 {
  2. //语法格式一:无参数,无返回值
  3. @Test
  4. public void test() {
  5. Runnable r = () -> System.out.println("语法格式一:无参数,无返回值");
  6. r.run();
  7. }
  8. //语法格式二:一个参数,无返回值
  9. @Test
  10. public void test2() {
  11. Consumer<String> c = (String s) -> {
  12. System.out.println(s);
  13. };
  14. c.accept("语法格式二:一个参数,无返回值");
  15. }
  16. //语法格式:类型推断
  17. @Test
  18. public void test3() {
  19. Consumer<String> c = (s) -> {
  20. System.out.println(s);
  21. };
  22. c.accept("语法格式:类型推断");
  23. }
  24. //语法格式四:只一个参数时,省略小括号
  25. @Test
  26. public void test4() {
  27. Consumer<String> c = s -> {
  28. System.out.println(s);
  29. };
  30. c.accept("语法格式四:只一个参数时,省略小括号");
  31. }
  32. //语法格式五:Lambda 需要两个以上参数,多条执行语句,并且有返回值。
  33. @Test
  34. public void test5() {
  35. Comparator<Integer> c = (o1, o2) -> {
  36. System.out.println("语法格式五:Lambda 需要两个以上参数,多条执行语句,并且有返回值。");
  37. return o1.compareTo(o2);
  38. };
  39. int compare = c.compare(32, 21);
  40. System.out.println(compare);
  41. }
  42. //语法格式六:当Lambda体只一条语句时,reurn与大括号若,都可以省略。
  43. @Test
  44. public void test6() {
  45. Comparator<Integer> c = (o1, o2) -> o1.compareTo(o2);
  46. int compare = c.compare(32, 21);
  47. System.out.println(compare);
  48. }
  49. }
  1. Java内置四大核心函数式接口(要求能看懂)
  2. 消费性接口 Consumer<T> void accept(T t)
  3. 供给型接口 Supplier<T> T get()
  4. 函数型接口 Function<T,R> R apply(T t)
  5. 断定型接口 Predicate<T> boolean test(T t)
  6. test()
  7. 使用情景:当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用。
  8. 方法引用:本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例,
  9. 所以方法引用,也是函数式接口的实例。
  10. 使用格式: 类(对象)::方法名
  11. 具体分为如下三种情况:
  12. 对象::非静态方法
  13. 类::静态方法
  14. 类::非静态方法
  15. 方法引用的使用要求,要求接口中的抽象方法的形参列表和返回值类型与方法引用
  16. 的方法的形参列表和返回值类型相同!

2.Stream API

  1. 1.Stream关注的是数据的运算,与CPU打交道。
  2. 集合关注的是是数据的存储,与内存打交道。
  3. 2.
  4. Stream自己不会存储元素。
  5. Stream不会改变源对象,相反,他们会返回一个持有结果的新Stream
  6. Stream操作是延迟执行的,这意味着它们会等到需要结果的时候才执行。
  7. 3.Stream的执行流程
  8. Stream的实例化
  9. ②一系列的中间操作(过滤,映射,。。。)
  10. ③终止操作
  11. 4.说明:
  12. ①一个中间链操作,对数据源的数据进行处理。
  13. ②一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用。

Stream的实例化:

  1. //创建Stream的方式一:通过集合创建
  2. @Test
  3. public void test() {
  4. List<Employee> employees = EmployeeData.getEmployees();
  5. //返回一个顺序流
  6. Stream<Employee> stream = employees.stream();
  7. //返回一个并行流
  8. Stream<Employee> employeeStream = employees.parallelStream();
  9. }
  10. //创建Stream的方式二:通过数组
  11. @Test
  12. public void test2() {
  13. int[] arr = new int[]{1, 2, 3, 4, 5, 6};
  14. IntStream stream = Arrays.stream(arr);
  15. }
  16. //创建方式:通过Stream的of()
  17. @Test
  18. public void test3() {
  19. Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
  20. }
  21. //创建Stream的方式四,无限流
  22. @Test
  23. public void test4() {
  24. //迭代
  25. Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
  26. //生成
  27. Stream.generate(Math::random).limit(10).forEach(System.out::println);
  28. }

Stream的中间操作:

1.筛选与切片

  1. @Test//filter()过滤出需要的元素
  2. public void test(){
  3. List<Employee> employees = EmployeeData.getEmployees();
  4. Stream<Employee> stream = employees.stream();
  5. stream.filter(e->e.getAge()>25).forEach(System.out::println);
  6. }
  7. @Test//limit()截断取前面
  8. public void test2(){
  9. List<Employee> employees = EmployeeData.getEmployees();
  10. Stream<Employee> stream = employees.stream();
  11. stream.limit(5).forEach(System.out::println);
  12. }
  13. @Test//skip()截断取后面
  14. public void test3(){
  15. List<Employee> employees = EmployeeData.getEmployees();
  16. Stream<Employee> stream = employees.stream();
  17. stream.skip(5).forEach(System.out::println);
  18. }
  19. @Test//
  20. public void test4(){//distinct()去除重复元素
  21. List<Employee> employees = EmployeeData.getEmployees();
  22. Stream<Employee> stream = employees.stream();
  23. stream.distinct().forEach(System.out::println);
  24. }

2.映射

  1. @Test//map(str -> str + str)
  2. public void test() {
  3. int a[] = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
  4. IntStream stream = Arrays.stream(a);
  5. stream.map(str -> str + str).forEach(System.out::println);
  6. }
  7. @Test////map(Employee::getAge)
  8. public void test2() {
  9. List<Employee> employees = EmployeeData.getEmployees();
  10. Stream<Employee> stream = employees.stream();
  11. stream.map(Employee::getAge).filter(age -> age > 25).forEach(System.out::println);
  12. }

3.排序

  1. @Test//自然排序
  2. public void test() {
  3. int a[] = new int[]{1, 2, 3, 5, 9, 7, 6, 45, 65};
  4. IntStream stream = Arrays.stream(a);
  5. stream.sorted().forEach(System.out::print);
  6. }
  7. @Test//定制排序
  8. public void test2() {
  9. List<Employee> employees = EmployeeData.getEmployees();
  10. Stream<Employee> stream = employees.stream();
  11. stream.sorted((o1, o2) -> {
  12. return -o1.getAge().compareTo(o2.getAge());
  13. }).forEach(System.out::println);
  14. }
  15. @Test//定制排序
  16. public void test3() {
  17. List<Employee> employees = EmployeeData.getEmployees();
  18. Stream<Employee> stream = employees.stream();
  19. stream.sorted((o1, o2) -> {
  20. if (o1.getAge() != o2.getAge()) {
  21. return o1.getAge().compareTo(o2.getAge());
  22. } else {
  23. return o1.getId().compareTo(o2.getId());
  24. }
  25. }).forEach(System.out::println);
  26. }

Stream的终止操作

1.匹配与查找

  1. @Test
  2. public void test(){
  3. List<Employee> employees = EmployeeData.getEmployees();
  4. Stream<Employee> stream = employees.stream();
  5. boolean b = stream.allMatch(e -> e.getAge() > 23);
  6. System.out.println(b);
  7. }
  8. @Test
  9. public void test2(){
  10. List<Employee> employees = EmployeeData.getEmployees();
  11. Stream<Employee> stream = employees.stream();
  12. boolean b = stream.anyMatch(e -> e.getAge() > 23);
  13. System.out.println(b);
  14. }
  15. @Test
  16. public void test3(){
  17. List<Employee> employees = EmployeeData.getEmployees();
  18. Stream<Employee> stream = employees.stream();
  19. boolean b = stream.noneMatch(e -> e.getName().contains("java"));
  20. System.out.println(b);
  21. }
  22. @Test
  23. public void test4(){
  24. List<Employee> employees = EmployeeData.getEmployees();
  25. Stream<Employee> stream = employees.stream();
  26. Optional<Employee> first = stream.findFirst();
  27. System.out.println(first);
  28. }
  29. @Test
  30. public void test5(){
  31. List<Employee> employees = EmployeeData.getEmployees();
  32. Stream<Employee> stream = employees.stream();
  33. Optional<Employee> any = stream.findAny();
  34. System.out.println(any);
  35. }
  36. @Test
  37. public void test6(){
  38. List<Employee> employees = EmployeeData.getEmployees();
  39. Stream<Employee> stream = employees.stream();
  40. long count = stream.count();
  41. System.out.println(count);
  42. }
  43. @Test
  44. public void test7(){
  45. List<Employee> employees = EmployeeData.getEmployees();
  46. Stream<Employee> stream = employees.stream();
  47. Optional<Employee> max = stream.max((e1, e2) -> e1.getAge().compareTo(e2.getAge()));
  48. System.out.println(max);
  49. }
  50. @Test
  51. public void test8(){
  52. List<Employee> employees = EmployeeData.getEmployees();
  53. Stream<Employee> stream = employees.stream();
  54. Optional<Employee> min = stream.max((e1, e2) -> -(e1.getAge().compareTo(e2.getAge())));
  55. System.out.println(min);
  56. }

2.归约

  1. @Test
  2. public void test(){
  3. List<Employee> employees = EmployeeData.getEmployees();
  4. Stream<Employee> stream = employees.stream();
  5. Optional<Integer> reduce = stream.map(e -> e.getAge()).reduce((d1, d2) -> d1 + d2);
  6. System.out.println(reduce);
  7. }
  8. @Test
  9. public void test2(){
  10. Integer a[]=new Integer []{1,2,3,4,5,6,7,8,9};
  11. Stream<Integer> stream = Arrays.stream(a);
  12. Integer reduce = stream.reduce(0, Integer::sum);
  13. System.out.println(reduce);
  14. }

3.收集

  1. @Test
  2. public void test(){
  3. List<Employee> employees = EmployeeData.getEmployees();
  4. Stream<Employee> stream = employees.stream();
  5. List<Employee> collect = stream.collect(Collectors.toList());
  6. for (Employee employee : collect) {
  7. System.out.print(employee+" ");
  8. }
  9. }

3.Optional类

  1. Optional类:为了在程序中避免出现空指针异常而创建的。
  2. 常用的方法:ofNullable(T t)//允许存null
  3. ofElse(T t)//如果是null,使用形参中的对象。
  4. get()://如果调用对象包含值,返回调用对象,否则抛出异常。
  1. public class OptionalTest {
  2. @Test
  3. public void test() {
  4. Person p=new Person();
  5. String boyName = getBoyName(p);
  6. System.out.println(boyName);//java.lang.NullPointerException原因:男孩为null
  7. }
  8. @Test
  9. public void test2(){
  10. Person p=null;
  11. String boyName = getBoyName(p);
  12. System.out.println(boyName);//java.lang.NullPointerException原因:Person为null
  13. }
  14. @Test
  15. public void test3(){
  16. Person p=null;
  17. System.out.println(getName(p));
  18. }
  19. public String getBoyName(Person person){
  20. return person.getBoy().getName();
  21. }
  22. public String getName(Person person){
  23. Optional<Person> person1 = Optional.ofNullable(person);
  24. Person person2 = person1.orElse(new Person());
  25. Optional<Boy> boy = Optional.ofNullable(person2.getBoy());
  26. Boy boy1 = boy.orElse(new Boy("Tom"));
  27. return boy1.getName();
  28. }
  29. }
  30. class Person {
  31. private Boy boy;
  32. public Person() {
  33. }
  34. public Person(Boy boy) {
  35. this.boy = boy;
  36. }
  37. public Boy getBoy() {
  38. return boy;
  39. }
  40. public void setBoy(Boy boy) {
  41. this.boy = boy;
  42. }
  43. }
  44. class Boy {
  45. private String name;
  46. public Boy() {
  47. }
  48. public Boy(String name) {
  49. this.name = name;
  50. }
  51. public String getName() {
  52. return name;
  53. }
  54. public void setName(String name) {
  55. this.name = name;
  56. }
  57. }

十五,JDBC核心技术

1.概述

软件架构方式:
B/S:浏览器
C/S:客户端

数据的持久化

  1. 把数据保存到可掉电式存储设备中以供之后使用

JDBC的理解:

  1. JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API
  2. 简单理解为:JDBC,是SUN提供的一套 API,使用这套API可以实现对具体数据库的操作(获取连接、关闭连接、DMLDDLDCL)

图示理解:

JAVA-SE核心高级篇 - 图1

2.获取连接

驱动和url

  1. Driver driver=new com.mysql.jdbc.Driver();//MySQL具体driver的实现类
  2. String url="jdbc:mysql://localhost:3306/test";
  3. jdbc:mysql :协议
  4. localhost :ip地址
  5. 3306 :端口号
  6. test:数据库

方式一

  1. @Test
  2. public void test() throws SQLException {
  3. Driver driver = new com.mysql.jdbc.Driver();
  4. String url = "jdbc:mysql://localhost:3306/test";
  5. Properties prop = new Properties();
  6. prop.setProperty("user", "root");
  7. prop.setProperty("password", "yhd666");
  8. Connection connect = driver.connect(url, prop);
  9. }

上述代码中显式出现了第三方数据库的API

方拾二

  1. @Test//方式二:对方式一的迭代,不出现第方api,使程序具更好的可移植性
  2. public void test2() throws Exception {
  3. //1.利用反射获取Driver的具体实现类对象
  4. Class clazz = Class.forName("com.mysql.jdbc.Driver");
  5. Driver driver = (Driver) clazz.newInstance();
  6. //2.提供要链接的数据库
  7. String url = "jdbc:mysql://localhost:3306/test";
  8. Properties prop = new Properties();//将用户名和密码封装在prop中。
  9. prop.setProperty("user", "root");
  10. prop.setProperty("password", "yhd666");
  11. //3..获取连接
  12. Connection connect = driver.connect(url, prop);
  13. System.out.println(connect);
  14. }

方式三

  1. @Test //方式:使用DriverManager替换driver
  2. public void test3() throws Exception {
  3. //注册驱动
  4. DriverManager.registerDriver((Driver) Class.forName("com.mysql.jdbc.Driver").newInstance());
  5. //获取连接
  6. Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "yhd666");
  7. System.out.println(connection);
  8. }

使用DriverManager实现数据库的连接。体会获取连接必要的4个基本要素。

方式四

  1. @Test
  2. public void testConnection4() throws Exception {
  3. //1.数据库连接的4个基本要素:
  4. String url = "jdbc:mysql://localhost:3306/test";
  5. String user = "root";
  6. String password = "yhd666";
  7. String driverName = "com.mysql.jdbc.Driver";
  8. //2.加载驱动 (①实例化Driver ②注册驱动
  9. Class.forName(driverName);
  10. //Driver driver = (Driver) clazz.newInstance();
  11. //3.注册驱动
  12. //DriverManager.registerDriver(driver);
  13. /*
  14. 可以注释掉上述代码的原因,是因为在mysql的Driver类中声明:
  15. static {
  16. try {
  17. DriverManager.registerDriver(new Driver());
  18. } catch (SQLException var1) {
  19. throw new RuntimeException("Can't register driver!");
  20. }
  21. }
  22. */
  23. //3.获取连接
  24. Connection conn = DriverManager.getConnection(url, user, password);
  25. System.out.println(conn);
  26. }

方式五

  1. @Test//最终版,配置文件版
  2. //1.实现了数据与代码的分离,解耦
  3. //2.如果需要修改配置文件信息,就可以避免程序重新打包
  4. public void test5() throws Exception {
  5. InputStream is = Test1.class.getClassLoader().getResourceAsStream("jdbc.properties");
  6. Properties prop = new Properties();
  7. prop.load(is);
  8. String user = prop.getProperty("user");
  9. String password = prop.getProperty("password");
  10. String url = prop.getProperty("url");
  11. String driverClass = prop.getProperty("driverClass");
  12. Class.forName(driverClass);
  13. Connection connection = DriverManager.getConnection(url, user, password);
  14. System.out.println(connection);
  15. }

其中,配置文件声明在工程的src目录下:【jdbc.properties】

  1. ```properties
  2. user=root
  3. password=yhd666
  4. url=jdbc:mysql://localhost:3306/test
  5. driverClass=com.mysql.jdbc.Driver

3.PreparedStatement

Statement

  1. 数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。
  2. - java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:
  3. - Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。
  4. - PrepatedStatementSQL 语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。
  5. - CallableStatement:用于执行 SQL 存储过程
  6. 使用Statement操作数据表的弊端
  7. - 通过调用 Connection 对象的 createStatement() 方法创建该对象。该对象用于执行静态的 SQL 语句,并且返回执行结果。
  8. - Statement 接口中定义了下列方法用于执行 SQL 语句:
  9. ```sql
  10. int excuteUpdate(String sql):执行更新操作INSERTUPDATEDELETE
  11. 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封装获取连接和关闭资源

  1. /**
  2. * @author yinhuidong
  3. * @createTime 2020-02-04-19:26
  4. * JDBC工具类
  5. */
  6. public class JDBCUtils {
  7. //获取连接
  8. public static Connection getConnection()throws Exception{
  9. InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
  10. Properties prop = new Properties();
  11. prop.load(is);
  12. String driverClass=prop.getProperty("driverClass");
  13. String url=prop.getProperty("url");
  14. String user = prop.getProperty("user");
  15. String password = prop.getProperty("password");
  16. Class.forName(driverClass);
  17. Connection connection = DriverManager.getConnection(url, user, password);
  18. return connection;
  19. }
  20. //关闭资源
  21. public static void closeResource(Connection co, PreparedStatement ps, ResultSet rs){
  22. try {
  23. if (co!=null){
  24. co.close();
  25. }
  26. if (ps!=null){
  27. ps.close();
  28. }
  29. if (rs!=null){
  30. rs.close();
  31. }
  32. } catch (SQLException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. }

增删改操作

添加操作

  1. @Test//添加操作
  2. public void add(){
  3. Connection co=null;
  4. PreparedStatement ps=null;
  5. try {
  6. co=JDBCUtils.getConnection();
  7. String sql="insert into customers(name,email,birth) values(?,?,?);";
  8. ps = co.prepareStatement(sql);
  9. ps.setObject(1,"yinhuidong");
  10. ps.setObject(2,"1972039773@qq.com");
  11. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
  12. java.util.Date date = format.parse("1998-11-16");
  13. ps.setObject(3,new Date(date.getTime()));
  14. ps.execute();
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. } finally {
  18. JDBCUtils.closeResource(co,ps,null);
  19. }
  20. }

删除操作

  1. @Test//删除操作
  2. public void delete(){
  3. Connection co=null;
  4. PreparedStatement ps=null;
  5. try {
  6. co=JDBCUtils.getConnection();
  7. String sql="delete from customers where id = ?;";
  8. ps=co.prepareStatement(sql);
  9. ps.setObject(1,20);
  10. ps.execute();
  11. } catch (Exception e) {
  12. e.printStackTrace();
  13. } finally {
  14. JDBCUtils.closeResource(co,ps,null);
  15. }
  16. }

修改操作:

  1. @Test//修改
  2. public void update(){
  3. Connection co=null;
  4. PreparedStatement ps=null;
  5. try {
  6. co=JDBCUtils.getConnection();
  7. String sql="update customers set name=? where id =?;";
  8. ps=co.prepareStatement(sql);
  9. ps.setObject(1,"尹会东");
  10. ps.setObject(2,1);
  11. ps.execute();
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. } finally {
  15. JDBCUtils.closeResource(co,ps,null);
  16. }
  17. }

通用增删改:

  1. //通用增删改
  2. public static void update(String sql,Object...args){
  3. Connection conn=null;
  4. PreparedStatement ps=null;
  5. try {
  6. conn=getConnection();
  7. ps=conn.prepareStatement(sql);
  8. for (int i = 0; i <args.length ; i++) {
  9. ps.setObject(i+1,args[i]);
  10. }
  11. ps.execute();
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. } finally {
  15. closeResource(conn,ps,null);
  16. }
  17. }

通用查询操作

  1. public static <T>List<T> find1(Class<T>clazz,String sql,Object...args) {
  2. Connection co=null;
  3. PreparedStatement ps=null;
  4. ResultSet rs=null;
  5. try {
  6. co=getConnection();
  7. ps=co.prepareStatement(sql);
  8. for (int i = 0; i <args.length ; i++) {
  9. ps.setObject(i+1,args[i]);
  10. }
  11. rs=ps.executeQuery();
  12. ResultSetMetaData data = rs.getMetaData();//获取数据源
  13. int count = data.getColumnCount();//获取一共有多少列
  14. ArrayList<T> list = new ArrayList<>();
  15. while (rs.next()){
  16. T t = clazz.newInstance();
  17. for (int i = 0; i <count ; i++) {
  18. Object value=rs.getObject(i+1);
  19. String name = data.getColumnLabel(i + 1);//获取别名,如果没别名就获取列名
  20. Field field = clazz.getDeclaredField(name);
  21. field.setAccessible(true);
  22. field.set(t,value);
  23. }
  24. list.add(t);
  25. }
  26. return list;
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. } finally {
  30. closeResource(co,ps,rs);
  31. }
  32. return null;
  33. }

表的列名和对象的属性名不一致的解决办法

  1. JavaSQL对应数据类型转换表
  2. | Java类型 | SQL类型 |
  3. | ------------------ | ------------------------ |
  4. | boolean | BIT |
  5. | byte | TINYINT |
  6. | short | SMALLINT |
  7. | int | INTEGER |
  8. | long | BIGINT |
  9. | String | CHAR,VARCHAR,LONGVARCHAR |
  10. | byte array | BINARY , VAR BINARY |
  11. | java.sql.Date | DATE |
  12. | java.sql.Time | TIME |
  13. | java.sql.Timestamp | TIMESTAMP |
  14. 1. **如何获取 ResultSetMetaData**: 调用 ResultSet getMetaData() 方法即可
  15. 2. **获取 ResultSet 中有多少列**:调用 ResultSetMetaData getColumnCount() 方法
  16. 3. **获取 ResultSet 每一列的列的别名是什么**:调用 ResultSetMetaData getColumnLabel() 方法

JDBC API小结

  1. - 两种思想
  2. - 面向接口编程的思想
  3. - ORM思想(object relational mapping)
  4. - 一个数据表对应一个java
  5. - 表中的一条记录对应java类的一个对象
  6. - 表中的一个字段对应java类的一个属性
  7. > sql是需要结合列名和表的属性名来写。注意起别名。
  8. - 两种技术
  9. - JDBC结果集的元数据:ResultSetMetaData
  10. - 获取列数:getColumnCount()
  11. - 获取列的别名:getColumnLabel()
  12. - 通过反射,创建指定类的对象,获取指定的属性并赋值
  13. 面试题:statementpreparedStatement的区别

操作Blob类型的变量

  1. @Test//像数据表中插入一个图片
  2. public void test(){
  3. Connection co=null;
  4. PreparedStatement ps=null;
  5. try {
  6. co=JDBCUtils.getConnection();
  7. String sql="insert into customers(name,email,birth,photo)values(?,?,?,?);";
  8. ps=co.prepareStatement(sql);
  9. ps.setObject(1,"宋红康");
  10. ps.setObject(2,"shk@126.com");
  11. ps.setObject(3,"1988-11-13");
  12. FileInputStream fis = new FileInputStream("D:\\copy1.jpg");
  13. ps.setObject(4,fis);
  14. ps.execute();
  15. } catch (SQLException e) {
  16. e.printStackTrace();
  17. } catch (FileNotFoundException e) {
  18. e.printStackTrace();
  19. } finally {
  20. JDBCUtils.closeResource(co,ps,null);
  21. }
  22. }
  1. @Test//查询blob字段
  2. public void test2(){
  3. Connection co=null;
  4. PreparedStatement ps=null;
  5. ResultSet rs=null;
  6. InputStream bs=null;
  7. FileOutputStream fos=null;
  8. try {
  9. co=JDBCUtils.getConnection();
  10. String sql="select * from customers where id=?;";
  11. ps=co.prepareStatement(sql);
  12. ps.setObject(1,22);
  13. rs=ps.executeQuery();
  14. while (rs.next()) {
  15. Integer id = (Integer) rs.getObject(1);
  16. String name = (String) rs.getObject(2);
  17. String email = (String) rs.getObject(3);
  18. Date birth = (Date) rs.getObject(4);
  19. Customer customer = new Customer(id,name,email,birth);
  20. System.out.println(customer);
  21. Blob photo=rs.getBlob(5);
  22. bs = photo.getBinaryStream();
  23. fos = new FileOutputStream("2.jpg");
  24. byte[]bytes=new byte[1024];
  25. int len;
  26. while ((len=bs.read(bytes))!=-1) {
  27. fos.write(bytes,0,len);
  28. }
  29. }
  30. } catch (SQLException e) {
  31. e.printStackTrace();
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. } finally {
  35. JDBCUtils.closeResource(co,ps,rs);
  36. try {
  37. if (bs!=null){
  38. bs.close();
  39. }
  40. if (fos!=null){
  41. fos.close();
  42. }
  43. } catch (IOException e) {
  44. e.printStackTrace();
  45. }
  46. }
  47. }

插入中遇到的问题:

JAVA-SE核心高级篇 - 图2

批处理

  1. @Test//像数据库一张表插入两万条数据
  2. public void test() {
  3. Connection conn = null;
  4. PreparedStatement ps = null;
  5. try {
  6. conn = JDBCUtils.getConnection();
  7. String sql = "insert into goods(name)values(?)";
  8. ps = conn.prepareStatement(sql);
  9. for (int i = 1; i <= 20000; i++) {
  10. ps.setString(1, "name_" + i);
  11. ps.executeUpdate();
  12. }
  13. } catch (SQLException e) {
  14. e.printStackTrace();
  15. } finally {
  16. JDBCUtils.closeResource(conn, ps, null);
  17. }
  18. }
  1. @Test//插入优化
  2. public void test3(){
  3. Connection conn = null;
  4. PreparedStatement ps = null;
  5. try {
  6. conn = JDBCUtils.getConnection();
  7. //设置不允许自动提交数据
  8. conn.setAutoCommit(false);
  9. String sql = "insert into goods(name)values(?)";
  10. ps = conn.prepareStatement(sql);
  11. for (int i = 0; i <=20000 ; i++) {
  12. ps.setString(1, "name_" + i);
  13. ps.addBatch();
  14. if (i%500==0){
  15. ps.executeBatch();
  16. ps.clearBatch();
  17. }
  18. }
  19. conn.commit();
  20. } catch (SQLException e) {
  21. e.printStackTrace();
  22. } finally {
  23. JDBCUtils.closeResource(conn,ps,null);
  24. }
  25. }

4.事务

  1. 1.事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。
  2. * > 一组逻辑操作单元:一个或多个DML操作。
  3. > 2.事务处理的原则:
  4. > 保证所事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。
  5. > 当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存
  6. > 下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态。
  7. 说明:
  8. 1.数据一旦提交,就不可回滚
  9. * 2.哪些操作会导致数据的自动提交?
  10. * >DDL操作一旦执行,都会自动提交。
  11. * >set autocommit = false DDL操作失效
  12. * >DML默认情况下,一旦执行,就会自动提交。
  13. * >我们可以通过set autocommit = false的方式取消DML操作的自动提交。
  14. * >默认在关闭连接时,会自动的提交数据

考虑事务以后的转账问题

  1. @Test
  2. public void test() {
  3. Connection co = null;
  4. try {
  5. co = JDBCUtils.getConnection();
  6. co.setAutoCommit(false);
  7. String sql1 = "update user_table set balance=balance-? where user=?";
  8. String sql2 = "update user_table set balance=balance+? where user=?";
  9. update(co,sql1,100,"AA");
  10. //System.out.println(10/0);
  11. update(co,sql2,100,"BB");
  12. co.commit();
  13. System.out.println("转账成功!");
  14. } catch (SQLException e) {
  15. try {
  16. co.rollback();
  17. System.out.println("转账失败!");
  18. } catch (SQLException e1) {
  19. e1.printStackTrace();
  20. }
  21. } finally {
  22. JDBCUtils.closeResource(co,null,null);
  23. }
  24. }
  1. public static int update(Connection co, String sql, Object... args) {
  2. PreparedStatement ps = null;
  3. try {
  4. ps = co.prepareStatement(sql);
  5. for (int i = 0; i < args.length; i++) {
  6. ps.setObject(i + 1, args[i]);
  7. }
  8. return ps.executeUpdate();
  9. } catch (SQLException e) {
  10. e.printStackTrace();
  11. } finally {
  12. JDBCUtils.closeResource(null, ps, null);
  13. }
  14. return 0;
  15. }

事务的属性

ACID

JAVA-SE核心高级篇 - 图3

数据操作过程中可能出现的问题:(针对隔离性)

JAVA-SE核心高级篇 - 图4

数据库的四种隔离级别:(一致性和并发性:一致性越好,并发性越差)

JAVA-SE核心高级篇 - 图5

如何查看并设置隔离级别:

JAVA-SE核心高级篇 - 图6

5.连接池技术

传统连接存在的问题:

JAVA-SE核心高级篇 - 图7

使用数据库连接池大的好处

  1. 1.提高程序的响应速度(减少了创建连接相应的时间)
  2. 2.降低资源的消耗(可以重复使用已经提供好的连接)
  3. 3.便于连接的管理

c3p0连接池

  1. //使用c3p0数据库连接池的配置文件方式,获取数据库的连接:推荐
  2. private static DataSource cpds = new ComboPooledDataSource("helloc3p0");
  3. public static Connection getConnection() throws SQLException {
  4. Connection conn = cpds.getConnection();
  5. return conn;
  6. }

c3p0-config.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <c3p0-config>
  3. <named-config name="helloc3p0">
  4. <!-- 提供获取连接的4个基本信息 -->
  5. <property name="driverClass">com.mysql.jdbc.Driver</property>
  6. <property name="jdbcUrl">jdbc:mysql:///test</property>
  7. <property name="user">root</property>
  8. <property name="password">yhd666</property>
  9. <!-- 进行数据库连接池管理的基本信息 -->
  10. <!-- 当数据库连接池中的连接数不够时,c3p0一次性向数据库服务器申请的连接数 -->
  11. <property name="acquireIncrement">5</property>
  12. <!-- c3p0数据库连接池中初始化时的连接数 -->
  13. <property name="initialPoolSize">10</property>
  14. <!-- c3p0数据库连接池维护的最少连接数 -->
  15. <property name="minPoolSize">10</property>
  16. <!-- c3p0数据库连接池维护的最多的连接数 -->
  17. <property name="maxPoolSize">100</property>
  18. <!-- c3p0数据库连接池最多维护的Statement的个数 -->
  19. <property name="maxStatements">50</property>
  20. <!-- 每个连接中可以最多使用的Statement的个数 -->
  21. <property name="maxStatementsPerConnection">2</property>
  22. </named-config>
  23. </c3p0-config>

dbcp连接池

  1. //使用dbocp数据库连接池的配置文件方式,获取数据库的连接:推荐
  2. private static DataSource source = null;
  3. static{
  4. try {
  5. Properties pros = new Properties();
  6. InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("dbcp.properties");
  7. pros.load(is);
  8. //根据提供的BasicDataSourceFactory创建对应的DataSource对象
  9. source = BasicDataSourceFactory.createDataSource(pros);
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. }
  14. public static Connection getConnection2() throws SQLException {
  15. Connection conn = source.getConnection();
  16. return conn;
  17. }

dbcp.properties

  1. driverClassName=com.mysql.jdbc.Driver
  2. url=jdbc:mysql:///test
  3. username=root
  4. password=yhd666
  5. initialSize=10

druid连接池

  1. //使用druid数据库连接池的配置文件方式,获取数据库的连接:推荐
  2. private static DataSource ds = null;
  3. static {
  4. try {
  5. Properties pro = new Properties();
  6. // pro.load(PoolTest.class.getClassLoader().getResourceAsStream("druid.properties"));//加载配置文件
  7. pro.load(ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties"));
  8. ds = DruidDataSourceFactory.createDataSource(pro);//通过工厂创建数据源
  9. } catch (Exception e) {
  10. e.printStackTrace();
  11. }
  12. }
  13. public static Connection getConnection3() {
  14. return ds.getConnection();//通过数据源获取连接
  15. }

druid.properties

  1. url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
  2. username=root
  3. password=yhd666
  4. driverClassName=com.mysql.jdbc.Driver
  5. #初始化时的连接数
  6. initialSize=10
  7. #最大连接池数量
  8. maxActive=20
  9. #获取连接时最大等待时间,单位毫秒。
  10. maxWait=1000
  11. #防御sql注入的filter:wall
  12. filters=wall
  13. #mysql下建议关闭
  14. poolPreparedStatements=false
  15. #建议配置为true,不影响性能,并且保证安全性。
  16. testWhileIdle=true

6.DBUtils工具类

通用增删改

  1. 使用现成的jar中的QueryRunner测试增、删、改的操作:
  2. //测试插入
  3. @Test
  4. public void testInsert() {
  5. Connection conn = null;
  6. try {
  7. QueryRunner runner = new QueryRunner();
  8. conn = JDBCUtils.getConnection3();
  9. String sql = "insert into customers(name,email,birth)values(?,?,?)";
  10. int insertCount = runner.update(conn, sql, "蔡徐坤","caixukun@126.com","1997-09-08");
  11. System.out.println("添加了" + insertCount + "条记录");
  12. } catch (SQLException e) {
  13. e.printStackTrace();
  14. }finally{
  15. JDBCUtils.closeResource(conn, null);
  16. }
  17. }

查询操作1

  1. 使用现成的jar中的QueryRunner测试查询的操作:
  2. //测试查询
  3. /*
  4. * BeanHander:是ResultSetHandler接口的实现类,用于封装表中的一条记录。
  5. */
  6. @Test
  7. public void testQuery1(){
  8. Connection conn = null;
  9. try {
  10. QueryRunner runner = new QueryRunner();
  11. conn = JDBCUtils.getConnection3();
  12. String sql = "select id,name,email,birth from customers where id = ?";
  13. BeanHandler<Customer> handler = new BeanHandler<>(Customer.class);
  14. Customer customer = runner.query(conn, sql, handler, 23);
  15. System.out.println(customer);
  16. } catch (SQLException e) {
  17. // TODO Auto-generated catch block
  18. e.printStackTrace();
  19. }finally{
  20. JDBCUtils.closeResource(conn, null);
  21. }
  22. }

查询操作2

  1. /*
  2. * BeanListHandler:是ResultSetHandler接口的实现类,用于封装表中的多条记录构成的集合。
  3. */
  4. @Test
  5. public void testQuery2() {
  6. Connection conn = null;
  7. try {
  8. QueryRunner runner = new QueryRunner();
  9. conn = JDBCUtils.getConnection3();
  10. String sql = "select id,name,email,birth from customers where id < ?";
  11. BeanListHandler<Customer> handler = new BeanListHandler<>(Customer.class);
  12. List<Customer> list = runner.query(conn, sql, handler, 23);
  13. list.forEach(System.out::println);
  14. } catch (SQLException e) {
  15. e.printStackTrace();
  16. }finally{
  17. JDBCUtils.closeResource(conn, null);
  18. }
  19. }

查询操作3

  1. /*
  2. * MapHander:是ResultSetHandler接口的实现类,对应表中的一条记录。
  3. * 将字段及相应字段的值作为map中的key和value
  4. */
  5. @Test
  6. public void testQuery3(){
  7. Connection conn = null;
  8. try {
  9. QueryRunner runner = new QueryRunner();
  10. conn = JDBCUtils.getConnection3();
  11. String sql = "select id,name,email,birth from customers where id = ?";
  12. MapHandler handler = new MapHandler();
  13. Map<String, Object> map = runner.query(conn, sql, handler, 23);
  14. System.out.println(map);
  15. } catch (SQLException e) {
  16. e.printStackTrace();
  17. }finally{
  18. JDBCUtils.closeResource(conn, null);
  19. }
  20. }

查询操作4

  1. /*
  2. * MapListHander:是ResultSetHandler接口的实现类,对应表中的多条记录。
  3. * 将字段及相应字段的值作为map中的key和value。将这些map添加到List中
  4. */
  5. @Test
  6. public void testQuery4(){
  7. Connection conn = null;
  8. try {
  9. QueryRunner runner = new QueryRunner();
  10. conn = JDBCUtils.getConnection3();
  11. String sql = "select id,name,email,birth from customers where id < ?";
  12. MapListHandler handler = new MapListHandler();
  13. List<Map<String, Object>> list = runner.query(conn, sql, handler, 23);
  14. list.forEach(System.out::println);
  15. } catch (SQLException e) {
  16. e.printStackTrace();
  17. }finally{
  18. JDBCUtils.closeResource(conn, null);
  19. }
  20. }

查询操作5

  1. /*
  2. * ScalarHandler:用于查询特殊值
  3. */
  4. @Test
  5. public void testQuery5(){
  6. Connection conn = null;
  7. try {
  8. QueryRunner runner = new QueryRunner();
  9. conn = JDBCUtils.getConnection3();
  10. String sql = "select count(*) from customers";
  11. ScalarHandler handler = new ScalarHandler();
  12. Long count = (Long) runner.query(conn, sql, handler);
  13. System.out.println(count);
  14. } catch (SQLException e) {
  15. e.printStackTrace();
  16. }finally{
  17. JDBCUtils.closeResource(conn, null);
  18. }
  19. }
  20. @Test
  21. public void testQuery6(){
  22. Connection conn = null;
  23. try {
  24. QueryRunner runner = new QueryRunner();
  25. conn = JDBCUtils.getConnection3();
  26. String sql = "select max(birth) from customers";
  27. ScalarHandler handler = new ScalarHandler();
  28. Date maxBirth = (Date) runner.query(conn, sql, handler);
  29. System.out.println(maxBirth);
  30. } catch (SQLException e) {
  31. e.printStackTrace();
  32. }finally{
  33. JDBCUtils.closeResource(conn, null);
  34. }
  35. }

自定义ResultSetHandler的实现类

  1. /*
  2. * 自定义ResultSetHandler的实现类
  3. */
  4. @Test
  5. public void testQuery7(){
  6. Connection conn = null;
  7. try {
  8. QueryRunner runner = new QueryRunner();
  9. conn = JDBCUtils.getConnection3();
  10. String sql = "select id,name,email,birth from customers where id = ?";
  11. ResultSetHandler<Customer> handler = new ResultSetHandler<Customer>(){
  12. @Override
  13. public Customer handle(ResultSet rs) throws SQLException {
  14. // System.out.println("handle");
  15. // return null;
  16. // return new Customer(12, "成龙", "Jacky@126.com", new Date(234324234324L));
  17. if(rs.next()){
  18. int id = rs.getInt("id");
  19. String name = rs.getString("name");
  20. String email = rs.getString("email");
  21. Date birth = rs.getDate("birth");
  22. Customer customer = new Customer(id, name, email, birth);
  23. return customer;
  24. }
  25. return null;
  26. }
  27. };
  28. Customer customer = runner.query(conn, sql, handler,23);
  29. System.out.println(customer);
  30. } catch (SQLException e) {
  31. e.printStackTrace();
  32. }finally{
  33. JDBCUtils.closeResource(conn, null);
  34. }
  35. }

资源关闭

  1. 使用dbutils.jar包中的DbUtils工具类实现连接等资源的关闭:
  2. /**
  3. *
  4. * @Description 使用dbutils.jar中提供的DbUtils工具类,实现资源的关闭
  5. * @author shkstart
  6. * @date 下午4:53:09
  7. * @param conn
  8. * @param ps
  9. * @param rs
  10. */
  11. public static void closeResource1(Connection conn,Statement ps,ResultSet rs){
  12. DbUtils.closeQuietly(conn);
  13. DbUtils.closeQuietly(ps);
  14. DbUtils.closeQuietly(rs);
  15. }

7.DAO设计模式

BaseDao类

  1. package com.atguigu.utils;
  2. import org.apache.commons.dbutils.QueryRunner;
  3. import org.apache.commons.dbutils.handlers.*;
  4. import java.lang.reflect.ParameterizedType;
  5. import java.lang.reflect.Type;
  6. import java.sql.Connection;
  7. import java.sql.SQLException;
  8. import java.util.List;
  9. import java.util.Map;
  10. /**
  11. * @author yinhuidong
  12. * @createTime 2020-02-12-21:07
  13. */
  14. public class BaseDao<T> {
  15. private Class<T> type;// 定义一个变量来接收泛型的类型
  16. public BaseDao() {
  17. //当子类调用父类方法时获取当前子类的父类类型
  18. ParameterizedType parameterizedType = (ParameterizedType) this.getClass().getGenericSuperclass();
  19. //获取具体的泛型的类型
  20. Type[] types = parameterizedType.getActualTypeArguments();
  21. this.type = (Class<T>) types[0];
  22. }
  23. private QueryRunner runner = new QueryRunner();
  24. /**
  25. * 考虑到事务以后的通用增删改
  26. */
  27. public int update(Connection co, String sql, Object... args) throws SQLException {
  28. return runner.update(co, sql, args);
  29. }
  30. /**
  31. * 考虑到事务以后的通用查询一
  32. */
  33. public <T> T select1(Connection co, String sql, Object... args) throws SQLException {
  34. BeanHandler<T> handler = new BeanHandler<>((Class<T>) type);
  35. return runner.query(co, sql, handler, args);
  36. }
  37. /**
  38. * 考虑到事务以后的通用查询二
  39. */
  40. public <T> List<T> select2(Connection co, String sql, Object... args) throws SQLException {
  41. BeanListHandler<T> handler = new BeanListHandler<>((Class<T>) type);
  42. return runner.query(co, sql, handler, args);
  43. }
  44. /**
  45. * MapHandler
  46. */
  47. public Map<String, Object> select3(Connection co, String sql, Object... args) throws SQLException {
  48. MapHandler handler = new MapHandler();
  49. return runner.query(co, sql, handler, args);
  50. }
  51. /**
  52. * MapListHandler
  53. */
  54. public List<Map<String, Object>> select4(Connection co, String sql, Object... args) throws SQLException {
  55. MapListHandler handler = new MapListHandler();
  56. return runner.query(co, sql, handler, args);
  57. }
  58. /**
  59. * 利用ScalarHandler获取单一值
  60. * 考虑事务问题
  61. */
  62. public Object select5(Connection co, String sql, Object... args) throws SQLException {
  63. ScalarHandler handler = new ScalarHandler();
  64. return runner.query(co, sql, handler, args);
  65. }
  66. }

Dao接口

  1. /**
  2. * @author yinhuidong
  3. * @createTime 2020-02-06-14:49
  4. */
  5. public interface CustomerDao {
  6. int add(Connection co,Object...args) throws SQLException;
  7. int delete(Connection co,Object...args) throws SQLException;
  8. int updates(Connection co,Object...args) throws SQLException;
  9. Customer FindByValue(Connection co,Object...args) throws SQLException;
  10. List<Customer> FindMore(Connection co, Object...args) throws SQLException;
  11. Long count(Connection co,Object...args) throws SQLException;
  12. }

DaoImpl实现类

  1. /**
  2. * @author yinhuidong
  3. * @createTime 2020-02-06-14:56
  4. */
  5. public class CustomerDaoImpl extends BaseDao<Customer> implements CustomerDao {
  6. @Override
  7. public int add(Connection co, Object... args) throws SQLException {
  8. String sql="insert into customers (name,email,birth)values(?,?,?);";
  9. return update(co,sql,args);
  10. }
  11. @Override
  12. public int delete(Connection co, Object... args) throws SQLException {
  13. String sql="delete from customers where id=?;";
  14. return update(co,sql,args);
  15. }
  16. @Override
  17. public int updates(Connection co, Object... args) throws SQLException {
  18. String sql="update customers set name=?,email=?,birth=? where id=?;";
  19. return update(co,sql,args);
  20. }
  21. @Override
  22. public Customer FindByValue(Connection co, Object... args) throws SQLException {
  23. String sql="select id,name,email,birth from customers where id=?;";
  24. return selectById(co,sql,args);
  25. }
  26. @Override
  27. public List<Customer> FindMore(Connection co, Object... args) throws SQLException {
  28. String sql="select id,name,email,birth from customers ;";
  29. return selectMore(co,sql,args);
  30. }
  31. @Override
  32. public Long count(Connection co,Object...args) throws SQLException {
  33. String sql="select count(*) from customers ;";
  34. return (Long) selectOne(co,sql,args);
  35. }
  36. }

测试类

  1. /**
  2. * @author yinhuidong
  3. * @createTime 2020-02-06-15:10
  4. */
  5. public class TestDao {
  6. private CustomerDao dao=new CustomerDaoImpl();
  7. @Test
  8. public void test(){
  9. Connection co=null;
  10. try {
  11. co=JDBCUtils.getConnection();
  12. co.setAutoCommit(false);
  13. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
  14. Date date = format.parse("2017-02-21");
  15. int add = dao.add(co, "name", "email", new java.sql.Date(date.getTime()));
  16. co.commit();
  17. if (add>0){
  18. System.out.println("添加成功!");
  19. }else{
  20. System.out.println("添加失败!");
  21. }
  22. } catch (SQLException e) {
  23. try {
  24. co.rollback();
  25. } catch (SQLException e1) {
  26. e1.printStackTrace();
  27. }
  28. } catch (ParseException e) {
  29. e.printStackTrace();
  30. } finally {
  31. JDBCUtils.closeResource(co);
  32. }
  33. }
  34. @Test
  35. public void test2(){
  36. Connection co=null;
  37. try {
  38. co=JDBCUtils.getConnection();
  39. co.setAutoCommit(false);
  40. Customer customer = dao.FindByValue(co, 21);
  41. co.commit();
  42. System.out.println(customer);
  43. } catch (SQLException e) {
  44. e.printStackTrace();
  45. } finally {
  46. JDBCUtils.closeResource(co);
  47. }
  48. }
  49. }

JDBCUtils工具类

  1. package com.atguigu.java6;
  2. import com.alibaba.druid.pool.DruidDataSourceFactory;
  3. import com.alibaba.druid.util.JdbcUtils;
  4. import com.mchange.v2.c3p0.ComboPooledDataSource;
  5. import org.apache.commons.dbcp.BasicDataSourceFactory;
  6. import javax.sql.DataSource;
  7. import java.io.InputStream;
  8. import java.sql.Connection;
  9. import java.sql.SQLException;
  10. import java.util.Properties;
  11. /**
  12. * @author yinhuidong
  13. * @createTime 2020-02-27-21:52
  14. */
  15. public class JDBCUtils {
  16. /**
  17. * c3p0
  18. */
  19. private static DataSource source1=new ComboPooledDataSource("helloc3p0");
  20. public static Connection getConnection() throws SQLException {
  21. return source1.getConnection();
  22. }
  23. /**
  24. * dbcp
  25. */
  26. private static DataSource source2=null;
  27. static{
  28. try {
  29. InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("dbcp.properties");
  30. Properties prop = new Properties();
  31. prop.load(is);
  32. source2=BasicDataSourceFactory.createDataSource(prop);
  33. } catch (Exception e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. public static Connection getConnection2() throws SQLException {
  38. return source2.getConnection();
  39. }
  40. private static DataSource source3=null;
  41. static {
  42. try {
  43. Properties prop = new Properties();
  44. InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
  45. prop.load(is);
  46. source3=DruidDataSourceFactory.createDataSource(prop);
  47. } catch (Exception e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. public static Connection getConnection3() throws SQLException {
  52. return source3.getConnection();
  53. }
  54. /**
  55. * closeResource
  56. */
  57. public static void closeResource(Connection co){
  58. JdbcUtils.close(co);
  59. }
  60. }