部分功能的实现和算法

目录

1.雪花算法

2.MD5加密

3.小眼睛显示密码

4.发送验证码

5.倒计时


1.雪花算法

SnowFlake 中文意思为雪花,故称为雪花算法。最早是 Twitter 公司在其内部用于分布式环境下生成唯一 ID。在2014年开源 scala 语言版本

雪花算法的原理就是生成一个的 64 位比特位的 long 类型的唯一 id。

最高 1 位固定值 0,因为生成的 id 是正整数,如果是 1 就是负数了。
接下来 41 位存储毫秒级时间戳,2^41/(1000*60*60*24*365)=69,大概可以使用 69 年。
再接下 10 位存储机器码,包括 5 位 datacenterId 和 5 位 workerId。最多可以部署 2^10=1024 台机器。
最后 12 位存储序列号。同一毫秒时间戳时,通过这个递增的序列号来区分。即对于同一台机器而言,同一毫秒时间戳下,可以生成 2^12=4096 个不重复 id。

public class SnowflakeIdGenerator {

    private final long twepoch = 1626708222000L; // 设置起始时间戳,这里使用当前时间的毫秒值作为起始时间
    private final long workerIdBits = 10L;
    private final long sequenceBits = 12L;

    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private final long workerIdShift = sequenceBits;
    private final long timestampLeftShift = sequenceBits + workerIdBits;
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);

    private long workerId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    public SnowflakeIdGenerator(long workerId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("Worker ID can't be greater than %d or less than 0", maxWorkerId));
        }
        this.workerId = workerId;
    }

    public synchronized long nextId() {
        long timestamp = timeGen();

        if (timestamp < lastTimestamp) {
            throw new RuntimeException("Clock moved backwards. Refusing to generate id for " + (lastTimestamp - timestamp) + " milliseconds");
        }

        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }

        lastTimestamp = timestamp;

        return ((timestamp - twepoch) << timestampLeftShift) |
                (workerId << workerIdShift) |
                sequence;
    }

    private long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }

    // 示例用法
    public static void main(String[] args) {
        SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1); // 假设当前机器的worker id是1

        // 生成10个ID进行展示
        for (int i = 0; i < 10; i++) {
            long id = idGenerator.nextId();
            System.out.println("Generated Id: " + id);
        }
    }
}

2.MD5加密

MD5加密全程是Message-Digest Algoorithm 5(信息-摘要算法),它对信息进行摘要采集,再通过一定的位运算,最终获取加密后的MD5字符串。
  例如我们要加密一篇文章,那么我们会随机从每段话或者每行中获取一个字,把这些字统计出来后,再通过一定的运算获得一个固定长度的MD5加密后信息。因此,其很难被逆向破解。

MD5加密的特点:

MD5加密的特点主要有以下几点:
  1、针对不同长度待加密的数据、字符串等等,其都可以返回一个固定长度的MD5加密字符串。(通常32位的16进制字符串);
  2、其加密过程几乎不可逆,除非维护一个庞大的Key-Value数据库来进行碰撞破解,否则几乎无法解开。
  3、运算简便,且可实现方式多样,通过一定的处理方式也可以避免碰撞算法的破解。
  4、对于一个固定的字符串。数字等等,MD5加密后的字符串是固定的,也就是说不管MD5加密多少次,都是同样的结果。

public class MD5Util {

    // 加密方法:接收一个字符串明文,返回使用 MD5 加密后的哈希值
    public static String encrypt(String plaintext) throws NoSuchAlgorithmException {
        // 使用 MD5 算法创建 MessageDigest 对象
        MessageDigest md = MessageDigest.getInstance("MD5");
        // 更新 MessageDigest 对象中的字节数据
        md.update(plaintext.getBytes());
        // 对更新后的数据计算哈希值,存储在 byte 数组中
        byte[] digest = md.digest();
        // 将 byte 数组转换为十六进制字符串
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b & 0xff));
        }
        // 返回十六进制字符串
        return sb.toString();
    }

    // 解密方法:接收一个字符串明文和一个使用 MD5 加密后的哈希值,返回解密结果(true 表示匹配,false 表示不匹配)
    public static boolean decrypt(String plaintext, String encrypted) throws NoSuchAlgorithmException {
        // 调用加密方法计算出明文的哈希值
        String decrypted = encrypt(plaintext);
        // 比较计算得到的哈希值和输入的哈希值是否相同
        return decrypted.equals(encrypted);
    }
}

3.小眼睛显示密码

