Java学习第7天 - 网络编程与数据库操作

学习时间: 4-5小时
学习目标: 掌握Java网络编程基础和数据库连接操作,为后端开发打基础


📋 详细学习清单

✅ 第一部分:网络编程基础(Socket编程)(90分钟)

1. 网络编程与JavaScript对比

JavaScript (你熟悉的网络操作)

javascript 复制代码
// JavaScript 客户端网络请求
// 1. Fetch API
async function getData() {
    try {
        const response = await fetch('http://localhost:8080/api/users', {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer token123'
            }
        });
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const data = await response.json();
        console.log('获取数据:', data);
        return data;
    } catch (error) {
        console.error('请求失败:', error);
    }
}

// 2. WebSocket 客户端
const ws = new WebSocket('ws://localhost:8080/websocket');

ws.onopen = function() {
    console.log('WebSocket连接已打开');
    ws.send('Hello Server!');
};

ws.onmessage = function(event) {
    console.log('收到消息:', event.data);
};

ws.onclose = function() {
    console.log('WebSocket连接已关闭');
};

Java (今天学习的网络编程)

java 复制代码
// SocketBasics.java - Socket基础概念
import java.net.*;
import java.io.*;

/**
 * Java网络编程基础
 * Socket = IP地址 + 端口号
 */
public class SocketBasics {
    public static void main(String[] args) {
        System.out.println("=== Java网络编程基础概念 ===");
        
        // 1. 获取本机网络信息
        try {
            InetAddress localhost = InetAddress.getLocalHost();
            System.out.println("本机主机名: " + localhost.getHostName());
            System.out.println("本机IP地址: " + localhost.getHostAddress());
            
            // 获取指定域名的IP
            InetAddress googleAddress = InetAddress.getByName("www.google.com");
            System.out.println("Google IP: " + googleAddress.getHostAddress());
            
        } catch (UnknownHostException e) {
            System.err.println("网络错误: " + e.getMessage());
        }
    }
}

2. TCP服务器端编程

java 复制代码
// SimpleServer.java - 简单的TCP服务器
import java.net.*;
import java.io.*;

public class SimpleServer {
    private static final int PORT = 8888;
    
    public static void main(String[] args) {
        System.out.println("=== TCP服务器启动 ===");
        
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("服务器正在监听端口: " + PORT);
            
            // 等待客户端连接
            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("客户端连接: " + clientSocket.getInetAddress());
                
                // 处理客户端请求(简单版本)
                handleClient(clientSocket);
            }
            
        } catch (IOException e) {
            System.err.println("服务器错误: " + e.getMessage());
        }
    }
    
    private static void handleClient(Socket clientSocket) {
        try (
            BufferedReader input = new BufferedReader(
                new InputStreamReader(clientSocket.getInputStream())
            );
            PrintWriter output = new PrintWriter(
                clientSocket.getOutputStream(), true
            )
        ) {
            // 读取客户端消息
            String clientMessage = input.readLine();
            System.out.println("收到消息: " + clientMessage);
            
            // 发送响应
            String response = "服务器收到: " + clientMessage;
            output.println(response);
            
            System.out.println("响应已发送: " + response);
            
        } catch (IOException e) {
            System.err.println("处理客户端错误: " + e.getMessage());
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                System.err.println("关闭连接错误: " + e.getMessage());
            }
        }
    }
}

3. TCP客户端编程

java 复制代码
// SimpleClient.java - 简单的TCP客户端
import java.net.*;
import java.io.*;

public class SimpleClient {
    private static final String SERVER_HOST = "localhost";
    private static final int SERVER_PORT = 8888;
    
    public static void main(String[] args) {
        System.out.println("=== TCP客户端启动 ===");
        
        try (
            Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
            PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader input = new BufferedReader(
                new InputStreamReader(socket.getInputStream())
            )
        ) {
            System.out.println("已连接到服务器: " + SERVER_HOST + ":" + SERVER_PORT);
            
            // 发送消息到服务器
            String message = "Hello, 这是来自Java客户端的消息!";
            output.println(message);
            System.out.println("发送消息: " + message);
            
            // 接收服务器响应
            String response = input.readLine();
            System.out.println("服务器响应: " + response);
            
        } catch (IOException e) {
            System.err.println("客户端错误: " + e.getMessage());
        }
    }
}

4. 实战练习:多线程聊天服务器

