java常用工具(正则表达式、crontab表达式、常用小工具......)

本文详细介绍了正则表达式的各种基础语法和特殊字符,包括匹配、重复、范围等,并给出了实际应用场景,如电话号码和姓名的脱敏处理。同时,文章还阐述了Cron表达式的用法,包括基础语法、特殊字符和常见写法,展示了如何设置定时任务。此外,还提供了日期处理和AES加密解密的Java代码示例。

正则表达式

基础语法

x|y:匹配单个字符x或者单个字符y
[xyz]:匹配指定(xyz)字符的任意一个
[^xyz]:匹配非(xyz)字符的任意一个
[0-9]:匹配范围;表示0到9的任意一个数字
[^a-z]:匹配范围;表示非小写字母(简单理解为非 a-z中的字母)
^:匹配开头;例如 :^[0-9]:表示以数字开头,并且只有一个数字,例如,字符串“1”匹配结果是true,字符串“12”匹配结果就是false
$:匹配结尾;例如:[0-9]$:表示以数字结尾,并且只有一个数字,同上
*:匹配0次或多次;例如:[0-9]*:表示匹配0次或多次数字
?:匹配0次或1次;例如:[0-9]?:表示匹配0次或一次数字
+:匹配1次或多次;例如:[0-9]+:表示匹配1次或多次数字
{n}:匹配确定的n次;例如:[0-9]{5};表示匹配5次数字
{n,m}:(n<=m)至少匹配n次,最多匹配m次;例如;[0-9]{1,2}:表示最少匹配一次数字,最多匹配2次数字

特殊字符

\d:表示一个十进制的数字 [0-9]
\D:表示非数字

\w:表示一个字符[0-9a-zA-Z_]
\W:表示除[0-9a-zA-Z_]之外的字符

\s:表示一个空白字符(空格,tab,换页符等)
\S:表示一个非空白字符
这些都是正则中能够表示一类字符的原子

常见写法

(1)匹配以某一个数字(字符)开头
^[1-9]:以1-9中的某一个数字开头,并且只有一个数字
(2)匹配固定格式开头
^(123):必须是123开头,并且这个串只有这三个数,例如,字符串“123”匹配结果是true,字符串“1234”匹配结果就是false,因为多了一个“4”,字符串“213”也是false,顺序不符合
(3)判断小数(转译字符相关java)
0\\.[1-9]:大于0小于1的小数,有且只有一个小数(这里重点关注哪个小数点的写法就行)

crontab表达式

详情参考:https://help.aliyun.com/document_detail/133509.html

基础语法

CRON 有如下两种语法格式:
秒 分 小时 日期 月份 星期 年
秒 分 小时 日期 月份 星期
一般都用下面这个(不带年的那个),“年”这个很少用到,可以暂时忽略

常用特殊字符

*:表示匹配域的任意值,在分这个域使用 *,即表示每分钟都会触发事件。
?:表示匹配域的任意值,但只能用在日期和星期两个域,因为这两个域会相互影响。示例:要在每月的 20 号触发调度,不管每个月的 20 号是星期几,则只能使用如下写法:0 0 0 20 * ?。其中,因为日期域已经指定了 20 号,最后一位星期域只能用 ?,不能使用 *。如果最后一位使用 *,则表示不管星期几都会触发,与日期域的 20 号相斥,此时表达式不正确。
-:表示起止范围,示例:在分这个域使用 5-20,表示从 5 分到 20 分钟每分钟触发一次。
/:表示起始时间开始触发,然后每隔固定时间触发一次,示例:在分这个域使用 5/20,表示从第5分钟开始触发,之后每 20 分钟触发一次,即 5、 25、45 等分别触发一次。

常用写法