方法:javafx中添加一个密码文本框(passwordFild),一个普通文本框(passwordlook),一个按钮(yanjingButton),两张图片(eyesz)(eyesb),按钮和两张图片位置重叠,按钮透明,睁眼的图片透明,闭眼的图片显示,设置按钮点击方法(yanjingButtonOnAction)如下。点击切换图片的透明和显示,切换两个文本框的透明与显示。


    // 在类的成员变量中添加一个标志,用于记录是否已经绑定过文本框
    private boolean isPasswordFieldsBound = false;
    //小眼睛
    public void yanjingButtonOnAction(ActionEvent actionEvent) {
        Button eyesButton = (Button) actionEvent.getSource();
        // 初始化绑定操作,只需执行一次
        if (!isPasswordFieldsBound) {
            passwordlook.textProperty().bindBidirectional(passwordField.textProperty());
            isPasswordFieldsBound = true;
        }
        eyesButton.setOnMouseClicked(event -> {
            String look = passwordField.getText();
            passwordField.setText(look);
            boolean isPasswordFieldVisible = passwordField.isVisible();
            passwordField.setVisible(!isPasswordFieldVisible);
            passwordlook.setVisible(isPasswordFieldVisible);
            eyesb.setVisible(!isPasswordFieldVisible);
            eyesz.setVisible(isPasswordFieldVisible);
        });
    }

4.发送验证码

注意:邮箱用自己的

同时想要如下导包:

发送验证码:

import java.util.Date;
import java.util.Properties;
import java.util.Random;
import javax.mail.Authenticator;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;


public class MailUtils {
    private static MimeMessage message;
    private static String m;

      public MailUtils() {
      }

      public static String sendEmail(String to) throws MessagingException {

          String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
          // QQ邮箱服务器
          String smtpHost = "smtp.qq.com";
          // 邮箱用户名,即QQ账号(自定义)
          String username = "2161672768";
          // 邮箱授权码(自定义)
          String password = "xbgwgdzxkqobdjih";
          // 自己的邮箱(自定义)
          String from = "2161672768@qq.com";
          // 要发送的邮箱地址(自定义)
          String toAddress = to;

          //Transport transport;
          Properties props = new Properties();
          props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
          props.setProperty("mail.smtp.socketFactory.fallback", "false");
          props.setProperty("mail.smtp.port", "465");
          props.setProperty("mail.smtp.socketFactory.port", "465");
          props.setProperty("mail.smtp.auth", "true");
          props.put("mail.smtp.host", smtpHost);
          props.put("mail.smtp.username", username);
          props.put("mail.smtp.password", password);
          Session session = Session.getDefaultInstance(props, new Authenticator() {
              protected PasswordAuthentication getPasswordAuthentication() {
                  return new PasswordAuthentication(username, password);
              }
          });
         InternetAddress[] addresses = new InternetAddress[]{new InternetAddress(toAddress)};
          message = new MimeMessage(session);
          message.setFrom(new InternetAddress(from));
          message.setRecipients(MimeMessage.RecipientType.TO, addresses);
          message.setSubject("验证码");
          message.setSentDate(new Date());
          m = generateVerificationCode(5);
          message.setText(m);
          System.out.println(m);
          Transport  transport = session.getTransport("smtp");
          transport.connect(smtpHost, username, password);
          transport.sendMessage(message, message.getAllRecipients());
        //  Transport.send(message);
          System.out.println("信息已经发送");
          transport.close();
          return m;
      }

      public static boolean judge(String s) {
          return m.equals(s);
      }

      //随机生成长度为5的验证码
      private static String generateVerificationCode(int length) {
          String charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
          StringBuilder verificationCode = new StringBuilder();
          Random random = new Random();

          for(int i = 0; i < length; ++i) {
              verificationCode.append(charSet.charAt(random.nextInt(charSet.length())));
          }

          return verificationCode.toString();
      }
  }

结果如下:

5.倒计时

在发送验证码后,用于显示等待用户再次发送验证码的剩余时间,这里设置的是60s(注意:1000L=1s)
 //在发送验证码后,用于显示等待用户再次发送验证码的剩余时间,60s
    public void count(){
        this.yzmButton.setVisible(false);
        this.wait.setVisible(true);
        (new Thread(() -> {
            int st = 60;

            while(st > 0) {
                final int finalSt = st;
                Platform.runLater(new Runnable() {
                    public void run() {
                        EmailLoginController.this.wait.setText(Integer.toString(finalSt));
                    }
                });

                try {
                    Thread.sleep(1000L);
                    --st;
                } catch (InterruptedException var4) {
                    InterruptedException e = var4;
                    throw new RuntimeException(e);
                }
            }

            this.yzmButton.setVisible(true);
            this.wait.setVisible(false);
        })).start();
    }

方法用于实现较长时间的倒计时,这里设置的是120秒,用于显示验证码的有效时间。
  //方法用于实现较长时间的倒计时(120秒),用于显示验证码的有效时间。
    public void count00(){
        this.time.setVisible(true);
        (new Thread(() -> {
            int st = 120;

            while(st > 0) {
                if (this.time1 != this.time2) {
                    this.time1 = this.time2;
                    st = 120;
                }

                final int finalSt = st;
                Platform.runLater(new Runnable() {
                    public void run() {
                       EmailLoginController.this.time.setText("验证码有效时间剩余:" + Integer.toString(finalSt));
                    }
                });

                try {
                    Thread.sleep(1000L);
                    --st;
                } catch (InterruptedException var4) {
                    InterruptedException e = var4;
                    throw new RuntimeException(e);
                }
            }

            this.time.setVisible(false);
        })).start();
    }

  • 22
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值