java 复制代码
// ChatServer.java - 支持多客户端的聊天服务器
import java.net.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;

public class ChatServer {
    private static final int PORT = 9999;
    private static Set<ClientHandler> clients = ConcurrentHashMap.newKeySet();
    
    public static void main(String[] args) {
        System.out.println("=== 聊天服务器启动 ===");
        
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("聊天服务器监听端口: " + PORT);
            
            while (true) {
                Socket clientSocket = serverSocket.accept();
                ClientHandler clientHandler = new ClientHandler(clientSocket);
                clients.add(clientHandler);
                
                // 每个客户端用独立线程处理
                new Thread(clientHandler).start();
                
                System.out.println("新客户端连接,当前在线: " + clients.size());
            }
            
        } catch (IOException e) {
            System.err.println("聊天服务器错误: " + e.getMessage());
        }
    }
    
    // 广播消息给所有客户端
    public static void broadcast(String message, ClientHandler sender) {
        System.out.println("广播消息: " + message);
        
        Iterator<ClientHandler> iterator = clients.iterator();
        while (iterator.hasNext()) {
            ClientHandler client = iterator.next();
            if (client != sender && client.isConnected()) {
                client.sendMessage(message);
            } else if (!client.isConnected()) {
                iterator.remove(); // 移除已断开的客户端
            }
        }
    }
    
    public static void removeClient(ClientHandler client) {
        clients.remove(client);
        System.out.println("客户端断开连接,当前在线: " + clients.size());
    }
}

// ClientHandler.java - 客户端处理器
class ClientHandler implements Runnable {
    private Socket socket;
    private BufferedReader input;
    private PrintWriter output;
    private String clientName;
    private boolean connected = true;
    
    public ClientHandler(Socket socket) {
        this.socket = socket;
        try {
            input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            output = new PrintWriter(socket.getOutputStream(), true);
        } catch (IOException e) {
            System.err.println("客户端处理器初始化错误: " + e.getMessage());
        }
    }
    
    @Override
    public void run() {
        try {
            // 获取客户端名称
            output.println("请输入您的昵称:");
            clientName = input.readLine();
            
            if (clientName == null || clientName.trim().isEmpty()) {
                clientName = "匿名用户" + socket.getPort();
            }
            
            System.out.println("用户 [" + clientName + "] 加入聊天室");
            ChatServer.broadcast("[系统消息] " + clientName + " 加入了聊天室", this);
            
            // 处理客户端消息
            String message;
            while ((message = input.readLine()) != null && connected) {
                if ("bye".equalsIgnoreCase(message.trim())) {
                    break;
                }
                
                String fullMessage = "[" + clientName + "] " + message;
                ChatServer.broadcast(fullMessage, this);
            }
            
        } catch (IOException e) {
            System.err.println("客户端 [" + clientName + "] 连接异常: " + e.getMessage());
        } finally {
            disconnect();
        }
    }
    
    public void sendMessage(String message) {
        if (output != null && connected) {
            output.println(message);
        }
    }
    
    public boolean isConnected() {
        return connected && !socket.isClosed();
    }
    
    private void disconnect() {
        connected = false;
        try {
            if (socket != null && !socket.isClosed()) {
                socket.close();
            }
        } catch (IOException e) {
            System.err.println("关闭连接错误: " + e.getMessage());
        }
        
        ChatServer.removeClient(this);
        if (clientName != null) {
            System.out.println("用户 [" + clientName + "] 离开聊天室");
            ChatServer.broadcast("[系统消息] " + clientName + " 离开了聊天室", this);
        }
    }
}

✅ 第二部分:JDBC数据库编程(100分钟)

1. JDBC基础概念

java 复制代码
// DatabaseBasics.java - JDBC基础概念
import java.sql.*;

/**
 * JDBC (Java Database Connectivity) 基础
 * JDBC是Java连接数据库的标准API
 */
public class DatabaseBasics {
    
    // 数据库连接信息
    private static final String DB_URL = "jdbc:mysql://localhost:3306/testdb";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "password";
    
    public static void main(String[] args) {
        System.out.println("=== JDBC数据库连接基础 ===");
        
        // 1. 加载数据库驱动(现代JDBC会自动加载)
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            System.out.println("MySQL驱动加载成功");
        } catch (ClassNotFoundException e) {
            System.err.println("驱动加载失败: " + e.getMessage());
            return;
        }
        