*/5 * * * * ?:每隔 5 秒执行一次,等同于 0/5 * * * * ?
0 */1 * * * ?:每隔 1 分钟执行一次,等同于 0 0/1 * * * ?
0 0 2 1 * ?:每月 1 日的凌晨 2 点执行一次
0 15 10 ? * MON-FRI:周一到周五每天上午 10:15 执行作业
0 15 10 ? 6L 2002-2006:2002 年至 2006 年的每个月的最后一个星期五上午 10:15 执行作业
0 0 23 * * ?:每天 23 点执行一次
0 0 1 * * ?:每天凌晨 1 点执行一次
0 0 1 1 * ?:每月 1 日凌晨 1 点执行一次
0 0 23 L * ?:每月最后一天 23 点执行一次
0 0 1 ? * L:每周星期天凌晨 1 点执行一次
0 26,29,33 * * * ?:在 26 分、29 分、33 分执行一次
0 0 0,13,18,21 * * ?:每天的 0 点、13 点、18 点、21 点都执行一次
0 0 10,14,16 * * ?:每天上午 10 点,下午 2 点,4 点执行一次
0 0/30 9-17 * * ?:朝九晚五工作时间内每半小时执行一次
0 0 12 ? * WED:每个星期三中午 12 点执行一次
0 0 12 * * ?:每天中午 12 点触发
0 15 10 ? * *:每天上午 10:15 触发
0 15 10 * * ?:每天上午 10:15 触发
0 15 10 * * ? *:每天上午 10:15 触发
0 15 10 * * ? 2005:2005 年的每天上午 10:15 触发
0 * 14 * * ?:每天下午 2 点到 2:59 期间的每 1 分钟触发
0 0/5 14 * * ?:每天下午 2 点到 2:55 期间的每 5 分钟触发
0 0/5 14,18 * * ?:每天下午 2 点到 2:55 期间和下午 6 点到 6:55 期间的每 5 分钟触发
0 0-5 14 * * ?:每天下午 2 点到 2:05 期间的每 1 分钟触发
0 10,44 14 ? 3 WED:每年三月的星期三的下午 2:10 和 2:44 触发
0 15 10 ? * MON-FRI:周一至周五的上午 10:15 触发
0 15 10 15 * ?:每月 15 日上午 10:15 触发
0 15 10 L * ?:每月最后一日的上午 10:15 触发
0 15 10 ? * 6L:每月的最后一个星期五上午 10:15 触发
0 15 10 ? * 6L 2002-2005:2002 年至 2005 年的每月的最后一个星期五上午 10:15 触发
0 15 10 ? * 6#3:每月的第三个星期五上午 10:15 触发

常用小工具

(1)将电话号码的中间4位替换成*

public class Mobile {
    public static void main(String[] args) {
        String mobile = "13681467423";
        mobile = mobile.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
        System.out.println(mobile);
    }
}

(2)姓名脱敏
脱敏规则: 只显示第一个汉字,比如李某某置换为李**, 李某置换为李*

private static String desensitizedName(String fullName){
        if (!Strings.isNullOrEmpty(name)) {
            String name = StringUtils.left(fullName, 1);
            return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
        }
        return name;
    }

(3)身份证号脱敏
脱敏规则: 保留前六后三, 适用于15位和18位身份证号
方式一: 需要判断身份证号位数

private static String desensitizedIdNumber(String idNumber){
        if (!Strings.isNullOrEmpty(idNumber)) {
            if (idNumber.length() == 15){
                idNumber = idNumber.replaceAll("(\\w{6})\\w*(\\w{3})", "$1******$2");
            }
            if (idNumber.length() == 18){
                idNumber = idNumber.replaceAll("(\\w{6})\\w*(\\w{3})", "$1*********$2");
            }
            }
        return idNumber;
    }

(4)地址脱敏
脱敏规则: 从第4位开始隐藏,隐藏8位
因地址位数是不确定的,所以结尾长度为总长度减去 前面保留长度和隐藏长度之和 address.length()-11

private static String desensitizedAddress(String address){
        if (!Strings.isNullOrEmpty(address)) {
            return StringUtils.left(address, 3).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(address, address.length()-11), StringUtils.length(address), "*"), "***"));
        }
        return address;
    }

(5)日期相关
获取指定日期的23:59:59
示例:date为new date(),如果传入-1,获取的就是前一天的23:59:59;如果传入的是0,获取的是就是当天的23:59:59

	//new date(),-1
    public static Date getEndOfDate(Date date, int amount){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.add(Calendar.DAY_OF_MONTH, amount);
        return calendar.getTime();
    }

jdk自带的加解密工具

package com.jd.mcs.util;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.SecureRandom;

public class AesUtils {

    /**
     * 生成的key
     */
    private static Key key;

