diff --git a/.gitignore b/.gitignore index 524f096..25af9ec 100644 --- a/.gitignore +++ b/.gitignore @@ -10,15 +10,6 @@ # Mobile Tools for Java (J2ME) .mtj.tmp/ -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* replay_pid* diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e31b6e0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "java.project.sourcePaths": [ + "src" + ], + "java.project.outputPath": "bin", + "java.project.referencedLibraries": [ + "lib/**/*.jar" + ] +} \ No newline at end of file diff --git a/lib/gson-2.11.0.jar b/lib/gson-2.11.0.jar new file mode 100644 index 0000000..18e59c8 Binary files /dev/null and b/lib/gson-2.11.0.jar differ diff --git a/lib/jsoup-1.17.2.jar b/lib/jsoup-1.17.2.jar new file mode 100644 index 0000000..52ae16d Binary files /dev/null and b/lib/jsoup-1.17.2.jar differ diff --git a/lib/jxl-2.6.12.jar b/lib/jxl-2.6.12.jar new file mode 100644 index 0000000..4a1fc64 Binary files /dev/null and b/lib/jxl-2.6.12.jar differ diff --git a/lib/mysql-connector-j-8.4.0.jar b/lib/mysql-connector-j-8.4.0.jar new file mode 100644 index 0000000..8294fe0 Binary files /dev/null and b/lib/mysql-connector-j-8.4.0.jar differ diff --git a/src/client/Client.java b/src/client/Client.java new file mode 100644 index 0000000..ddb163f --- /dev/null +++ b/src/client/Client.java @@ -0,0 +1,179 @@ +package client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Socket; +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import server.vo.User; + +public class Client { + + // 多个函数共享的数据可以定义为全局的 + public static Scanner scan = new Scanner(System.in); // 控制台输入 + public static Socket socket; // 建立连接后的套接字对象 + public static BufferedReader buf; // 字符输入流 + public static PrintWriter write; // 字符输出流 + public static User currentUser; // 当前登录用户 + + // 主方法 + public static void main(String[] args) throws Exception, IOException { + String ip = "127.0.0.1"; // 服务器IP + int port = 1234; // 服务器程序的端口 + // 1.建立与服务器的连接 + socket = new Socket(ip, port); + // 获取输入流 + InputStream is = socket.getInputStream(); + buf = new BufferedReader(new InputStreamReader(is, "utf-8")); + // 获取输出流 + OutputStream os = socket.getOutputStream(); + write = new PrintWriter(new OutputStreamWriter(os, "utf-8")); + // 2.用户登录 + if (!login()) { // 登录失败,退出程序 + System.out.println("登录失败,欢迎下次访问"); + System.exit(0); + } + // 登录成功,显示程序主界面 + int choose = menu(); + while (choose != 8) { // 不是退出 + switch (choose) { + case 1: // 修改密码 + updatepassword(); + break; + case 2:// 修改密码 + + break; + case 3:// 增加数据:显示二级菜单 + + break; + default: + break; + } + choose = menu(); // 执行完毕,重新显示主菜单,并选择 + } + // 输入选择=8,退出 + close(); + System.out.println("您已退出程序,欢迎下次使用!"); + } + + // 选择退出时,先向服务器发送“退出请求:code=8”,然后关闭连接 + public static void close() throws Exception { + Map map = new HashMap<>(); + map.put("code", 8); + String sendData = new Gson().toJson(map); // 将java的map对象直接转换成json字符串 + System.out.println("发送给服务器:" + sendData); + write.println(sendData); + write.flush(); + if (write != null) { + write.close(); + } + if (buf != null) { + buf.close(); + } + if (socket != null) { + socket.close(); + } + } + + // 绘制流程图,按流程图书写 + public static boolean login() throws Exception { + for (int i = 1; i <= 3; i++) { + // 1.输入用户名,密码:所有输入均应该先给输入提示 + System.out.println("请输入用户名:"); + String userName = scan.nextLine(); + System.out.println("请输入密码:"); + String passsord = scan.nextLine(); + // 可以使用GSON包非常方便的将java类型的数据转成json字符串,或者从json字符串中获取相关的数据,见教案p129 + // 封装发送的数据:如登录请求的数据格式可以为"{code:0,data:{userName:***,password:***}}" + Map map = new HashMap<>(); + map.put("code", 0); + User user = new User(); + user.setUserName(userName); + user.setPassword(passsord); + Gson gson = new Gson(); + map.put("data", gson.toJson(user)); // toJson方法可以将java的vo对象直接转换成json字符串 + String sendData = gson.toJson(map); // 将java的map对象直接转换成json字符串 + System.out.println("发送给服务器:" + sendData); + /** + * 2.发送数据并接收服务器返回的数据(返回数据也有格式,如可以是以下格式: + * code:0或1,data:**** + * code=0表示登录失败,data中存放失败原因 + * code=1表示登录成功,data中放当前用户相关的信息(用户名,姓名,角色等) + */ + String responseData = send(sendData); + System.out.println("接收到服务器端的响应:" + responseData); + // 4.解析返回的字符串 + JsonElement element = JsonParser.parseString(responseData); // 使用parseString方法将json字符串转换为JsonElement对象 + JsonObject obj = element.getAsJsonObject(); // 将JsonElement对象转换为JsonObject对象 + int returnCode = obj.get("code").getAsInt(); // 获取code属性 + String returnData = obj.get("data").getAsString(); // 获取data属性 + if (returnCode == 0) { // 登录失败 + System.out.println("登录失败:" + returnData); + } else { // 登录成功,returnData中存放的是当前用户的json字符串 + currentUser = gson.fromJson(returnData, User.class); // 使用fromJson方法可以将json字符串直接转换为指定类型的对象 + return true; + } + + } + + return false; + + } + + // 显示操作界面,返回用户的选择1,2,..... + public static int menu() { + System.out.println("======新闻管理系统======="); + System.out.println("作者:****&******"); + System.out.println("当前用户:" + currentUser.getName()); + System.out.println("1.密码修改"); + System.out.println("2.增加数据"); // 需要增加二级菜单:【键盘录入,网页爬取,txt文件导入,xls文件导入】 + System.out.println("3.修改数据"); // 按key修改其他字段 + System.out.println("4.删除数据"); // 按key删除记录 + System.out.println("5.查询数据"); // 需要增加二级菜单,【自动设计查询条件】 + System.out.println("6.统计数据"); // 需要增加二级菜单,【自行设计统计条件】 + System.out.println("7.导出数据至文件"); // 需要增加二级菜单:【导出至txt,导出至xls】 + System.out.println("8.退出"); + + System.out.println("请输入选项(1-8):"); + int choose = scan.nextInt(); + + return choose; + } + + // 将指定的字符串发送给服务器,并接收服务器返回的数据 + public static String send(String data) throws Exception { + // 发送数据 + write.println(data); + write.flush(); + // 接收数据 + String response = buf.readLine(); + return response; + } + + // 修改密码 + public static void updatepassword() { + + } + + // 从键盘输入 + public static void inputFromKeyboard() { + + } + + // 将电子表格文件编码为base64形式的字符串进行传输 + public static void importFromXLS() { + + } +} diff --git a/src/server/Server.java b/src/server/Server.java new file mode 100644 index 0000000..b92c588 --- /dev/null +++ b/src/server/Server.java @@ -0,0 +1,25 @@ +package server; + +import java.net.ServerSocket; +import java.net.Socket; + +import server.thread.HandleThread; + +public class Server { + + public static void main(String[] args) throws Exception { + // 创建服务器 + int port = 1234; + ServerSocket server = new ServerSocket(port); + System.out.println("服务器正在1234端口侦听客户端请求"); + // 循环等待客户端请求 + while (true) { + Socket socket = server.accept(); + System.out.println("客户端" + socket.getInetAddress().getHostAddress() + "成功连接"); + // 新建一个线程来处理该处理该请求(实现并发) + new HandleThread(socket).start(); + } + + } + +} diff --git a/src/server/dao/UserDAO.java b/src/server/dao/UserDAO.java new file mode 100644 index 0000000..26187d5 --- /dev/null +++ b/src/server/dao/UserDAO.java @@ -0,0 +1,64 @@ +package server.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; + +import server.tools.DBConnection; +import server.vo.User; + +public class UserDAO { + // 按关键字进行查询,返回查询结果(vo对象,因为查询结果最多一条),没有查询到,则返回null + public static User get(String userName) throws Exception { + User user = null; + // 获取连接 + Connection con = DBConnection.getConnection(); + // 操作对应sql语句,支持参数 + String sql = "select * from t_users where userName=?"; + // 创建语句对象 + PreparedStatement pst = con.prepareStatement(sql); + // 对sql语句的?参数进行赋值 + pst.setString(1, userName); + // 执行select查询语句,如果sql语句是insert,update或delete,则需调用executeUpdate进行执行 + ResultSet rs = pst.executeQuery(); + // 将记录集转换为vo对象 + while (rs.next()) { + user = new User(); + user.setUserName(rs.getString("userName")); + user.setPassword(rs.getString("password")); + user.setName(rs.getString("name")); + user.setRole(rs.getString("role")); + } + // 关闭连接对象 + DBConnection.close(con, pst); + return user; + } + + // 按任意条件组合查询,将查询结果存放在集合中【因为可能有多条】 + public static ArrayList query(User userCondition) throws Exception { + ArrayList list = new ArrayList(); + // 获取连接 + Connection con = DBConnection.getConnection(); + // 操作对应sql语句 + String sql = "*******"; + // 创建语句对象 + PreparedStatement pst = con.prepareStatement(sql); + // 执行select查询语句,如果sql语句是insert,update或delete,则需调用executeUpdate进行执行 + ResultSet rs = pst.executeQuery(); + // 将记录集转换为vo对象 + while (rs.next()) { + User user = new User(); + user.setUserName(rs.getString("userName")); + user.setPassword(rs.getString("password")); + user.setName(rs.getString("name")); + user.setRole(rs.getString("role")); + list.add(user); // 将对象增加到集合中 + } + // 关闭连接对象 + DBConnection.close(con, pst); + + return list; + } + +} diff --git a/src/server/thread/HandleThread.java b/src/server/thread/HandleThread.java new file mode 100644 index 0000000..c7b5867 --- /dev/null +++ b/src/server/thread/HandleThread.java @@ -0,0 +1,135 @@ +package server.thread; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Socket; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import server.dao.UserDAO; +import server.tools.Encoding; +import server.vo.User; + +public class HandleThread extends Thread { + private Socket socket; + private BufferedReader buf; // 字符输入流 + private PrintWriter write; // 字符输出流 + + // 构造方法 + public HandleThread(Socket socket) { + super(); + this.socket = socket; + try { + // 获取输入流 + InputStream is = socket.getInputStream(); + buf = new BufferedReader(new InputStreamReader(is, "utf-8")); + // 获取输出流 + OutputStream os = socket.getOutputStream(); + write = new PrintWriter(new OutputStreamWriter(os, "utf-8")); + } catch (Exception e) { + // TODO: handle exception + } + + } + + // 具体的请求处理:线程执行start方法时自动调用 + @Override + public void run() { + while (true) { // 循环接收客户端发送过来的数据 + try { + // 接收客户端发送的json字符串 + String receiveStr = buf.readLine(); + System.out.println("接收到客户端的请求数据:" + receiveStr); + // 按协议解析字符串,如:code = 0,表示的是登录请求 + JsonElement element = JsonParser.parseString(receiveStr); // 使用parseString方法将json字符串转换为JsonElement对象 + JsonObject obj = element.getAsJsonObject(); // 将JsonElement对象转换为JsonObject对象 + int code = obj.get("code").getAsInt(); // 获取code属性 + if (code == 8) { // 客户端退出 + close(); + break; + } + String data = obj.get("data").getAsString(); // 获取data属性 + String response = ""; + switch (code) { + case 0: // 登录请求 + response = loginHandle(data); // 登录请求处理,data中存放的是输入的用户名和密码 + break; + case 1: + + break; + case 2: + break; + default: + System.out.println("命令无效!"); + break; + } + // 向客户端发送响应数据 + write.println(response); + write.flush(); + + } catch (Exception e) { + // TODO: handle exception + } + + } + + System.out.println("客户端退出!"); + + } + + // 客户端选择退出时,关闭连接 + public void close() throws Exception { + if (write != null) { + write.close(); + } + if (buf != null) { + buf.close(); + } + if (socket != null) { + socket.close(); + } + } + + public String loginHandle(String str) throws Exception { + // 解析json字符串,str中的存放的是输入的用户名,密码信息的json格式字符串,使用Gson包将其直接转换为User对象 + User loginUser = new Gson().fromJson(str, User.class); + // 调用DAO,按用户名查询数据库,返回查询结果 + User user = UserDAO.get(loginUser.getName()); + /** + * 根据dao执行结果,给出相应的响应,需要设计响应字符串的协议格式 如可以这样设计:*{code:0 + * 1,data:****} + * code=0表示登录失败,data中存放失败原因 code= + * 表示登录成功,data中放当前用户相关的信息(用户名,姓名,角色等) + */ + String responseData = ""; + if (user == null) { // 登录失败,原因:表示的用户不存在 + Map map = new HashMap<>(); + map.put("code", 0); + map.put("data", "用户名不存在"); + responseData = new Gson().toJson(map); // 将java的map对象直接转换成json字符串 + } else { // 有该用户,进一步密码是否正确 + if (Encoding.md5(loginUser.getPassword()).equals(user.getPassword())) { // 用户名密码正确 + Map map = new HashMap<>(); + map.put("code", 1); + map.put("data", new Gson().toJson(user)); // 使用toJson方法可以将java的vo对象直接转换成json字符串 + responseData = new Gson().toJson(map); // 将java的map对象直接转换成json字符串 + } else { // 密码不正确 + Map map = new HashMap<>(); + map.put("code", 0); + map.put("data", "密码错误"); + responseData = new Gson().toJson(map); // 将java的map对象直接转换成json字符串 + } + } + return responseData; + } + +} diff --git a/src/server/tools/DBConnection.java b/src/server/tools/DBConnection.java new file mode 100644 index 0000000..6f523fd --- /dev/null +++ b/src/server/tools/DBConnection.java @@ -0,0 +1,26 @@ +package server.tools; + +import java.sql.Connection; +import java.sql.PreparedStatement; + +public class DBConnection { + private String driverName; + private String url; + private String user; + private String password; + + // 加载驱动 + static { + + } + + public static Connection getConnection() { + + return null; + } + + public static void close(Connection con, PreparedStatement pst) { + + } + +} diff --git a/src/server/tools/Encoding.java b/src/server/tools/Encoding.java new file mode 100644 index 0000000..232a7f6 --- /dev/null +++ b/src/server/tools/Encoding.java @@ -0,0 +1,20 @@ +package server.tools; + +public class Encoding { + // 对指定的字符串进行md5编码 + public static String md5(String password) { + + return ""; + } + + // 将指定的文件进行base64编码,返回编码字符串 + public static String base64FromFile(String filePath) { + return ""; + } + + // 将base64编码字符串还原为文件,文件路径及文件名为filePath + public static String base64ToFile(String base64Str, String filePath) { + return ""; + } + +} diff --git a/src/server/vo/User.java b/src/server/vo/User.java new file mode 100644 index 0000000..a8512cd --- /dev/null +++ b/src/server/vo/User.java @@ -0,0 +1,50 @@ +package server.vo; + +public class User { + private String userName; + private String password; + private String name; + private String role; + + public User() { + super(); + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + @Override + public String toString() { + return userName + "\\t" + password + "\\t" + name + "\\t" + role; + } + +}