        // 2. 建立数据库连接
        try (Connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            System.out.println("数据库连接成功!");
            System.out.println("数据库产品: " + connection.getMetaData().getDatabaseProductName());
            System.out.println("数据库版本: " + connection.getMetaData().getDatabaseProductVersion());
            
            // 基本的数据库操作示例
            basicDatabaseOperations(connection);
            
        } catch (SQLException e) {
            System.err.println("数据库连接错误: " + e.getMessage());
        }
    }
    
    private static void basicDatabaseOperations(Connection connection) throws SQLException {
        System.out.println("\n=== 执行基本数据库操作 ===");
        
        // 创建Statement对象
        try (Statement statement = connection.createStatement()) {
            
            // 1. 创建表(如果不存在)
            String createTableSQL = """
                CREATE TABLE IF NOT EXISTS users (
                    id INT AUTO_INCREMENT PRIMARY KEY,
                    name VARCHAR(50) NOT NULL,
                    email VARCHAR(100) UNIQUE,
                    age INT,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
                """;
            statement.executeUpdate(createTableSQL);
            System.out.println("用户表创建成功或已存在");
            
            // 2. 插入数据
            String insertSQL = """
                INSERT INTO users (name, email, age) VALUES 
                ('张三', '[email protected]', 25),
                ('李四', '[email protected]', 30),
                ('王五', '[email protected]', 28)
                """;
            int rowsAffected = statement.executeUpdate(insertSQL);
            System.out.println("插入了 " + rowsAffected + " 条记录");
            
            // 3. 查询数据
            String selectSQL = "SELECT * FROM users ORDER BY id";
            try (ResultSet resultSet = statement.executeQuery(selectSQL)) {
                System.out.println("\n用户列表:");
                System.out.println("ID\t姓名\t邮箱\t\t\t年龄\t创建时间");
                System.out.println("----------------------------------------------------");
                
                while (resultSet.next()) {
                    int id = resultSet.getInt("id");
                    String name = resultSet.getString("name");
                    String email = resultSet.getString("email");
                    int age = resultSet.getInt("age");
                    Timestamp createdAt = resultSet.getTimestamp("created_at");
                    
                    System.out.printf("%d\t%s\t%s\t\t%d\t%s%n", 
                        id, name, email, age, createdAt);
                }
            }
        }
    }
}

2. PreparedStatement安全操作

java 复制代码
// DatabaseSecurity.java - 安全的数据库操作
import java.sql.*;
import java.util.*;

public class DatabaseSecurity {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/testdb";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "password";
    
    public static void main(String[] args) {
        System.out.println("=== 安全的数据库操作 ===");
        
        try (Connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            
            // 1. 演示SQL注入风险(不安全的方式)
            demonstrateSQLInjectionRisk(connection);
            
            // 2. 使用PreparedStatement(安全的方式)
            demonstrateSafeDatabaseOperation(connection);
            
            // 3. 事务处理
            demonstrateTransaction(connection);
            
        } catch (SQLException e) {
            System.err.println("数据库错误: " + e.getMessage());
        }
    }
    
    // 演示SQL注入风险(仅用于教学,实际开发中避免使用)
    private static void demonstrateSQLInjectionRisk(Connection connection) throws SQLException {
        System.out.println("\n=== SQL注入风险演示 ===");
        
        // 危险的做法:直接拼接SQL字符串
        String userInput = "'; DROP TABLE users; --";
        String dangerousSQL = "SELECT * FROM users WHERE name = '" + userInput + "'";
        
        System.out.println("危险的SQL: " + dangerousSQL);
        System.out.println("⚠️  这种写法可能导致SQL注入攻击!");
    }
    
