数据发送:
使用输出流发送数据给服务器
遵从Runnable接口
数据接收:
使用输入流从服务器端接收数据
遵从Runnable接口
客户端主方法:
用户名提交
数据发送
数据接收
多线程启动
-代码中操作了大量的输入流和输出流,这里都需要进行关闭操作。
DataInputStream, DataOutputStream, BufferedReader, Socket
以上这些资源都是Closeable接口的实现类,都有对应的Close方法
封装一个工具类:
提供一个closeAll方法,参数为符合Closeable接口的实现类对象。
这里可以考虑可变长参数
Closeable… closeable
可变长参数在方法中使用的过程里面是对应一个数组,这里完成可以使用增强for来使用
工具类名:
CloseUtil
public static void closeAll(Closeable… closeable)
用户退出
用户输入指定字段之后可以退出
客户端Socket服务
服务端Socket服务
涉及资源关闭,线程关闭
用户异常退出
在运行过程中发现问题,需要及时处理,关闭对应的资源,终止对应的线程
服务器保存所有的聊天记录
JSON对象
{
“ID”:001,
“name”:“骚磊”,
“age”:16
}
特征:
1. 数据形式键值对形式
“键”:值
2. 数据支持 字符串,数字,true false
3. {} 大括号以内的数据
JSON对象数组
特征:
1. 数据使用[]包含
2. 在[]都是JSON格式对象
3. 每一个对象之间使用逗号隔开,同时最后一个元素不需要逗号
JSON数据验证
常用的工具:
Gson,fastjson, Jackson
以上都是第三方工具,需要导入对应的jar包按使用XML导包
FastJson内容
解析演示
注解解释
注解:
Java语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java虚拟机可以保留标注内容,在运行时可以获取到标注内容。 当然它也支持自定义Java标注
JDK1.5之后的特征
用于说明程序
一般在框架中使用
格式:
@AnnotationName
文档注释:
@param @return @Exeception 从根本上是一个注释,不存在代码编译,不会生成对应的.class字节码问题,只是提供给JavaDoc API文件生成工具。作为标记生成对应的文档。
注解是有一部分参与编译
@Override并不是没编译就有效果了,是因为不管是Eclipse还是IDEA都可以预编译Java代码生成对应的.class文件的
注解作用
【IDEA JavaDoc工具使用参数】
Other Command Line Arguments : -encoding utf-8 -charset utf-8
解决中文乱码,因为IDEA默认编码集为UTF-8 Windows GKB
代码检查:
继承重写,或者说接口遵从之后的实现中,存在@Override
代码数据获取: [小框架]
通过反射获取指定注解中的一些内容,例如 配置,数据,操作,验证。。。
Java中预定义的一些注解
@Deprecated
标注当前方法已过时,例如 Data日期类内的一些方法
@SuppressWarnings(“all”)
压制警告,可以用于一些代码中存在明确无异常的情况下,压制一些警告
Java中自定义注解的方式
Annotation注解是可以编译得到对应的.class字节码文件,验证了注解是可以参与编译过程的
通过反编译工具可以得到一下内容
【Annotation本质】
public interface MyAnnotation1 extends java.lang.annotation.Annotation {
}
MyAnnotation1
本质是一个interface,同时java.lang.annotation.Annotation 子接口
Annotation注解属性【难点】
【但是实际上是利用abstract方法来完成属性概念的】
属性使用的格式[实际按照方法格式操作]
1. 属性的值数据类型和对应具体数据 ==> 返回值类型和返回的数据
属性类型支持:
a. 基本数据类型
b. String类型
c. 其他的注解类型
d. 枚举类型
枚举就是一个带有名字的常量,为了更好的域阅读性和操作
e. 以上类型对相应的数组
属性值要求
a. 定义属性时可以使用default关键字,加上默认值,该属性在使用的过程中是
没有强制要求属性值,如果没有赋予属性值,采用对应的默认值操作,如果赋
值,使用对应值
b. 如果注解中有且只有一个value属性,或者说注解中除value属性之外,都有
默认值,不管是类,方法,成员变量,包使用当前注解是可以直接在括号内加入
对应数据类型数值、
c. 如果属性是数组类型, {}大括号保存,并且不同的内容,使用,隔开
2. 属性的键名字 ==> 方法的名字
元注解
别纠结,记下就好:
RetentionPolicy.SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)
@Override
对应属性RetentionPolicy.SOURCE
在代码编译过程中,检查方法格式是否正确,不参与代码运行和解析。
@Documented
标记这些注解是否包含在用户文档中。
是否可以通过JavaDoc工具,生成对应的API文档
@Target
标记这个注解应该是哪种 Java 成员。
属性:
ElementType
TYPE: 当前注解可以用于类声明
METHOD: 当前注解可以用于方法声明位置
FIELD:当前注解可以用于成员变量声明位置
@Inherited
标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
【重点】
@Target目标
可以作用范围 类,方法,成员变量…
@Retention
RetentionPolicy.RUNTIME 常用
概述
可以直接理解JDK1.8的新特征,Lambda表达式来使用。
Lambda表达式对比匿名内部类使用
1. 简化了代码结构
2. 节约了内存资源
3. 让程序员更加关注,我要做什么,而不是为了做什么需要完成什么
@FunctionalInterface 使用
Lambda延迟执行
日志记录
使用函数式接口提供日志信息功能
Lambda作为方法参数和返回值
JDK常用函数式接口概述
Supplier 生产者, 返回一个指定类型的数据
Consumer 消费者, 消耗一个指定类型的数据
Predicate 判断调节,过滤使用
Function
Supplier 生产者,返回一个指定的数据类型
Consumer消费者,处理数据
Predicate 判断数据是否合适,返回true/false
Function
延迟方法:
返回值类型依然是Stream接口本身,并没有影响我们操作真正的资源
允许链式操作,
例如
filter(XXX).limit(XXX).sorted(XXX).
终结方法:
返回值类型不是Stream接口本身,要么处理数据,要么返回其他类型数据,并且不再支持Stream流对象链式操作,count,foreach
foreach方法【终结方法】
filter方法
Stream filter(Predicate super T> condition);
/*
filter是过滤方式,需要的参数是Predicate接口,Predicate是一个函数式接口,可以直接使用Lambda表达运行。
这里返回值类型是Stream类对象,是经过过滤之后的Stream类型,可以进行链式操作
Predicate接口中需要实现的方法
boolean test(T t);
*/
为何会出现这个错误?
因为调用终结方法后,Stream流已经被销毁,所以不能再对Stream流进行操作。
- map方法
- Stream map(Function super T, ? super R> fun);
/*
类型转换操作,得到的一个转换之后数据类型的Stream流对象
这里需要的参数是Function函数式接口,
R apply(T t);
T类型的数据转换成R类型数据
*/
- count方法【终结方法】
- long count();
/*
返回当前Stream流对象中有多少个元素
类似有Collection接口下的size(). String的length();
【终结方法】
一旦执行Stream流对象被关闭
*/
- limit方法
- Stream limit(long maxSize);
/*
对于当前Stream流对象操作的数据进行限制操作,限制个数到maxSize
例如:
Stream流中保存的有10个元素,limit 5 ==> 前五个元素
*/
- skip方法
- Stream skip(long n);
/*
返回值依然是一个Stream流对象,这里跳过当前Stream流对象前n个元素
*/
- concat方法
- static Stream concat(Stream extends T> a, Stream extends T> b)
/*
拼接两个Stream流对象,是一个静态方法,得到新的Stream流对象
*/
- 原始操作方式和Stream流方式对比
- 1. 一个String类型的字符串集合,"1,骚磊,16"
testPrint(“郑州加油!!!”, System.out::println);
BIO
BIO ==> Basic IO (基本IO), Block IO(阻塞IO)
Scanner操作,文件读写操作,Socket数据传输操作… 都是BIO
比如TCP群聊,私聊聊天室
Socket涉及到的IO,也是BIO
资源浪费:
1. 多线程,每一个Socket会对应一个线程,如果用户量巨大,会导致线程过
多,资源处理过多
2. 采用阻塞状态,一旦进入阻塞,代码无法执行其他操作。
3. 承载量一般,吞吐量比较小,同时可靠性不佳
常用API
常用方法:
public static ByteBuffer allocate(int capacity);
按照指定的字节数分配对应的缓冲区空间,保存字节数据
public byte get();
从字节缓冲区对象中读取一个byte类型数组
public final Buffer flip();
翻转缓冲区,回到缓冲区的开始位置。
public static ByteBuffer wrap(byte[] arr);
存入一个byte类型数组到缓冲区,会得到一个新的ByteBuffer
public static ByteBuffer put(byte[] b);
将字节数组存入缓冲区
Channel接口,通道接口
FileChannel 文件操作通道
DatagramChannel UDP协议数据包操作的Channel
ServerSocketChannel TCP服务端ServerSocket对应Channel
SocketChannel TCP客户端Socket对应Channel
首先操作文件,以FileChannel为例
public long read(ByteBuffer buffer);
从通道中读取数据到ByteBuffer中
public long write(ByteBuffer buffer);
从Buffer中写数据到通道中
public long transferFrom(ReadableByteChannel src, long position, long count)
从指定srcChannel中,指定位置position开始,读取count个元素,到当前通道中
文件复制操作。
public long transferTo(long position, long count, WritableByteChannel target)
将当前通道中的数据写入到target中,从当前通道的position位置开始,计数count
Selector选择器老大
Selector常用方法:
public static Selector Open();
得到一个选择器对象
public int select(long timeout);
监听所有注册通道,存在IO流操作是,会将对应的信息SelectionKey存入到内部的集
合中,参数是一个超时时间
public Set selectionKeys();
返回当前Selector内部集合中保存的所有SelectionKey
SelectionKey
ServerSocketChannel
SocketChannel
常用方法:
public static SocketChannel open();
打卡一个Socket客户端Channel对象
public final SelectableChannel configureBlocking(boolean block)
这里可以设置是阻塞状态,还是非阻塞状态
false,表示非阻塞
public boolean connect(SocketAddress remote);
连接服务器
public boolean finishConnect();
如果connect连接失败,可以通过finishConnect继续连接
public int write(ByteBuffer buf);
写入数据到缓冲流中
public int read(ByteBuffer buf); 、
从缓冲流中读取数据
public final SelectionKey register(Selector sel, int ops, Object attechment);
注册当前SocketChannel,选择对应的监听操作,并且可以带有Object attachment参数
public final void close();
关闭SocketChannel
XMind: ZEN - Trial Version