工具类

public class StringMatchUtil {

    public static boolean isLike(String source, String regex) {
        return isLike(source, regex, false);
    }

    /**
     * 判断source字符串是否能够被regex匹配,能满足普通情况,没有考虑特别复杂的情况
     *
     * @param source     任意字符串
     * @param regex      包含*或?的匹配表达式(如果要匹配*、?、\,需要加上反斜杠,如\*,\?,\\)
     * @param ignoreCase 大小写敏感
     * @return
     */
    public static boolean isLike(String source, String regex, boolean ignoreCase) {
        if (source == null || regex == null) return false;
        if (ignoreCase) {
            source = source.toLowerCase();
            regex = regex.toLowerCase();
        }
        return matches(source, regex.replaceAll("(^|([^\\\\]))[\\*]{2,}", "$2*"));//去除多余*号
    }

    private static boolean matches(String source, String regex) {
        //如果source与regex完全相等,且source不包含反斜杠,则返回true。(当source包含*号或者?号,此时亦满足,不做多余判断)
        if (source.equals(regex) && source.indexOf('\\') < 0) return true;
        int rIdx = 0, sIdx = 0;//同时遍历源字符串与匹配表达式
        while (rIdx < regex.length() && sIdx < source.length()) {
            char c = regex.charAt(rIdx);//以匹配表达式为主导
            switch (c) {
                case '*'://匹配到*号进入下一层递归
                    String tempSource = source.substring(sIdx);//去除前面已经完全匹配的前缀
                    String tempRegex = regex.substring(rIdx + 1);//从星号后一位开始认为是新的匹配表达式
                    for (int j = 0; j <= tempSource.length(); j++) {//此处等号不能缺,如(ABCD,*),等号能达成("", *)条件
                        if (matches(tempSource.substring(j), tempRegex)) {//很普通的递归思路
                            return true;
                        }
                    }
                    return false;//排除所有潜在可能性,则返回false
                case '?':
                    break;
                case '\\'://匹配到反斜杠跳过一位,匹配下一个字符串
                    c = regex.charAt(++rIdx);
                default:
                    if (source.charAt(sIdx) != c) return false;//普通字符的匹配
            }
            rIdx++;
            sIdx++;
        }
        //最终source被匹配完全,而regex也被匹配完整或只剩一个*号
        return source.length() == sIdx &&
                (regex.length() == rIdx ||
                        regex.length() == rIdx + 1 && regex.charAt(rIdx) == '*');
    }
}

来源