    // 安全的数据库操作
    private static void demonstrateSafeDatabaseOperation(Connection connection) throws SQLException {
        System.out.println("\n=== 安全的数据库操作 ===");
        
        // 1. 安全的插入操作
        String insertSQL = "INSERT INTO users (name, email, age) VALUES (?, ?, ?)";
        try (PreparedStatement pstmt = connection.prepareStatement(insertSQL)) {
            
            // 插入多条记录
            String[][] userData = {
                {"赵六", "[email protected]", "32"},
                {"孙七", "[email protected]", "27"},
                {"周八", "[email protected]", "29"}
            };
            
            for (String[] user : userData) {
                pstmt.setString(1, user[0]);      // name
                pstmt.setString(2, user[1]);      // email
                pstmt.setInt(3, Integer.parseInt(user[2])); // age
                
                int result = pstmt.executeUpdate();
                if (result > 0) {
                    System.out.println("成功插入用户: " + user[0]);
                }
            }
        }
        
        // 2. 安全的查询操作
        String selectSQL = "SELECT * FROM users WHERE age > ? AND name LIKE ?";
        try (PreparedStatement pstmt = connection.prepareStatement(selectSQL)) {
            pstmt.setInt(1, 25);           // 年龄大于25
            pstmt.setString(2, "%三%");     // 名字包含"三"
            
            try (ResultSet rs = pstmt.executeQuery()) {
                System.out.println("\n查询结果(年龄>25且名字包含'三'):");
                while (rs.next()) {
                    System.out.printf("ID: %d, 姓名: %s, 年龄: %d%n",
                        rs.getInt("id"),
                        rs.getString("name"),
                        rs.getInt("age"));
                }
            }
        }
        
        // 3. 安全的更新操作
        String updateSQL = "UPDATE users SET age = age + 1 WHERE name = ?";
        try (PreparedStatement pstmt = connection.prepareStatement(updateSQL)) {
            pstmt.setString(1, "张三");
            
            int rowsUpdated = pstmt.executeUpdate();
            System.out.println("\n更新了 " + rowsUpdated + " 条记录(张三年龄+1)");
        }
    }
    
    // 事务处理演示
    private static void demonstrateTransaction(Connection connection) throws SQLException {
        System.out.println("\n=== 事务处理演示 ===");
        
        // 保存原始的自动提交设置
        boolean originalAutoCommit = connection.getAutoCommit();
        
        try {
            // 开始事务
            connection.setAutoCommit(false);
            System.out.println("事务开始...");
            
            // 操作1:插入用户
            String insertUserSQL = "INSERT INTO users (name, email, age) VALUES (?, ?, ?)";
            try (PreparedStatement pstmt1 = connection.prepareStatement(insertUserSQL)) {
                pstmt1.setString(1, "事务用户");
                pstmt1.setString(2, "[email protected]");
                pstmt1.setInt(3, 35);
                
                int result1 = pstmt1.executeUpdate();
                System.out.println("操作1:插入用户 " + (result1 > 0 ? "成功" : "失败"));
            }
            
            // 操作2:更新其他用户信息
            String updateSQL = "UPDATE users SET age = age + 1 WHERE age < ?";
            try (PreparedStatement pstmt2 = connection.prepareStatement(updateSQL)) {
                pstmt2.setInt(1, 30);
                
                int result2 = pstmt2.executeUpdate();
                System.out.println("操作2:更新了 " + result2 + " 个用户的年龄");
            }
            
            // 模拟业务逻辑判断
            boolean businessLogicSuccess = true; // 假设业务逻辑成功
            
            if (businessLogicSuccess) {
                // 提交事务
                connection.commit();
                System.out.println("✅ 事务提交成功!");
            } else {
                // 回滚事务
                connection.rollback();
                System.out.println("❌ 事务回滚!");
            }
            
        } catch (SQLException e) {
            // 发生异常时回滚事务
            connection.rollback();
            System.err.println("❌ 事务回滚(异常): " + e.getMessage());
            throw e;
            
        } finally {
            // 恢复原始的自动提交设置
            connection.setAutoCommit(originalAutoCommit);
            System.out.println("事务处理完成,恢复自动提交模式");
        }
    }
}

3. 数据库连接池基础

java 复制代码
// ConnectionPoolBasics.java - 简单的连接池实现
import java.sql.*;
import java.util.concurrent.*;
import java.util.*;

public class ConnectionPoolBasics {
    
