学习时间: 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)
- 微服务架构
- 消息队列系统
💡 学习要点总结
- Socket编程:理解TCP/UDP协议差异
- JDBC操作:掌握PreparedStatement防SQL注入
- 连接池:理解资源管理的重要性
- 多线程:网络编程中的并发处理
- 事务处理:保证数据一致性