Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 23 additions & 40 deletions core/src/main/java/info/xiaomo/core/utils/CastUtil.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package info.xiaomo.core.utils;

import java.io.*;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
Expand Down Expand Up @@ -74,49 +75,31 @@ public static int toInteger(String str) {
}

public static int isNumeric(String str) {
if (str == null) {
if (str == null || str.isEmpty()) {
return 0;
} else {
boolean isdouble = false;
boolean hasE = false;
int i = str.length();

while (true) {
while (true) {
char c;
do {
--i;
if (i < 0) {
if (isdouble) {
return 2;
}

return 1;
}

c = str.charAt(i);
} while (i == 0 && c == 45);

if (c == 46) {
if (isdouble) {
return 0;
}

isdouble = true;
} else if (c != 69 && c != 101) {
if (!Character.isDigit(str.charAt(i))) {
return 0;
}
} else {
if (hasE) {
return 0;
}

hasE = true;
}
}
}
String check = str;
if (check.charAt(0) == '-') {
// 允许唯一的负号前缀(负整数), 与旧实现一致; "-" 单独出现视为非数字
check = check.substring(1);
if (check.isEmpty()) {
return 0;
}
} else if (check.charAt(0) == '+') {
return 0;
}
try {
// 用 BigDecimal 严格校验, "1.2.3" 之类非法数字返回 0, 不再抛运行期异常
new BigDecimal(check);
} catch (NumberFormatException e) {
return 0;
}
for (int i = 0; i < check.length(); i++) {
if (!Character.isDigit(check.charAt(i))) {
return 2;
}
}
return 1;
}

public static HashMap copyMap(HashMap map) {
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/java/info/xiaomo/core/utils/ExcelUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ private static String[][] getData(File file, int ignoreRows)
}
break;
case FORMULA:
// 导入时如果为公式生成的数据则无值
if (!"".equals(cell.getStringCellValue())) {
// 公式单元格可能是字符串或数值, 分别取值, 避免类型不匹配时抛异常
try {
value = cell.getStringCellValue();
} else {
value = cell.getNumericCellValue() + "";
} catch (IllegalStateException e) {
value = String.valueOf(cell.getNumericCellValue());
}
break;
case BLANK:
Expand Down
10 changes: 5 additions & 5 deletions core/src/main/java/info/xiaomo/core/utils/FileUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@
* @deprecated 在实现的时候没有注意到File类本身带一个toURL方法将文件路径转换为URL。
* 请使用File.toURL方法。
*/
public static URL getURL(File file) throws MalformedURLException {

Check warning on line 272 in core/src/main/java/info/xiaomo/core/utils/FileUtil.java

View workflow job for this annotation

GitHub Actions / Build (JDK 21)

deprecated item is not annotated with @deprecated

Check warning on line 272 in core/src/main/java/info/xiaomo/core/utils/FileUtil.java

View workflow job for this annotation

GitHub Actions / Build (JDK 25)

deprecated item is not annotated with @deprecated
String fileURL = "file:/" + file.getAbsolutePath();
return new URL(fileURL);
}
Expand Down Expand Up @@ -856,11 +856,11 @@

public static boolean isImage(String imageName) {
String fileType = FileUtil.getFileType(imageName);
return !("bmp".equals(fileType) || "BMP".equals(fileType)
|| "jpg".equals(fileType) || "JPG".equals(fileType)
|| "jpeg".equals(fileType) || "JPEG".equals(fileType)
|| "git".equals(fileType) || "GIF".equals(fileType)
|| "png".equals(fileType) || "PNG".equals(fileType));
return "bmp".equalsIgnoreCase(fileType)
|| "jpg".equalsIgnoreCase(fileType)
|| "jpeg".equalsIgnoreCase(fileType)
|| "gif".equalsIgnoreCase(fileType)
|| "png".equalsIgnoreCase(fileType);
}

}
5 changes: 4 additions & 1 deletion core/src/main/java/info/xiaomo/core/utils/IDUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ public static void main(String[] args) {
}

/**
* 获取唯一一个id
* 获取唯一一个id。
*
* <p>注意: 该实现只在单个 JVM 进程内(秒内 65000 个)保证单调不回退, 并非跨进程、
* 跨重启全局唯一的 snowflake 方案, 不适用于分布式主键场景。
*
* @return long
*/
Expand Down
47 changes: 11 additions & 36 deletions core/src/main/java/info/xiaomo/core/utils/MailUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
import jakarta.mail.*;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Objects;
import java.util.Properties;

/**
Expand All @@ -31,11 +32,15 @@ public class MailUtil {
*/
private static Session getSession() throws IOException {
Properties props = new Properties();
String dir = System.getProperty("user.dir");
FileInputStream is = new FileInputStream(dir + "/website/src/main/resources/config/application.properties");
props.load(is);
USERNAME = String.valueOf(props.get("mail.username"));
PASSWORD = String.valueOf(props.get("mail.password"));
// 从 classpath 读取配置, 不再依赖进程工作目录(user.dir)下的绝对路径
try (InputStream is = MailUtil.class.getClassLoader().getResourceAsStream("config/application.properties")) {
if (is == null) {
throw new IOException("未找到 classpath 下的 config/application.properties");
}
props.load(is);
}
USERNAME = Objects.toString(props.get("mail.username"), "");
PASSWORD = Objects.toString(props.get("mail.password"), "");
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
Expand All @@ -61,34 +66,4 @@ public static void send(String toEmail, String subject, String content) {
mex.printStackTrace();
}
}

/**
* 返回激活链接
*
* @param email email
* @return 有3个参数 email password time
*/
public static String redirectValidateUrl(String email, String password) {
Long now = TimeUtil.getNowOfMills();
StringBuilder sb = new StringBuilder("点击下面链接激活账号,48小时生效,否则重新注册账号,链接只能使用一次,请尽快激活!</br>");
sb.append("<a href=\"http://localhost:8080/user/validate?email=");
sb.append(email);
sb.append("&password=");
sb.append(password);
sb.append("&time=");
sb.append(now);
sb.append("\">");
sb.append("http://localhost:8080/user/validate?email=");
sb.append(email);
sb.append("&password=");
sb.append(password);
sb.append("&time=");
sb.append(now);
sb.append("</a><br/>");
sb.append("<span style='float:right;padding-right:4%'>小莫</span></br>");
sb.append("<span style='float:right'>");
sb.append(TimeUtil.getFormatDate());
sb.append("</span></br>");
return sb.toString();
}
}
3 changes: 2 additions & 1 deletion core/src/main/java/info/xiaomo/core/utils/Md5Util.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package info.xiaomo.core.utils;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

/**
Expand Down Expand Up @@ -70,7 +71,7 @@ public static String encode(String password, String salt) {
try {
resultString = password + salt;
MessageDigest md = MessageDigest.getInstance("md5");
resultString = byteArrayToString(md.digest(resultString.getBytes()));
resultString = byteArrayToString(md.digest(resultString.getBytes(StandardCharsets.UTF_8)));
} catch (Exception ex) {
ex.printStackTrace();
}
Expand Down
18 changes: 8 additions & 10 deletions core/src/main/java/info/xiaomo/core/utils/RegExUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -167,13 +169,11 @@ public static Vector<String> splitTags2Vector(String pattern, String str) throws
public static String[] splitTags(String pattern, String str) {
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(str);
String[] array = new String[m.groupCount()];
int i = 0;
List<String> array = new ArrayList<>();
while (m.find()) {
array[i] = eregReplace("(\\[\\#)|(\\#\\])", "", m.group());
i++;
array.add(eregReplace("(\\[\\#)|(\\#\\])", "", m.group()));
}
return array;
return array.toArray(new String[0]);
}


Expand Down Expand Up @@ -206,13 +206,11 @@ public static Vector<String> regMatchAll2Vector(String pattern, String str) thro
public static String[] regMatchAll2Array(String pattern, String str) throws PatternSyntaxException {
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(str);
String[] array = new String[m.groupCount()];
int i = 0;
List<String> array = new ArrayList<>();
while (m.find()) {
array[i] = m.group();
i++;
array.add(m.group());
}
return array;
return array.toArray(new String[0]);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/java/info/xiaomo/core/utils/SerializeUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static String serialize(Object object) {
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return new String(bytes, StandardCharsets.UTF_8);
return new String(bytes, StandardCharsets.ISO_8859_1);
} catch (Exception e) {
e.printStackTrace();
}
Expand All @@ -51,8 +51,8 @@ public static String serialize(Object object) {
/**
* 反序列化
*/
public static Object unserialize(String s) throws UnsupportedEncodingException {
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
public static Object unserialize(String s) {
byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
ByteArrayInputStream bais;
try {
//反序列化
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/java/info/xiaomo/core/utils/SqlUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ private String delNewSQlString(String sql) {
}

private String delSQlString(String sql) {
if (sql == null || sql.isEmpty()) {
return "in()";
}
StringBuilder delSql = new StringBuilder("in(");
StringTokenizer tokenizer = new StringTokenizer(sql, "|");

Expand Down
64 changes: 42 additions & 22 deletions core/src/main/java/info/xiaomo/core/utils/StringUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,10 @@ public static String replace(String s, Map<String, String> map) {
char ch = '}';
for (int start, end; (start = s.indexOf(str, cursor)) != -1 && (end = s.indexOf(ch, start)) != -1; ) {
sb.append(s.substring(cursor, start));
String key = s.substring(start + 2, end);
sb.append(map.get(StringUtils.trim(key)));
String key = StringUtils.trim(s.substring(start + 2, end));
String value = map.get(key);
// 缺失的 key 原样保留占位符, 而不是拼出字面量 "null"
sb.append(value != null ? value : str + key + ch);
cursor = end + 1;
}
sb.append(s.substring(cursor, s.length()));
Expand All @@ -209,32 +211,37 @@ public static String replace(String s, Map<String, String> map) {
* @return ip 如果返回null,说明是一个不合法的ip地址格式
*/
public static String getIP(HttpServletRequest request) {
String ip = request.getHeader("X-Requested-For");
String unknown = "unknown";
if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
// 反代场景下这些头可能是逗号分隔的多级代理列表, 取第一段(真实客户端地址)并跳过 "unknown"
String ip = firstCandidate(request.getHeader("X-Forwarded-For"),
request.getHeader("X-Requested-For"),
request.getHeader("Proxy-Client-IP"),
request.getHeader("WL-Proxy-Client-IP"),
request.getHeader("HTTP_CLIENT_IP"),
request.getHeader("HTTP_X_FORWARDED_FOR"));
if (ip == null) {
ip = request.getRemoteAddr();
}
if (!ip.matches(IP_REGEX)) {
if (ip == null || !ip.matches(IP_REGEX)) {
return null;
}
return ip;
}

private static String firstCandidate(String... headers) {
for (String header : headers) {
if (StringUtils.isBlank(header)) {
continue;
}
for (String part : header.split(",")) {
String candidate = part.trim();
if (StringUtils.isNotBlank(candidate) && !"unknown".equalsIgnoreCase(candidate)) {
return candidate;
}
}
}
return null;
}

/**
* 判断字符串是否为空,并删除首尾空格
*
Expand Down Expand Up @@ -467,7 +474,7 @@ public static String format(String str, Object... params) {
param = obj.toString();
}
}
m.appendReplacement(sb, param);
m.appendReplacement(sb, Matcher.quoteReplacement(param));
}
m.appendTail(sb);
return sb.toString();
Expand Down Expand Up @@ -964,12 +971,25 @@ public static String decode(String s) {
|| ch == ')') {
sbuf.append((char) ch);
} else if (ch == '%') {
// 末尾残缺的 % (如 "abc", "abc%u123") 直接原样输出剩余部分, 不再越界访问
if (i + 1 >= len) {
sbuf.append(s.substring(i));
break;
}
int cint = 0;
if ('u' != s.charAt(i + 1)) {
if (i + 3 > len) {
sbuf.append(s.substring(i));
break;
}
cint = (cint << 4) | VAL[s.charAt(i + 1)];
cint = (cint << 4) | VAL[s.charAt(i + 2)];
i += 2;
} else {
if (i + 6 > len) {
sbuf.append(s.substring(i));
break;
}
cint = (cint << 4) | VAL[s.charAt(i + 2)];
cint = (cint << 4) | VAL[s.charAt(i + 3)];
cint = (cint << 4) | VAL[s.charAt(i + 4)];
Expand Down
Loading
Loading