    public static void main(String[] args) {
        System.out.println("=== 数据库连接池基础 ===");
        
        // 创建简单连接池
        SimpleConnectionPool pool = new SimpleConnectionPool(
            "jdbc:mysql://localhost:3306/testdb",
            "root",
            "password",
            5  // 最大连接数
        );
        
        // 模拟多个线程同时使用数据库
        ExecutorService executor = Executors.newFixedThreadPool(10);
        
        for (int i = 0; i < 20; i++) {
            final int taskId = i;
            executor.submit(() -> {
                try {
                    // 从连接池获取连接
                    Connection conn = pool.getConnection();
                    System.out.println("任务 " + taskId + " 获取到连接");
                    
                    // 模拟数据库操作
                    try (PreparedStatement pstmt = conn.prepareStatement(
                        "SELECT COUNT(*) as user_count FROM users")) {
                        
                        ResultSet rs = pstmt.executeQuery();
                        if (rs.next()) {
                            int count = rs.getInt("user_count");
                            System.out.println("任务 " + taskId + " 查询到 " + count + " 个用户");
                        }
                    }
                    
                    // 模拟处理时间
                    Thread.sleep(1000);
                    
                    // 归还连接到池中
                    pool.releaseConnection(conn);
                    System.out.println("任务 " + taskId + " 归还连接");
                    
                } catch (Exception e) {
                    System.err.println("任务 " + taskId + " 执行错误: " + e.getMessage());
                }
            });
        }
        
        executor.shutdown();
        try {
            executor.awaitTermination(30, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        // 关闭连接池
        pool.close();
        System.out.println("连接池已关闭");
    }
}

// 简单的连接池实现(仅用于学习)
class SimpleConnectionPool {
    private final String url;
    private final String username;
    private final String password;
    private final int maxConnections;
    
    private final Queue<Connection> availableConnections = new ArrayDeque<>();
    private final Set<Connection> usedConnections = new HashSet<>();
    
    public SimpleConnectionPool(String url, String username, String password, int maxConnections) {
        this.url = url;
        this.username = username;
        this.password = password;
        this.maxConnections = maxConnections;
        
        // 初始化连接池
        initializePool();
    }
    
    private void initializePool() {
        try {
            for (int i = 0; i < maxConnections; i++) {
                Connection connection = DriverManager.getConnection(url, username, password);
                availableConnections.offer(connection);
            }
            System.out.println("连接池初始化完成,创建了 " + maxConnections + " 个连接");
        } catch (SQLException e) {
            System.err.println("连接池初始化失败: " + e.getMessage());
        }
    }
    
    public synchronized Connection getConnection() throws SQLException {
        if (availableConnections.isEmpty()) {
            if (usedConnections.size() < maxConnections) {
                // 创建新连接
                Connection connection = DriverManager.getConnection(url, username, password);
                usedConnections.add(connection);
                return connection;
            } else {
                // 等待可用连接
                try {
                    wait(5000); // 等待5秒
                    if (availableConnections.isEmpty()) {
                        throw new SQLException("获取连接超时");
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new SQLException("获取连接被中断");
                }
            }
        }
        
        Connection connection = availableConnections.poll();
        usedConnections.add(connection);
        return connection;
    }
    
    public synchronized void releaseConnection(Connection connection) {
        if (usedConnections.remove(connection)) {
            availableConnections.offer(connection);
            notify(); // 通知等待的线程
        }
    }
    
    public void close() {
        synchronized (this) {
            // 关闭所有连接
            availableConnections.forEach(this::closeConnection);
            usedConnections.forEach(this::closeConnection);
            
            availableConnections.clear();
            usedConnections.clear();
        }
    }
    
    private void closeConnection(Connection connection) {
        try {
            if (connection != null && !connection.isClosed()) {
                connection.close();
            }
        } catch (SQLException e) {
            System.err.println("关闭连接错误: " + e.getMessage());
        }
    }
}

✅ 第三部分:综合实战项目(70分钟)

网络+数据库综合应用:简单的用户管理系统

java 复制代码
// UserManagementSystem.java - 用户管理系统主类
import java.io.*;
import java.net.*;
import java.sql.*;
import java.util.concurrent.*;

/**
 * 简单的网络用户管理系统
 * 功能:用户注册、登录、查询
 * 技术:Socket + JDBC
 */
public class UserManagementSystem {
    private static final int PORT = 7777;
    private UserService userService;
    
    public UserManagementSystem() {
        this.userService = new UserService();
    }
    
    public void start() {
        System.out.println("=== 用户管理系统启动 ===");
        
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("系统监听端口: " + PORT);
            
            // 使用线程池处理客户端请求
            ExecutorService threadPool = Executors.newFixedThreadPool(10);
            
            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("新客户端连接: " + clientSocket.getInetAddress());
                
                // 提交任务到线程池
                threadPool.submit(new ClientRequestHandler(clientSocket, userService));
            }
            
        } catch (IOException e) {
            System.err.println("服务器启动错误: " + e.getMessage());
        }
    }
    
    public static void main(String[] args) {
        new UserManagementSystem().start();
    }
}

// ClientRequestHandler.java - 客户端请求处理器
class ClientRequestHandler implements Runnable {
    private Socket clientSocket;
    private UserService userService;
    private BufferedReader input;
    private PrintWriter output;
    
