今日学习目标
- 网络编程
- TCP通信
- Junit单元测试
- 单列设计模式
- 多列设计模式
-
1 网络编程
1.1 网络编程三要素
IP地址 : 设备在网络中的地址,是唯一的标识。
- 端口 : 设备在网络中的地址,是唯一的标识。
数据在网络中传输的规则,常见的协议有UDP协议和TCP协议。
1.2 IP地址
P地址常见分类 : ipv4和ipv6
- 常用命令:
- ipconfig:查看本机IP地址
- IP地址:检查网络是否连通
- 特殊IP地址:
- 127.0.0.1:是回送地址也称本地回环地址,可以代表本机的IP地址,一般用来测试使用
- InetAddress类: | 构造方法 | 作用 | | —- | —- | | static InetAddress getByName(String host) | 在给定主机名的情况下确定主机的 IP 地址 | | String getHostName() | 获取此 IP 地址的主机名 | | String getHostAddress() | 返回 IP 地址字符串(以文本表现形式) |
1.3 端口
- 端口:应用程序在设备中唯一的标识。
- 端口号:用两个字节表示的整数,它的取值范围是0~65535,其中0~1023之间的端口号用于一些知名的网络服务或者应用,我们自己使用1024以上的端口号就可以了
-
1.4 通信协议
协议:计算机网络中,连接和通信的规则被称为网络通信协议
- UDP协议:
- UDP是面向无连接通信协议.
- 速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。
TCP协议:
- TCP协议是面向连接的通信协议
-
2 TCP通信
2.1 TCP发送数据
```java import java.io.IOException; import java.io.OutputStream; import java.net.Socket; /* 客户端 : 发送数据的步骤 1 创建客户端的Socket对象 : Socket(String host, int port) 与指定服务端连接
参数说明:host 表示服务器端的主机名,也可以是服务器端的IP地址,只不过是String类型的port 表示服务器端的端口
2 通获Socket对象取网络中的输出流,写数据
OutputStream getOutputStream()
3 释放资源
void close()
*/ public class ClientDemo { public static void main(String[] args) throws IOException {
// 创建客户端的Socket对象(Socket) 与指定服务端连接Socket socket = new Socket("127.0.0.1", 10010);// 通获Socket对象取网络中的输出流,写数据OutputStream os = socket.getOutputStream();os.write("hello".getBytes());// while(true){}// 释放资源os.close();socket.close();
2.2 TCP接收数据
```java import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;
/* 服务端接收数据 :
1 创建服务器端的Socket对象 : ServerSocket类ServerSocket(int port) : 构造方法需要绑定一个端口号 , port就是端口号2 监听客户端连接,并接受连接,返回一个Socket对象Socket accept() : 该方法会一直阻塞直到建立连接3 获取网络中的输入流,用来读取客户端发送过来的数据InputStream getInputStream()4 释放资源 : 服务端一般不会关闭void close()
*/ public class ServerDemo { public static void main(String[] args) throws IOException { // 1 创建服务器端的Socket对象 : ServerSocket类 // ServerSocket(int port) : 构造方法需要绑定一个端口号 , port就是端口号 ServerSocket serverSocket = new ServerSocket(10010);
// 2 监听客户端连接,并接受连接,返回一个Socket对象 // Socket accept() : 该方法会一直阻塞直到建立连接 Socket socket = serverSocket.accept(); // // 3 获取网络中的输入流,用来读取客户端发送过来的数据 // InputStream getInputStream() InputStream is = socket.getInputStream(); int by; System.out.println(“read方法执行前”); while ((by = is.read()) != -1) { System.out.print((char) by); } System.out.println(“read方法执行后”); } }
<a name="NyH7d"></a>#### 2.3 TCP练习1- 代码需要敲熟练:```javapublic class ClientDemo {public static void main(String[] args) throws IOException {// 创建客户端的Socket对象(Socket) 与指定服务端连接Socket socket = new Socket("127.0.0.1", 10010);// 通获Socket对象取网络中的输出流,写数据OutputStream os = socket.getOutputStream();os.write("hello".getBytes());// 像服务端写入结束标记socket.shutdownOutput();BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line = br.readLine();System.out.println(line);// 释放资源br.close();os.close();socket.close();}}
public class ServerDemo {public static void main(String[] args) throws IOException {// 1 创建服务器端的Socket对象 : ServerSocket类// ServerSocket(int port) : 构造方法需要绑定一个端口号 , port就是端口号ServerSocket serverSocket = new ServerSocket(10010);// 2 监听客户端连接,并接受连接,返回一个Socket对象// Socket accept() : 该方法会一直阻塞直到建立连接Socket socket = serverSocket.accept();//// 3 获取网络中的输入流,用来读取客户端发送过来的数据// InputStream getInputStream()InputStream is = socket.getInputStream();int by;while ((by = is.read()) != -1) {System.out.print((char) by);}BufferedWriter bos = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));bos.write("你谁啊");bos.close();is.close();socket.close();serverSocket.close();}}
2.4 TCP练习2
public class ClientDemo {public static void main(String[] args) throws IOException {// 创建客户端Socket对象Socket socket = new Socket("127.0.0.1", 10086);BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\传智播客\\安装包\\好看的图片\\liqin.jpg"));BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());int by;while ((by = bis.read()) != -1) {// 从本地中读一个字节bos.write(by);// 往服务器写一个字节bos.flush();}// 写结束标记socket.shutdownOutput();// 把网络中的字节输入流 , 封装成高效的字符输入流BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));// String line;// while ((line = br.readLine()) != null) {// System.out.println(line);// }String msg = br.readLine();// 读到换行才叫读到一行, 所以必须写服务器必须写newLineSystem.out.println(msg);// 释放资源bis.close();socket.close();}}
public class ServerDemo {public static void main(String[] args) throws IOException {// 创建服务端的连接对象ServerSocket serverSocket = new ServerSocket(10086);Socket socket = null;BufferedInputStream bis = null;BufferedWriter socketBw = null;while (true) {// 获取Socket对象socket = serverSocket.accept();// 获取网络中的字节输入流 在封装成高效的字节输入流对象bis = new BufferedInputStream(socket.getInputStream());// 创建本地的字节输出流 , 封装成高效的字节输出流BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("day13_demo\\图片\\a.jpg"));int by;while ((by = bis.read()) != -1) {bw.write(by);bw.flush();}//关闭本地流bw.close();// 获取网络中的字节输出流 , 封装成高效的字符输出流socketBw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));socketBw.write("谢谢你");socketBw.newLine();// 必须有换行 , 因为readLine读到换行结束socketBw.flush();}// 释放资源// socketBw.close();// bis.close();// socket.close();// serverSocket.close();}}
2.5 TCP练习3
public class ClientDemo {public static void main(String[] args) throws IOException {// 创建客户端Socket对象Socket socket = new Socket("127.0.0.1", 10086);BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\传智播客\\安装包\\好看的图片\\liqin.jpg"));BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());int by;while ((by = bis.read()) != -1) {// 从本地中读一个字节bos.write(by);// 往服务器写一个字节bos.flush();}// 写结束标记socket.shutdownOutput();// 把网络中的字节输入流 , 封装成高效的字符输入流BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));// String line;// while ((line = br.readLine()) != null) {// System.out.println(line);// }String msg = br.readLine();// 读到换行才叫读到一行, 所以必须写服务器必须写newLineSystem.out.println(msg);// 释放资源bis.close();socket.close();}}
public class ServerDemo {public static void main(String[] args) throws IOException {// 创建服务端的连接对象ServerSocket serverSocket = new ServerSocket(10086);ExecutorService executorService = Executors.newFixedThreadPool(10);while (true) {// 获取Socket对象Socket socket = serverSocket.accept();executorService.submit(new ServerThread(socket));}// 释放资源// socketBw.close();// bis.close();// socket.close();// serverSocket.close();}}
public class ServerThread implements Runnable {Socket socket = null;BufferedOutputStream bw = null;public ServerThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {// 获取网络中的字节输入流 在封装成高效的字节输入流对象BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());// 创建本地的字节输出流 , 封装成高效的字节输出流bw = new BufferedOutputStream(new FileOutputStream("day13_demo\\图片\\" + UUID.randomUUID() + ".jpg"));int by;while ((by = bis.read()) != -1) {bw.write(by);bw.flush();}// 获取网络中的字节输出流 , 封装成高效的字符输出流BufferedWriter socketBw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));socketBw.write("谢谢你");socketBw.newLine();// 必须有换行 , 因为readLine读到换行结束socketBw.flush();} catch (IOException e) {e.printStackTrace();} finally {//关闭本地流try {bw.close();} catch (IOException e) {e.printStackTrace();}}}}
3 Junit单元测试
3.1 Junit4单元测试概述
- 单元测试就是编写测试代码,可以准确、快速地保证程序的正确性,Junit是Java单元测试的框架
JUnit4可以通过注解的方式来标记方法 , 让方法存某种意义 ,常见的注解有:
生成Junit测试框架
- 右键选择 Generate(Alt+Insert)/ go to 选项 , 选择Test…
可以在注释后面给个毫秒值单位
预先判断某个条件一定成立,如果条件不成立,则直接报错。
- 使用 :
- 格式:Assert.assertEquals(期望值,实际值) ```java //第一个参数表示期望值 //第二个参数表示实际值 // 如果实际值和期望值相同,说明结果正确就测试通过,如果不相同,说明结果是错误的,就会报错 Assert.assertEquals( 期望值, 实际值); Assert.assertEquals(“异常原因”, 期望值, 实际值);
//例如: int result = add(100,200); Assert.assertEquals(300, result);
<a name="Ox6YD"></a>### 4 单例设计模式<a name="gxcvi"></a>#### 4.1 单例设计模式的作用- 一个类只有一个对象实例。- 可以节省内存,共享数据<a name="NdFyq"></a>#### 4.2 单例设计模式的类型- 饿汉单例设计模式- 懒汉单例设计模式<a name="pRpky"></a>#### 4.3 实现单例模式的步骤- 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。- 在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型的成员变量。- 定义一个静态方法返回这个唯一对象。<a name="mU5fA"></a>#### 4.3 饿汉单例设计模式- 饿汉单例设计模式就是使用类的时候已经将对象创建完毕```javapublic class Singleton {// 1.将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。private Singleton() {}// 2.在该类内部产生一个唯一的实例化对象,并且将其封装为private static 类型的成员变量。private static final Singleton instance = new Singleton();// 3.定义一个静态方法返回这个唯一对象。public static Singleton getInstance() {return instance;}}
4.4 懒汉单例设计模式
懒汉单例设计模式就是调用getInstance()方法时对象才被创建
public class Singleton {// 1.将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。private Singleton() {}// 2.在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型的成员变量。private static Singleton instance; // 0x001// 3.定义一个静态方法返回这个唯一对象。要用的时候才例化出对象public static synchronized Singleton getInstance() {if(instance == null) {instance = new Singleton();}return instance;}}
注意事项:
通过多例模式可以保证项目中,应用该模式的类有固定数量的实例。
- 多例类要自我创建并管理自己的实例,还要向外界提供获取本类实例的方法。
- 使用场景:线程池:
- 创建一个类, 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象
- 在类中定义该类被创建对象的总数量
- 在类中定义存放类实例的list集合
- 在类中提供静态代码块,在静态代码块中创建类的实例
-
5.3.实现代码
```java /* 需求 : 某一个学科有固定3位老师,年级中上该课程的老师就是这三位老师其中一位
要求使用多例模式 ,每次获取的都是这三位老师其中一位
实现步骤 :
1.创建一个类, 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。2.在类中定义该类被创建对象的总数量3.在类中定义存放类实例的list集合4.在类中提供静态代码块,在静态代码块中创建类的实例5.提供获取类实例的静态方法
*/ public class Teacher { // 1.创建一个类, 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。 private Teacher() { }
// 2.在类中定义该类被创建对象的总数量 private static int maxCount = 3;
// 3.在类中定义存放类实例的list集合 private static ArrayList
list = new ArrayList<>();// {teacher1 , teacher2 , teacher3} // 4.在类中提供静态代码块,在静态代码块中创建类的实例 static {
for (int i = 0; i < maxCount; i++) {list.add(new Teacher());}
}
// 5.提供获取类实例的静态方法 public static Teacher getInstance() {
int index = new Random().nextInt(3);// [0 - 2]return list.get(index);
}
}
<a name="IMfWZ"></a>### 6 工厂设计模式<a name="SxkEX"></a>#### 6.1 概述- 工厂模式:它提供了一种创建对象的最佳方式。之前我们创建类对象时, 都是使用 new 对象的形式创建, 除new 对象方式以外, 工厂模式也可以创建对象.<a name="jmx9L"></a>#### 6.2 作用- 解决类与类之间的耦合问题,防止因为对象的改变而影响到其他调用这个对象的类<a name="YIh3f"></a>#### 6.3案例实践```java/*- 需求:定义汽车工厂类,生产各种品牌的车- 实现步骤- 编写一个Car接口, 提供run方法- 编写一个Falali类实现Car接口,重写run方法- 编写一个Benchi类实现Car接口=============================================- 提供一个CarFactory(汽车工厂),用于生产汽车对象- 定义CarFactoryTest测试汽车工厂*/public class CarTest {public static void main(String[] args) {Car benchi = CarFactory.getInstance(Brand.BENCHI);System.out.println(benchi);}}// 汽车接口interface Car {public abstract void run();}// 编写一个Falali类实现Car接口,重写run方法class Falali implements Car {public Falali() {}@Overridepublic void run() {System.out.println("法拉利破百需要3秒...");}}// 编写一个Benchi类实现Car接口class Benchi implements Car {@Overridepublic void run() {System.out.println("奔驰破百需要5秒...");}}// 汽车品牌枚举enum Brand {BENCHI, FALALI, BAOMA, BINLI, AODI;}// 提供一个CarFactory(汽车工厂),用于生产汽车对象class CarFactory {private CarFactory() {}public static Car getInstance(Brand brand) {switch (brand) {case FALALI:return new Falali();case BENCHI:return new Benchi();default:return null;}}