    /**
     * 生成密钥的字符串(自己随便写)
     */
    private static final String ENCRYPT_KEY = "test";


    /**
     * 加密
     * @param encryptionStr
     * @return
     */
    public static String encrypt(String encryptionStr) {
        try {
            // 加密
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, getKey());
            byte[] resultBytes = cipher.doFinal(encryptionStr.getBytes());
            //使用Base64将加密后的字节数组变成字符串
            return Base64.encodeBase64String(resultBytes);
        } catch (Exception e) {
            log.error("加密失败!", e);
            return null;
        }
    }


    /**
     * 解密
     * @param encryptionStr
     * @return
     */
    public static String decrypt(String encryptionStr) {
        try {
            // 解密
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, getKey());
            byte[] result = cipher.doFinal(Base64.decodeBase64(encryptionStr));
            return new String(result);
        } catch (Exception e) {
            log.error("解密失败!", e);
            return null;
        }
    }


    /**
     * 生成密钥
     * @return
     */
    public static Key getKey() {
        if (null != key) return key;
        synchronized (AesUtils.class) {
            if (null == key) {
                try {
                    // 生成KEY ,AES 要求密钥长度为 128
                    KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
                    SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
                    secureRandom.setSeed(ENCRYPT_KEY.getBytes());
                    keyGenerator.init(128, secureRandom);
                    SecretKey secretKey = keyGenerator.generateKey();
                    byte[] byteKey = secretKey.getEncoded();
                    // 转换KEY
                    key = new SecretKeySpec(byteKey, "AES");
                } catch (Exception e) {
                    log.error("生成密钥失败!", e);
                    e.printStackTrace();
                }
            }
        }
        return key;
    }
  }
### 如何配置每天6:35的定时任务 为了实现每天早上6:35运行的任务,可以通过Cron表达式完成这一需求。Cron表达式的格式由多个字段组成,分别代表不同的时间单位[^3]。 #### Cron表达式的基本结构 Cron表达式的标准格式为: ``` 秒 分 小时 日 月 周 (年 - 可选) ``` 对于每天固定时间的任务,“日”、“月”和“周”通常不需要特别指定具体的值,而是通过通配符`*`表示任意值。因此,针对每天6:35的需求,可以构建如下Cron表达式: ```plaintext 35 6 * * * ``` - **秒**:未显式定义,默认为0。 - **分**:设为35,表示任务将在每小时的第35分钟触发。 - **小时**:设为6,表示任务将在早晨6点钟触发。 - **日**:使用`*`,表示每一天都会触发。 - **月**:同样使用`*`,表示每个月都会触发。 - **周**:也使用`*`,因为每天都需要触发,而不是特定某一周中的某一天。 完整的Cron表达式为 `35 6 * * *`[^4]。 如果需要更精确地控制到秒级(尽管大多数情况下无需如此),可以在Quartz风格的Cron表达式中扩展第一位作为秒字段,其形式变为: ```plaintext 35 35 6 * * ? ``` 这里额外增加了第一个字段“秒”,并将其设置为35,以确保任务在6:35:35触发[^3]。 --- ### 使用场景下的实际应用 假设您正在Linux环境中配置此任务,可通过编辑系统的crontab文件来添加该条目。以下是操作方法: 1. 打开终端并输入以下命令进入crontab编辑模式: ```bash crontab -e ``` 2. 添加以下行至文件末尾: ```bash 35 6 * * * /path/to/command ``` 这里的`/path/to/command`应替换为您希望执行的实际脚本路径或命令。 3. 如果是在Java项目中使用Quartz调度器,则需将上述Cron表达式传递给相应的JobDetail对象实例化过程中使用的TriggerBuilder[^3]。 示例代码片段如下所示: ```java import org.quartz.CronScheduleBuilder; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Trigger; // 定义作业细节 JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("myJob", "group1").build(); // 创建基于Cron表达式的触发器 String cronExpression = "35 35 6 * * ?"; Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("myTrigger", "group1") .startNow() .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)) .build(); ``` --- ### 注意事项 当设计Cron表达式时需要注意各字段之间的逻辑关联以及可能存在的冲突情况。例如,在某些框架下,“日期”与“星期”两个字段不可同时指定具体数值,而应该至少有一个采用问号(`?`)占位。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值