    public ClientRequestHandler(Socket clientSocket, UserService userService) {
        this.clientSocket = clientSocket;
        this.userService = userService;
        
        try {
            input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            output = new PrintWriter(clientSocket.getOutputStream(), true);
        } catch (IOException e) {
            System.err.println("初始化客户端处理器错误: " + e.getMessage());
        }
    }
    
    @Override
    public void run() {
        try {
            // 发送欢迎消息和菜单
            sendWelcomeMessage();
            
            // 处理客户端命令
            String command;
            while ((command = input.readLine()) != null) {
                String response = processCommand(command);
                output.println(response);
                
                if ("quit".equalsIgnoreCase(command.trim())) {
                    break;
                }
            }
            
        } catch (IOException e) {
            System.err.println("处理客户端请求错误: " + e.getMessage());
        } finally {
            closeConnection();
        }
    }
    
    private void sendWelcomeMessage() {
        output.println("========================================");
        output.println("    欢迎使用用户管理系统");
        output.println("========================================");
        output.println("可用命令:");
        output.println("register <用户名> <密码> <邮箱> - 注册新用户");
        output.println("login <用户名> <密码> - 用户登录");
        output.println("list - 查看所有用户");
        output.println("quit - 退出系统");
        output.println("========================================");
        output.println("请输入命令:");
    }
    
    private String processCommand(String command) {
        try {
            String[] parts = command.trim().split("\\s+");
            if (parts.length == 0) {
                return "❌ 无效命令";
            }
            
            String action = parts[0].toLowerCase();
            
            switch (action) {
                case "register":
                    if (parts.length < 4) {
                        return "❌ 用法: register <用户名> <密码> <邮箱>";
                    }
                    return handleRegister(parts[1], parts[2], parts[3]);
                    
                case "login":
                    if (parts.length < 3) {
                        return "❌ 用法: login <用户名> <密码>";
                    }
                    return handleLogin(parts[1], parts[2]);
                    
                case "list":
                    return handleListUsers();
                    
                case "quit":
                    return "👋 再见!";
                    
                default:
                    return "❌ 未知命令: " + action;
            }
            
        } catch (Exception e) {
            return "❌ 处理命令错误: " + e.getMessage();
        }
    }
    
    private String handleRegister(String username, String password, String email) {
        try {
            boolean success = userService.registerUser(username, password, email);
            if (success) {
                return "✅ 用户注册成功: " + username;
            } else {
                return "❌ 用户注册失败,可能用户名或邮箱已存在";
            }
        } catch (Exception e) {
            return "❌ 注册错误: " + e.getMessage();
        }
    }
    
    private String handleLogin(String username, String password) {
        try {
            boolean success = userService.validateUser(username, password);
            if (success) {
                return "✅ 登录成功,欢迎 " + username + "!";
            } else {
                return "❌ 用户名或密码错误";
            }
        } catch (Exception e) {
            return "❌ 登录错误: " + e.getMessage();
        }
    }
    
    private String handleListUsers() {
        try {
            String userList = userService.getAllUsers();
            return "📋 用户列表:\n" + userList;
        } catch (Exception e) {
            return "❌ 获取用户列表错误: " + e.getMessage();
        }
    }
    
    private void closeConnection() {
        try {
            if (clientSocket != null && !clientSocket.isClosed()) {
                clientSocket.close();
            }
        } catch (IOException e) {
            System.err.println("关闭连接错误: " + e.getMessage());
        }
    }
}

// UserService.java - 用户服务类
class UserService {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/usermgmt";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "password";
    
    public UserService() {
        initializeDatabase();
    }
    
    private void initializeDatabase() {
        try (Connection conn = getConnection();
             Statement stmt = conn.createStatement()) {
            
            // 创建用户表
            String createTableSQL = """
                CREATE TABLE IF NOT EXISTS app_users (
                    id INT AUTO_INCREMENT PRIMARY KEY,
                    username VARCHAR(50) UNIQUE NOT NULL,
                    password VARCHAR(100) NOT NULL,
                    email VARCHAR(100) UNIQUE NOT NULL,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
                """;
            
            stmt.executeUpdate(createTableSQL);
            System.out.println("数据库初始化完成");
            
        } catch (SQLException e) {
            System.err.println("数据库初始化错误: " + e.getMessage());
        }
    }
    
