项目修改记录

1. 在使用TCP协议时,如果输入流迟迟等不到消息,可能会一直阻塞,导致程序无响应,可以给客户端Socket设置一个最大等待时间。超过这个时间Socket将会自动关闭,从而结束阻塞的状态。

Socket s = ...;    // 客户端连接
s.setSoTimeout(10000); // 设置10秒超时时间

可通过捕获SocketTimeOutException异常对阻塞情况进行处理

2. 向MySQL数据库插入数据的时候,如果已经存在关键数据都相同的数据,将会抛出异常。所以为了尽量避免异常可以先判断是否存在相同数据,再确定是否执行新增数据操作。

String username = UsernameGenerator.generateUsername();
while ( FindRowNumber.toFindRowNumber(username) > 0 ) {
      username = UsernameGenerator.generateUsername();
} //用于保证生成的 username 不会重复

其中UsernameGenerator.generateUsername()是一个用于生成随机字符串的静态方法

FindRowNumber.toFindRowNumber(username)则是用于寻找数据所在数据库的行数,如果没有找到将会返回-1,其源代码如下所示
import java.sql.*;

public class FindRowNumber {

    public static int toFindRowNumber(String keyname) {
        // 数据库配置
        String url = "jdbc:mysql://localhost:3306/ydll";
        String user = "root";
        String password = "1234";
        String tableName = "logindata";
        String keyColumn = "username";
        String keyValue = keyname; // 你要查找的关键键值

        // 查找关键键所在的行号
        int rowNumber = findRowNumber(url, user, password, tableName, keyColumn, keyValue);

        /*if (rowNumber > 0) {
            System.out.println("关键键值 " + keyValue + " 在第 " + rowNumber + " 行。");
        } else {
            System.out.println("未找到关键键值 " + keyValue + " 的行。");
        }*/
        return rowNumber;
    }

    public static void main(String[] args) {
        toFindRowNumber("10");
    }

    private static int findRowNumber(String url, String user, String password, String tableName, String keyColumn, String keyValue) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        int rowNumber = -1;

        try {
            // 加载数据库驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 建立连接
            conn = DriverManager.getConnection(url, user, password);

            // 首先,检查关键键值是否存在于表中
            String checkSql = "SELECT COUNT(*) FROM " + tableName + " WHERE " + keyColumn + " = ?";
            pstmt = conn.prepareStatement(checkSql);
            pstmt.setString(1, keyValue);
            rs = pstmt.executeQuery();
            if (rs.next() && rs.getInt(1) == 0) {
                // 关键键值不存在
                return -1;
            }

            // SQL查询,使用子查询来计算行号
            String sql = "SELECT COUNT(*) + 1 AS row_num FROM " + tableName + " WHERE " + keyColumn + " < ? ORDER BY " + keyColumn + ";";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, keyValue);
            rs = pstmt.executeQuery();

            // 获取行号
            if (rs.next()) {
                rowNumber = rs.getInt("row_num");
            }

        } catch (ClassNotFoundException e) {
            System.out.println("JDBC Driver not found.");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("Database access error.");
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (rs != null) rs.close();
                if (pstmt != null) pstmt.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return rowNumber;
    }
}

*3. 目前使用的客户端计时限制方法需要额外开辟一个线程,这样才能使表示时间限制的int变量timeRemaining自动递减。源码如下:

import java.util.Timer;
import java.util.TimerTask;

public class TimerWithTimerTask {

    public static int timeRemaining = 0;
    private Timer timer;

    public TimerWithTimerTask() {
        //this.timeRemaining = initialTime;
        this.timer = new Timer();
    }

    public void startCountdown() {
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                if (timeRemaining > 0) {
                    timeRemaining--;
                    System.out.printf("剩余时间: %02d:%02d\n", timeRemaining / 60, timeRemaining % 60);
                } else {
                    System.out.println("时间到!");
                    timer.cancel();
                }
            }
        }, 0, 1000);
    }

    public static void main(String[] args) {
        TimerWithTimerTask timer = new TimerWithTimerTask();
        timer.startCountdown();
    }
}

只需给TimerWithTimerTask.timeRemaining赋值,就可以改变需要等待的时间。使用下面的两行代码将会开辟线程,实现该int变量随着时间的递减

TimerWithTimerTask timer = new TimerWithTimerTask();
timer.startCountdown();

(由于是线程处理,可以将timeRemaining设置为非静态,实现多个倒数计算器)

3.5 由于是在线程中运行,所以当timer.startCountdown()跑完前,即使关闭所有JavaFX生成的窗口也不会停止线程运行。以下是解决方法

其实窗口全部关闭是JavaFX的launch()语句跑完的标志,只需在launch()语句后使TimerWithTimerTask.timeRemaining=0即可,如果timeRemaining设置为非静态,也可以设置其他静态变量在TimerWithTimerTask类中,并作为线程结束的标志之一。

4.忘记密码功能模块不需要设置新的...Message类去传输,只用邮箱实现可以共用 (获取验证码)Message ,需要使用用户名实现可以将 (获取验证码)Message 和 (登录信息)Message 一起进行TCP传输。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值