本文主要是介绍Java程序猿必学第二十三篇——网络编程(聊天室)与反射,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
//1. 网络编程案例
//1.1 注册功能
//案例:注册功能
//分析:
//1.客户端与服务器建立连接
//2.客户端准备好注册数据,拼成一个字符串;例如:{id:"1001",name:"zs",age:30}
//3.发送注册数据,服务器接收数据
//4.服务器拆分数据,取出id对应的value作为key,接收的注册信息作为value
//5.判断key在配置文件中是否存在,如果存在,则返回"已存在"
//6.不存在,把这些数据存到配置文件,并返回“注册成功”
//-----服务器------
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(9527);
Socket socket = ss.accept();
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg = br.readLine(); //{id:1001,name:zs,age:30}
String strId = msg.split(",")[0]; //{id:1001
String id = strId.split(":")[1]; //1001
//通过Properties集合去加载配置文件
Properties p = new Properties();
p.load(new FileInputStream("user.properties"));
OutputStream os = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
if(p.containsKey(id)) {
bw.write("已存在");
}else {
Tool.saveProperties(id,msg); //将数据存储到配置文件
bw.write("注册成功");
}
bw.newLine();
bw.flush();
IOUtils.closeAll(bw,os,br,is,socket);
}
}
//-----客户端------
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",9527);
OutputStream os = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
String json = getData(); //{id:1001,name:zs,age:30}
//发数据
bw.write(json);
bw.newLine();
bw.flush();
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg = br.readLine();
System.out.println("服务器响应:"+msg);
IOUtils.closeAll(is,br,os,bw,socket);
}
private static String getData() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入ID:");
String id = sc.next();
System.out.println("请输入用户名:");
String name = sc.next();
System.out.println("请输入年龄:");
int age = sc.nextInt();
return "{id:"+id+",name:"+name+",age:"+age+"}";
}
}
//----工具类----
public class Tool {
public static void saveProperties(String id, String msg) throws FileNotFoundException, IOException {
Properties properties = new Properties();
properties.put(id, msg);
properties.store(new FileOutputStream("user.properties"), "");
}
}
//1.2 聊天室程序
//案例:聊天室程序
//分析: 多人聊天---多线程
//1.通过多线程形式接收多个客户端的连接
//2.客户端要录入姓名,传入服务器接收,并存储到线程中
//(注意:客户端的发送和接收要分为两个线程,才能方便群发)
//3.服务器给客户端回应“欢迎进入聊天室”
//4.该客户端就可以实时发数据聊天了
//5.要实现服务器群发信息给客户端,需要先将所有线程对象存储
//6.退出方式,客户端退出,其他用户应该都知道
-------服务器-------
public class Server {
public static List<ServerThread> list = new ArrayList<ServerThread>();
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(9527);
//多线程方式监听及创建socket
while(true) {
Socket socket = ss.accept();
System.out.println("有一个客户端进来了");
ServerThread st = new ServerThread(socket);
st.start();
list.add(st); //存储线程对象
}
}
}
//------服务器线程-------
public class ServerThread extends Thread {
private Socket socket;
private BufferedReader br;
private BufferedWriter bw;
public ServerThread(Socket socket) throws IOException {
this.socket = socket;
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
}
@Override
public void run() {
try {
sendHello(); //欢迎
while(true){
String name = this.br.readLine(); //读取到数据后,发给自身
String msg = this.getName()+"说:"+name;
//循环遍历线程对象,除了自己,都发一份出去
for(ServerThread st : Server.list) {
if(st!=this) {
st.bw.write(msg);
st.bw.newLine();
st.bw.flush();
}
}
}
} catch (Exception e) {
String msg = this.getName()+"退出了聊天室"; //群发退出信息
Server.list.remove(this); //将当前线程对象在集合中移除
for(ServerThread st : Server.list) { //移除后群发
try {
st.bw.write(msg);
st.bw.newLine();
st.bw.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}finally {
IOUtils.closeAll(bw,br,socket);
}
}
private void sendHello() throws IOException {
String name = br.readLine(); //读取到数据后,发给自身
String msg = "【温馨提示】:欢迎"+name+"进入聊天室";
this.setName(name); //记录客户的访问
bw.write(msg);
bw.newLine();
bw.flush();
}
}
//------客户端-------
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",9527);
//客户端读写分离
new WriteClient(socket).start();
new ReadClient(socket).start();
}
}
//-------客户端写线程-------
public class WriteClient extends Thread {
private Socket socket;
public WriteClient(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
OutputStream os = null;
BufferedWriter bw = null;
try {
os = socket.getOutputStream();
bw = new BufferedWriter(new OutputStreamWriter(os));
System.out.println("请输入用户名:");
Scanner sc = new Scanner(System.in);
while(true) {
String name = sc.next(); //第一次是输入名字,后面就是聊天内容
bw.write(name);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
IOUtils.closeAll(os,bw,socket);
}
}
}
//-------客户端读线程--------
public class ReadClient extends Thread {
private Socket socket;
public ReadClient(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
InputStream is = null;
BufferedReader br = null;
try {
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
while(true) {
String msg = br.readLine();
System.out.println(msg);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
IOUtils.closeAll(is,br,socket);
}
}
}
//2. 反射(重点)
//2.1 反射概述
/**
*概述:反射对象,就是类对象,是类加载的产物,
只要有了类对象,就可以知道类的所有信息(类名,接口,包名,属性,方法等)
获取类对象方式:
1.类名.class (常用)
2.对象.getClass()
3.Clas.forname("包名.类名") (常用)
结论:无论哪种方式获取的类对象,都是同一个
*
*/
class Person{
private String name;
private int age;
public Person() {
System.out.println("调无参构造");
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void test() {
System.out.println("test");
}
}
public class Test1 {
public static void main(String[] args) throws ClassNotFoundException {
Class class1 = Person.class;
Class class2 = new Person().getClass();
Class class3 = Class.forName("com.qf.d_reflect.Person");
System.out.println(class1==class2); //true
System.out.println(class1==class3); //true
}
}
//2.2 反射常用方法
public class Test2 {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException, NoSuchMethodException {
Class clazz1 = Person.class; //获取反射对象
System.out.println(clazz1.getName()); //获取类名
System.out.println(clazz1.getPackage()); //获取包名
System.out.println(clazz1.getSuperclass()); //获取父类
System.out.println(Arrays.toString(clazz1.getInterfaces())); //获取接口
System.out.println(Arrays.toString(clazz1.getFields())); //性能高,不能处理私有权限属性
System.out.println(Arrays.toString(clazz1.getDeclaredFields())); //(常用)可以处理私有权限
System.out.println(Arrays.toString(clazz1.getMethods()));//(常用)
System.out.println(Arrays.toString(clazz1.getConstructors())); //获取所有构造器
System.out.println(clazz1.getDeclaredField("name")); //(常用) 获取Field对象
System.out.println(clazz1.getMethod("test")); //(常用) 获取Method对象
System.out.println(clazz1.newInstance()); //调无参构造 (常用)
}
}
//2.3 反射操作属性
//通过反射对象,给私有属性赋值及取值
//分析:
//1.获取反射对象
//2.获取Field对象
//3.调用set方法赋值 ,通过get方法取值
class Student{
private String name;
private int age;
public String getName() {
return name;
}
public void hello(String name,int age) {
System.out.println("反射的方法调用--"+name+"--"+age);
}
}
public class Test1 {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
Class clazz = Student.class;
Field field = clazz.getDeclaredField("name");
field.setAccessible(true); //开启私有权限
Student st = (Student) clazz.newInstance();
field.set(st, "zsf");
System.out.println(field.get(st));
System.out.println(st.getName()); //验证value值是否存储到name属性
}
}
//2.4 反射操作方法
//案例2:通过反射对象调用方法
//1.获取反射对象
//2.通过反射获取Method对象,传方法名和反射类型
//3.通过Method对象调invoke方法
//反射作用:可以灵活动态操作属性和方法
public class Test2 {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
Class<Student> class1 = Student.class;
//获取Method对象,参数1:方法名 后面参数:参数类型反射对象
Method method = class1.getMethod("hello", String.class,int.class);
method.invoke(class1.newInstance(), "谭小虎",28);
}
}
//2.5 反射应用场景
//案例3:通过反射对象灵活的获取老师和学生的对象
class Teacher{
}
public class Test3 {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
//常规获取对象方式:
//弊端: 每次获取对象时,都创建了不同的方法
Teacher teacher = Tool.getTeacher();
Student student = Tool.getStudent();
//使用反射灵活获取对象
Teacher t1 = Tool.getObject(Teacher.class);
Student s1 = Tool.getObject(Student.class);
System.out.println(t1+"---"+s1);
}
}
//----工具类调用-----
public class Tool {
public static Teacher getTeacher() {
return new Teacher();
}
public static Student getStudent() {
return new Student();
}
//泛型方法
public static <T> T getObject(Class<T> class1) throws InstantiationException, IllegalAccessException {
return class1.newInstance();
}
}
这篇关于Java程序猿必学第二十三篇——网络编程(聊天室)与反射的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!