    private Connection getConnection() throws SQLException {
        return DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
    }
    
    public boolean registerUser(String username, String password, String email) throws SQLException {
        String sql = "INSERT INTO app_users (username, password, email) VALUES (?, ?, ?)";
        
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            pstmt.setString(1, username);
            pstmt.setString(2, hashPassword(password)); // 实际应用中应该加密密码
            pstmt.setString(3, email);
            
            int rowsAffected = pstmt.executeUpdate();
            return rowsAffected > 0;
            
        } catch (SQLException e) {
            if (e.getErrorCode() == 1062) { // MySQL重复键错误
                return false;
            }
            throw e;
        }
    }
    
    public boolean validateUser(String username, String password) throws SQLException {
        String sql = "SELECT password FROM app_users WHERE username = ?";
        
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            pstmt.setString(1, username);
            
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    String storedPassword = rs.getString("password");
                    return storedPassword.equals(hashPassword(password));
                }
                return false;
            }
        }
    }
    
    public String getAllUsers() throws SQLException {
        String sql = "SELECT id, username, email, created_at FROM app_users ORDER BY created_at DESC";
        StringBuilder result = new StringBuilder();
        
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {
            
            result.append("ID\t用户名\t\t邮箱\t\t\t创建时间\n");
            result.append("------------------------------------------------------------\n");
            
            while (rs.next()) {
                result.append(String.format("%d\t%s\t\t%s\t\t%s\n",
                    rs.getInt("id"),
                    rs.getString("username"),
                    rs.getString("email"),
                    rs.getTimestamp("created_at")));
            }
            
            if (result.length() == 0) {
                result.append("暂无用户");
            }
        }
        
        return result.toString();
    }
    
    // 简单的密码哈希(实际应用中应使用更安全的方法如BCrypt)
    private String hashPassword(String password) {
        return "HASH_" + password.hashCode();
    }
}

🎯 今日练习任务

1. 网络编程练习(40分钟)

  • 运行聊天服务器和客户端
  • 尝试多个客户端同时连接
  • 观察消息广播效果

2. 数据库操作练习(40分钟)

  • 配置MySQL数据库
  • 运行JDBC基础示例
  • 尝试PreparedStatement操作

3. 综合项目练习(60分钟)

  • 部署用户管理系统
  • 测试注册、登录、查询功能
  • 观察多客户端并发访问

4. 代码改进挑战(30分钟)

  • 为聊天服务器添加私聊功能
  • 为用户管理系统添加密码加密
  • 优化数据库连接池性能

📚 扩展学习资源

推荐学习材料

  • 《Java网络编程》- Elliotte Rusty Harold
  • Oracle JDBC官方文档
  • MySQL连接器/J文档

下一步学习方向

  • Web开发框架(Spring Boot)
  • ORM框架(MyBatis/Hibernate)
  • 微服务架构
  • 消息队列系统

💡 学习要点总结

  1. Socket编程:理解TCP/UDP协议差异
  2. JDBC操作:掌握PreparedStatement防SQL注入
  3. 连接池:理解资源管理的重要性
  4. 多线程:网络编程中的并发处理
  5. 事务处理:保证数据一致性
相关推荐
真实的菜2 小时前
适配器模式:接口转换的神奇魔法[特殊字符],让不兼容的类和谐共处!
java·适配器模式
骚戴2 小时前
SpringBoot源码解析(十五):spring-boot-autoconfigure.jar的模块化设计
java
YuTaoShao2 小时前
Java八股文——计算机网络「应用层篇」
java·网络·计算机网络
Mryan20052 小时前
Android 应用多语言与系统语言偏好设置指南
android·java·国际化·android-studio·多语言
鲁Q同志3 小时前
若依导出模板时设置动态excel下拉框(表连接的)
java·excel
汇匠源4 小时前
Java 零工市场小程序 | 灵活就业平台 | 智能匹配 | 日结薪系统 | 用工一站式解决方案
java·小程序
why1514 小时前
java IO流
java
IT_10244 小时前
SpringBoot扩展——发送邮件!
java·spring boot·后端
二宝哥4 小时前
maven命令安装jar包到本地仓库
java·maven·jar