`
蛋呢823
  • 浏览: 72056 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

山寨hibernate

    博客分类:
  • SSH
阅读更多

 

    之前, 在做web 个人blog项目的时候,

    数据库那里设置了三个表 ---- userinfo, article, comment

    然后,在项目里写了个pojo包, dao包.

    里面 分别都有三个表的 对应的 实现类 和 操作类 ,

    这样, 即使是只写 基本的 CRUD操作. 也都要写3遍.

    代码量,复杂程度 可想而知 ...

 

    现在, 利用 java 灵活的反射功能.

    可以 很灵活的 通过反射 判断一个对象的类

    从而 实现 智能分析的功能.

 

    举个例子,  通过一个例子  比较一下:

 

    任务:     往数据库里 分别添加一个 user对象, 一个article对象, 一个comment对象

 

    之前:    

  • 调用 user      的dao类 的save方法.        eg:  userDao.save(user);
  • 调用 article    的dao类 的save方法.        eg:  articleDao.save(article);
  • 调用comment 的dao类 的save方法.        eg:  commentDao.save(comment);

 

    现在:  

  •   save(user);
  •   save(article);
  •   save(comment);

 

 

    是不是很省事???  

 

 

    来看看具体的代码 是怎么实现的吧...

 

    先大致的介绍一下这个东东的基本功能....

 

    1. 增加对象. .

 

/**
* 保存一个对象的 方法.
* @param obj: 要保存的对象
*/
public static boolean save (Object obj){}

        sql =  insert into obj.类名 (属性1,属性2,...) values (值1,值2, ...) ;

 

     2. 删除对象..

 

/**
 * 删除一个对象的方法
 * @param  id: 要删除的数据的ID, 
 * @param  c : 要删除的数据的类型.
 */
public static boolean delete (int id , Class c){}

        sql = delete  from 类名 where id= id;

 

     3. 修改对象的属性值

 

/**
 * 修改一个对象的信息的方法
 *  @param obj: 传入修改后的对象
 */
public static boolean modify (Object obj){}

         sql = update obj.类名 set 属性1=值1,属性2=值2,...   where id = obj.getId;

 

     4. 查找---某一类型的全部对象

 

/**
 * 查找某一个类型的所有对象. select * from 表名;
 * 
 * @return : 对象的队列
 */
public static List selectAll(Class c) {}

       sql = select * from 类名;

 

     5. 查找--- 根据某些属性  模糊查找

 

/**
 * 根据一个模板来查找对象 可以理解成为多条件查找. eg: 查找 age=20, name="Lilei" 的用户
 * 
 * @param obj
 */
public static List selectBySample(Object obj) {}

     sql = select * from 类名 where 属性1 = 值1  and  属性2 like 值2 ...;

      (int型 就用等号连接,   string型 则模糊查找  用like 连接)

 

    6. 查找--- 根据id 来查找

 

/**
 * 通过唯一的 主键 id 查找对象的方法
 * 
 * @param id: id
 * @param c : 要查找的类型
 * @return : 返回对象
 */
public static Object selectById(int id, Class c) {}

      sql = select * from 类名 where  id = id;

 

 

    目前只写了这么多功能...

    相信多花点心思下去,  可以写得更好的...

 

    大家可能注意到,  上面的每一个功能下面  我都添加了个 sql 的注释..

     因为,  在现在看来.

    下面的代码, 所干的事情,  就是 :

  •   拼凑一条 符合操作要求的 sql ; 
  •   执行sql 语句;
  •   返回结果;
  •   对结果 进行处理 --- (对于selec 语句: 把得到的属性值 赋值给一个对象, 返回这个对象, 或者这个对象队列..)

 

      其中 写出 一句 正确的 sql 语句是 很关键的一步...

 

      具体实现.  就看看下面的代码吧...

 

 

package orm;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.Date;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 山寨hibernate的实现. 实现ORM 功能
 * 
 * @author 小奇
 * 
 */
public class HibernateORM {

	/**
	 * 保存一个对象的 方法.
	 * 
	 * @param obj
	 *            : 要保存的对象
	 */
	public static boolean save(Object obj) {

		// 1.拼凑一条 保存的sql语句 insert into 类名 (属性1,属性2,...) values (值1,值2, ...) ;
		String sql = "insert into ";
		// 得到对象的类
		Class c = obj.getClass();
		// 得到类名 也就是表名
		String cName = c.getName();
		sql += cName.substring(cName.lastIndexOf(".") + 1, cName.length());
		// 得到类中的所有方法的队列
		java.lang.reflect.Method[] methods = c.getMethods();

		List<Method> gets = new ArrayList<Method>();
		for (Method m : methods) {
			String s = m.getName();

			// 判断是否为 get 方法 而且 不是getClass 方法
			if (s.startsWith("get") && !s.equals("getClass")) {
				try {
					// int类型的默认值是 0; 所以必须去除这种 默认值的..
					if ((m.invoke(obj, null) != null)
							&& !m.invoke(obj, null).equals(0)) {
						gets.add(m);
						System.out.println("------>方法名:" + s);
					}
				} catch (IllegalArgumentException e1) {
					e1.printStackTrace();
				} catch (IllegalAccessException e1) {
					e1.printStackTrace();
				} catch (InvocationTargetException e1) {
					e1.printStackTrace();
				}
			}
		}
		String properties = "(";
		String values = "(";
		for (int i = 0; i < gets.size(); i++) {
			Method m = gets.get(i);
			// 先判断属性值 是否为null 如果为null 则没必要继续写入语句
			try {
				String s = m.getName();
				// 得到属性名 即get后面的字符串
				String fName = s.substring(3, s.length());
				if (i != gets.size() - 1) {
					properties += fName + " , ";
				} else
					properties += fName + ") ";

				// 执行get方法
				// 判断get方法的返回类型
				Class re = m.getReturnType();
				String value;
				if (re.getName().equals("int")) { // 如果是int 类型, 则直接添加就行.
					value = ((Integer) m.invoke(obj, null)).toString();
					if (i != gets.size() - 1) {
						values += value + ",";
					} else
						values += value + ")";
				} else if (re.getName().equals("String")) { // 如果是String类型
															// 则要记得加单引号 ' '
					value = (String) m.invoke(obj, null);
					if (i != gets.size() - 1) {
						values += "'" + value + "' ,";
					} else
						values += "'" + value + "' )";
				} else {
					System.out.println("未知的数据类型...  暂时不支持");
				}
			} catch (IllegalArgumentException e1) {
				e1.printStackTrace();
			} catch (IllegalAccessException e1) {
				e1.printStackTrace();
			} catch (InvocationTargetException e1) {
				e1.printStackTrace();
			}
		}
		sql += properties + "values" + values;
		System.out.println("得到的sql语句是:  " + sql);

		// 2. 连接数据库
		Connection conn = dbConn.DBUtil.getConn();
		// 3. 执行sql 语句
		try {
			java.sql.Statement stmt = conn.createStatement();
			int t = stmt.executeUpdate(sql);
			if (t == 1) {
				System.out.println("保存成功!");
				return true;
			} else {
				System.out.println("删除失败!");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		// 4. 返回结果
		return false;
	}

	/**
	 * 删除一个对象的方法
	 */
	public static boolean delete(int id, Class c) {

		// 1.拼凑一条 保存的sql语句 delete from 类名 where id = id ;
		String sql = "delete from ";
		// 得到类名 也就是表名
		String cName = c.getName();
		sql += cName.substring(cName.lastIndexOf(".") + 1, cName.length());
		sql += " where id = " + id;
		System.out.println("得到的sql语句是:  " + sql);

		// 2. 连接数据库
		Connection conn = dbConn.DBUtil.getConn();
		// 3. 执行sql 语句
		try {
			java.sql.Statement stmt = conn.createStatement();
			int i = stmt.executeUpdate(sql);
			if (i == 1) {
				System.out.println("删除成功!");
				return true;
			} else {
				System.out.println("删除失败!");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		// 4. 返回结果
		return false;
	}

	/**
	 * 修改一个对象的信息的方法
	 */
	public static boolean modify(Object obj) {

		// 1.拼凑一条 保存的sql语句
		String sql = "update ";
		int id = 0;
		// 得到对象的类
		Class c = obj.getClass();
		// 得到类名 也就是表名
		String cName = c.getName();
		sql += cName.substring(cName.lastIndexOf(".") + 1, cName.length());
		sql += " set ";
		// 得到类中的所有方法的队列
		java.lang.reflect.Method[] methods = c.getMethods();

		List<Method> gets = new ArrayList<Method>();
		for (Method m : methods) {
			String s = m.getName();
			System.out.println("--->方法名:" + s);

			// 判断是否为 get 方法 而且 不是getClass 方法
			if (s.startsWith("get") && !s.equals("getClass")) {
				try {
					// 先判断属性值 是否为null或者初始值"0" , 如果是 , 则没必要继续写入语句
					if (m.invoke(obj, null) != null
							&& !m.invoke(obj, null).equals(0)) {
						gets.add(m);
						System.out.println("------>方法名:" + s);
					}
				} catch (IllegalArgumentException e1) {
					e1.printStackTrace();
				} catch (IllegalAccessException e1) {
					e1.printStackTrace();
				} catch (InvocationTargetException e1) {
					e1.printStackTrace();
				}
			}
		}
		for (int i = 0; i < gets.size(); i++) {
			Method m = gets.get(i);

			try {
				// 如果是 getId 方法. 则得到id.
				if (m.getName().equalsIgnoreCase("getId")) {
					id = (Integer) m.invoke(obj, null);
				} else {
					String s = m.getName();
					// 得到属性名 即get后面的字符串
					String fName = s.substring(3, s.length());
					sql += fName + "=";

					// 执行get方法
					// 判断get方法的返回类型
					Class re = m.getReturnType();
					String value;
					if (re.getName().equals("int")) { // 如果是int 类型, 则直接添加就行.
						value = ((Integer) m.invoke(obj, null)).toString();
						if (i != gets.size() - 1) {
							sql += value + ",";
						} else
							sql += value;
					} else { // 如果是String类型 则要记得加单引号 ' '
						value = (String) m.invoke(obj, null).toString();
						if (i != gets.size() - 1) {
							sql += "'" + value + "' ,";
						} else
							sql += "'" + value + "'";
					}
				}
			} catch (IllegalArgumentException e1) {
				e1.printStackTrace();
			} catch (IllegalAccessException e1) {
				e1.printStackTrace();
			} catch (InvocationTargetException e1) {
				e1.printStackTrace();
			}
		}
		sql += " where id = " + id;
		System.out.println("得到的sql语句是:  " + sql);

		// 2. 连接数据库
		Connection conn = dbConn.DBUtil.getConn();
		// 3. 执行sql 语句
		try {
			java.sql.Statement stmt = conn.createStatement();
			int i = stmt.executeUpdate(sql);
			if (i == 1) {
				System.out.println("更改信息成功!");
				return true;
			} else {
				System.out.println("更改信息失败!");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		// 4. 返回结果
		return false;

	}

	/**
	 * 根据一个模板来查找对象 可以理解成为多条件查找. eg: 查找 age=20, name="Lilei" 的用户
	 * 
	 * @param obj
	 */
	public static List selectBySample(Object obj) {

		// 即将返回的 队列....
		List list = new ArrayList();

		String sql = "select * from ";
		Class c = obj.getClass();
		String cName = c.getName();
		sql += cName.substring(cName.lastIndexOf(".") + 1, cName.length())
				+ " where ";

		// 得到类中的所有方法的队列
		java.lang.reflect.Method[] methods = c.getMethods();

		List<Method> gets = new ArrayList<Method>();
		List<Method> sets = new ArrayList<Method>();
		for (Method m : methods) {
			String s = m.getName();
			if (s.startsWith("set")) {
				// 添加 set 方法进入队列
				sets.add(m);
				System.out.println("--- >set方法名:" + s);
				String field = s.substring(3);
				for (Method sm : methods) {
					if (sm.getName().equals("get" + field)) {
						// 添加 get 方法 进入队列
						gets.add(sm);
						System.out.println("------>get方法名:" + sm.getName());
					}
				}
			}
		}
		for (int i = 0; i < gets.size(); i++) {
			Method get = gets.get(i);
			try {
				// 先判断 sample里面的非初始化的值
				if (get.invoke(obj, null) != null
						&& !get.invoke(obj, null).equals(0)) {
					String name = get.getName();
					// 得到属性名 即get后面的字符串
					String fName = name.substring(3, name.length());

					// 执行get方法
					// 判断get方法的返回类型
					Class re = get.getReturnType();
					String value;
					if (re.getName().equals("int")) { // 如果是int 类型, 则直接添加就行.
						value = ((Integer) get.invoke(obj, null)).toString();
						sql += fName + "="; // 如果是 int 型, 则用"=" 连接
						sql += value + " and ";
					} else { // 如果是String类型 则要记得加单引号 ' '
						value = (String) get.invoke(obj, null).toString();
						sql += fName + " like "; // 如果是 string 型, 则用"=" 连接
						sql += "'%" + value + "%' and ";
					}
				}
			} catch (IllegalArgumentException e1) {
				e1.printStackTrace();
			} catch (IllegalAccessException e1) {
				e1.printStackTrace();
			} catch (InvocationTargetException e1) {
				e1.printStackTrace();
			}
		}
		// 输出sql语句 测试 记得去掉最后的 "and" 三个字符
		sql = sql.substring(0, sql.length() - 4);
		System.out.println("得到的sql 语句是: " + sql);

		// 执行sql 语句
		Connection conn = dbConn.DBUtil.getConn();
		try {
			java.sql.Statement stmt = conn.createStatement();
			java.sql.ResultSet rs = stmt.executeQuery(sql);
			while (rs.next()) {
				// 创建这个类型的新对象
				Object o = c.newInstance();

				// 给这个对象 设置属性. 赋值
				for (int i = 0; i < sets.size(); i++) {
					Method set = sets.get(i);
					Method getM = gets.get(i);
					// 得到set 方法名字 eg: setAge
					String mName = set.getName();
					System.out.println("得到的set 方法是: " + mName);
					// 得到属性名字 eg: Age --> age
					String fName = mName.substring(3, 4).toLowerCase()
							+ mName.substring(4);
					Class re = getM.getReturnType();
					System.out.println("set方法返回类型是: " + re.getName());
					if (re.getName().equals("int")) { // 如果是int 类型
						int param = rs.getInt(fName);
						System.out.println(" rs 得到的是: " + param);
						set.invoke(o, param);
					} else if (re.getName().equals("java.lang.String")) { // 如果是String类型
						String param = rs.getString(fName);
						if (param != null) { // 如果rs得到的不是null
							set.invoke(o, param);
						}
					} else if (re.getName().equals("java.sql.Date")) {
						Date param = rs.getDate(fName);
						if (param != null) { // 如果rs得到的不是null
							set.invoke(o, param);
						}
					}
				}

				// 把对象加入 队列中...
				list.add(o);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * 查找某一个类型的所有对象. select * from 表名;
	 * 
	 * @return : 对象的队列
	 */
	public static List selectAll(Class c) {

		// 即将返回的 队列....
		List list = new ArrayList();

		String sql = "select * from ";
		String cName = c.getName();
		sql += cName.substring(cName.lastIndexOf(".") + 1);

		// 得到类中的所有方法的队列
		java.lang.reflect.Method[] methods = c.getMethods();

		List<Method> gets = new ArrayList<Method>();
		List<Method> sets = new ArrayList<Method>();
		for (Method m : methods) {
			String s = m.getName();
			if (s.startsWith("set")) {
				// 添加 set 方法进入队列
				sets.add(m);
				System.out.println("--- >set方法名:" + s);
				String field = s.substring(3);
				for (Method sm : methods) {
					if (sm.getName().equals("get" + field)) {
						// 添加 get 方法 进入队列
						gets.add(sm);
						System.out.println("------>get方法名:" + sm.getName());
					}
				}
			}
		}

		// 输出sql语句 测试
		System.out.println("得到的sql 语句是: " + sql);

		// 执行sql 语句
		Connection conn = dbConn.DBUtil.getConn();
		try {
			java.sql.Statement stmt = conn.createStatement();
			java.sql.ResultSet rs = stmt.executeQuery(sql);
			while (rs.next()) {
				// 创建这个类型的新对象
				Object o = c.newInstance();

				// 给这个对象 设置属性. 赋值
				for (int i = 0; i < sets.size(); i++) {
					Method set = sets.get(i);
					Method getM = gets.get(i);
					// 得到set 方法名字 eg: setAge
					String mName = set.getName();
					System.out.println("得到的set 方法是: " + mName);
					// 得到属性名字 eg: Age --> age
					String fName = mName.substring(3, 4).toLowerCase()
							+ mName.substring(4);
					Class re = getM.getReturnType();
					System.out.println("set方法返回类型是: " + re.getName());
					if (re.getName().equals("int")) { // 如果是int 类型
						int param = rs.getInt(fName);
						System.out.println(" rs 得到的是: " + param);
						set.invoke(o, param);
					} else if (re.getName().equals("java.lang.String")) { // 如果是String类型
						String param = rs.getString(fName);
						if (param != null) { // 如果rs得到的不是null
							set.invoke(o, param);
						}
					} else if (re.getName().equals("java.sql.Date")) {
						Date param = rs.getDate(fName);
						if (param != null) { // 如果rs得到的不是null
							set.invoke(o, param);
						}
					}
				}

				// 把对象加入 队列中...
				list.add(o);
			}
		} catch (IllegalArgumentException e1) {
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
			e1.printStackTrace();
		} catch (InvocationTargetException e1) {
			e1.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * 通过唯一的 主键 id 查找对象的方法
	 * 
	 * @param id
	 *            : id
	 * @param c
	 *            : 要查找的类型
	 * @return : 返回对象
	 */
	public static Object selectById(int id, Class c) {
		String sql = "select * from ";
		String cName = c.getName();
		sql += cName.substring(cName.lastIndexOf(".") + 1) + " where id = "
				+ id;

		// 得到类中的所有方法的队列
		java.lang.reflect.Method[] methods = c.getMethods();

		List<Method> gets = new ArrayList<Method>();
		List<Method> sets = new ArrayList<Method>();
		for (Method m : methods) {
			String s = m.getName();
			if (s.startsWith("set")) {
				// 添加 set 方法进入队列
				sets.add(m);
				System.out.println("--- >set方法名:" + s);
				String field = s.substring(3);
				for (Method sm : methods) {
					if (sm.getName().equals("get" + field)) {
						// 添加 get 方法 进入队列
						gets.add(sm);
						System.out.println("------>get方法名:" + sm.getName());
					}
				}
			}
		}

		// 输出sql语句 测试
		System.out.println("得到的sql 语句是: " + sql);

		// 执行sql 语句
		Connection conn = dbConn.DBUtil.getConn();
		try {
			java.sql.Statement stmt = conn.createStatement();
			java.sql.ResultSet rs = stmt.executeQuery(sql);
			while (rs.next()) {
				// 创建这个类型的新对象
				Object o = c.newInstance();

				// 给这个对象 设置属性. 赋值
				for (int i = 0; i < sets.size(); i++) {
					Method set = sets.get(i);
					Method getM = gets.get(i);
					// 得到set 方法名字 eg: setAge
					String mName = set.getName();
					System.out.println("得到的set 方法是: " + mName);
					// 得到属性名字 eg: Age --> age
					String fName = mName.substring(3, 4).toLowerCase()
							+ mName.substring(4);
					Class re = getM.getReturnType();
					System.out.println("set方法返回类型是: " + re.getName());
					if (re.getName().equals("int")) { // 如果是int 类型
						int param = rs.getInt(fName);
						System.out.println(" rs 得到的是: " + param);
						set.invoke(o, param);
					} else if (re.getName().equals("java.lang.String")) { // 如果是String类型
						String param = rs.getString(fName);
						if (param != null) { // 如果rs得到的不是null
							set.invoke(o, param);
						}
					} else if (re.getName().equals("java.sql.Date")) {
						Date param = rs.getDate(fName);
						if (param != null) { // 如果rs得到的不是null
							set.invoke(o, param);
						}
					}
				}
				return o;
			}
		} catch (IllegalArgumentException e1) {
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
			e1.printStackTrace();
		} catch (InvocationTargetException e1) {
			e1.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		}
		return null;
	}
}

 

 

 

 

 

      

分享到:
评论
1 楼 hold_on 2010-11-16  

相关推荐

    看我山寨版 hibernate 简单实现 一

    NULL 博文链接:https://skymr.iteye.com/blog/728685

    山寨版当当网 struts+hibernate

    山寨版当当网 struts+hibernate

    山寨qq,java开发,使用hibernate

    使用java和hibernate做到山寨qq

    java Struts+hibernate实现的山寨版当当网系统

    实现了网上购物的基本功能,次系统使用mvc设计模式。通过hibernate访问数据库实现图书的浏览,会员的注册,购物车的管理,订单的管理等

    (sjie)山寨版通用分页

    作品吹牛: ...通用Hibernate Dao 最后真心话! 力行 一个星期完成! 第一次 心血之作 所以望大家体谅给点支持! 好请给予支持,坏请给予批评并且指正! 在次感谢大家的支持。。。 留言QQ:308117229

    电信计费系统(山寨版)

    主要实现了权限部分和资费部分.采用struts2.18+spring2.0+hibernate3.2,因为上传大小限制,里面没有jar包,如果自己没有jar包.可以在我资源里下载

    山寨版--当当网源程序

    本程序是完全模拟当当网而做的网上购物系统,运用了java+jsp+struts+hibernate等技术,开发环境:myelispe,Tomcat,是相关毕业程序的首选!

    myHibernate源码

    自己写的一个hibernate,实现增删查该基本功能 同时也有对hibernate 的原理领悟

    C++实现的泛型List类分享

    有时看算法有时看Unity、Hibernate;有时看Hadoop有时看Redis;现在又开始看C++了。 以前觉得无论什么语言嘛,其实都差不多,核心思想基本一致。现在又不这么想了,其实语言的选择对软件的性能、可靠性、开发成本之...

    Spring 3.x 中文开发手册.pdf

    Spring 3.x 新特性全部介绍 ...我自己也曾经仿造者,并且基于aspectj山寨过过aop annotation cache 在大部分简单的cache场景都是非常好用的 少部分需要精确evict key的场景还不适合 具体可以参考 ...

    JAVA上百实例源码以及开源项目

     Java编写的山寨QQ,多人聊天+用户在线,程序分服务端和客户端,典型C/S结构,  当用户发送第一次请求的时候,验证用户登录,创建一个该qq号和服务器端保持通讯连接得线程,启动该通讯线程,通讯完毕,关闭Scoket...

    JAVA上百实例源码以及开源项目源代码

     Java编写的山寨QQ,多人聊天+用户在线,程序分服务端和客户端,典型C/S结构,  当用户发送第一次请求的时候,验证用户登录,创建一个该qq号和服务器端保持通讯连接得线程,启动该通讯线程,通讯完毕,关闭Scoket...

    java源码包---java 源码 大量 实例

     Java编写的山寨QQ,多人聊天+用户在线,程序分服务端和客户端,典型C/S结构,  当用户发送第一次请求的时候,验证用户登录,创建一个该qq号和服务器端保持通讯连接得线程,启动该通讯线程,通讯完毕,关闭Scoket...

    java源码包2

     Java编写的山寨QQ,多人聊天+用户在线,程序分服务端和客户端,典型C/S结构,  当用户发送第一次请求的时候,验证用户登录,创建一个该qq号和服务器端保持通讯连接得线程,启动该通讯线程,通讯完毕,关闭Scoket...

    java源码包3

     Java编写的山寨QQ,多人聊天+用户在线,程序分服务端和客户端,典型C/S结构,  当用户发送第一次请求的时候,验证用户登录,创建一个该qq号和服务器端保持通讯连接得线程,启动该通讯线程,通讯完毕,关闭Scoket...

    java源码包4

     Java编写的山寨QQ,多人聊天+用户在线,程序分服务端和客户端,典型C/S结构,  当用户发送第一次请求的时候,验证用户登录,创建一个该qq号和服务器端保持通讯连接得线程,启动该通讯线程,通讯完毕,关闭Scoket...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    Java编写的山寨QQ,多人聊天+用户在线 21个目标文件 摘要:JAVA源码,媒体网络,山寨QQ,Java聊天程序 Java编写的山寨QQ,多人聊天+用户在线,程序分服务端和客户端,典型C/S结构, 当用户发送第一次请求的时候,验证...

Global site tag (gtag.js) - Google Analytics