一、涉及的技术知识点1.1 空值判断与防御性编程知识点说明多类型空值判断对 string/collection/map/array/optional/object 统一判空可变参数(varargs)i
一、涉及的技术知识点
1.1 空值判断与防御性编程
| 知识点 | 说明 |
|---|
| 多类型空值判断 | 对 string/collection/map/array/optional/object 统一判空 |
| 可变参数(varargs) | isorempty(object...) 任一为空返回 true,isandempty(object...) 全部为空返回 true |
| null safety | 替代手写 != null && !"" 链式判断 |
1.2 日期时间处理
| 知识点 | 说明 |
|---|
java.util.date(旧 api) | dateutil 基于旧 api 兼容存量代码 |
java.time.localdate/localdatetime(新 api) | datetimeutil 基于 java 8 时间 api |
| 智能日期解析 | 根据字符串长度自动识别格式(10位时间戳/13位时间戳/19位标准格式/23位含毫秒) |
| 正则模式匹配 | 用正则判断日期字符串格式(标准 yyyy-mm-dd/斜杠 yyyy/mm/dd) |
| temporaladjusters | 获取月初/月末/年初/年末/上月/下月等时间点 |
| 时区枚举 | zoneenums 定义时区常量 |
| 日期格式枚举 | datetimeformat 枚举统一管理 20+ 种日期格式 |
1.3 json 序列化/反序列化
| 知识点 | 说明 |
|---|
| jackson objectmapper | 配置好的全局单例,线程安全 |
| typereference 泛型反序列化 | 解决 java 泛型擦除问题 |
| snake case 支持 | snakemapper 自动驼峰 ↔ 下划线转换 |
| 容错处理 | 序列化/反序列化异常不抛出,返回 null 并记录日志 |
1.4 加密工具
| 知识点 | 说明 |
|---|
| aes 对称加密 | aesutil 提供简单的 aes 加解密(ecb 模式) |
| md5 摘要 | md5utils 提供 md5 哈希(签名校验场景) |
| threadlocal messagedigest | md5 计算使用 threadlocal 避免多线程竞争 |
| hex 编码 | 字节数组转十六进制字符串 |
1.5 线程上下文管理
| 知识点 | 说明 |
|---|
| threadlocal | auth2sessionidutil 使用 threadlocal 存储请求级别的用户信息 |
| token 传递 | 在请求处理链中透传 oauth2 token |
| 请求级隔离 | 每个请求有独立的 sessionid/token/loginname |
| 清理机制 | delete() 方法清理 threadlocal 防止内存泄漏 |
1.6 国际化(i18n)
| 知识点 | 说明 |
|---|
messagesource | spring 国际化消息源 |
| 资源文件 | messages.properties / messages_zh_cn.properties |
| 参数化消息 | getmsg(key, args...) 支持占位符 |
1.7 网络工具
| 知识点 | 说明 |
|---|
| 客户端 ip 获取 | 从 x-forwarded-for / x-real-ip 等 header 解析 |
| 内网 ip 判断 | isintranetip() 判断是否为 10.x/172.16-31.x/192.168.x |
| 主机名获取 | gethostname() 获取当前服务器主机名 |
| threadlocal ip | 请求级别缓存客户端 ip |
二、包结构
xxx.xxx.xxx.utils
├── checkemptyutil.java // 空值判断工具(使用频率最高)
├── dateutil.java // 日期工具(旧api,java.util.date)
├── stringutil.java // 字符串/json工具(序列化+特殊字符处理)
├── jsonutil.java // json 序列化工具(支持 snake case)
├── auth2sessionidutil.java // oauth2 会话上下文(threadlocal)
├── iputil.java // ip 地址工具
├── aesutil.java // aes 加解密工具
├── md5utils.java // md5 摘要工具
├── xxxi18nutil.java // 国际化消息工具
├── fileutil.java // 文件操作工具
├── jasperutil.java // 报表导出工具(jasper)
├── pdfutil.java // pdf 生成工具
├── classnameutil.java // 类名处理工具
├── xxxserializationutils.java // java 序列化工具
├── packageutil.java // 包扫描工具
├── urlutil.java // url 处理工具
├── cloud/
│ ├── adapterheader.java // 适配器 header 工具
│ └── logintoken.java // 登录 token 封装
└── time/
├── datetimeutil.java // 日期时间工具(新api,java.time)
├── datetimeformat.java // 日期格式枚举(20+种预定义格式)
├── datetimeconverter.java // 日期转换器
└── zoneenums.java // 时区枚举
无 spring.factories:纯工具类库,不涉及自动配置,直接引入静态方法调用。
三、通用示例代码
3.1 checkemptyutil(空值判断工具)
package com.example.utils;
import java.lang.reflect.array;
import java.util.collection;
import java.util.map;
import java.util.optional;
/**
* 通用空值判断工具.
* 统一处理各种类型的空值判断,替代业务代码中的 != null && !isempty() 链式判断.
*
* 支持类型:
* - null
* - string(空字符串)
* - collection(空集合)
* - map(空map)
* - array(空数组)
* - optional(空optional)
* - 其他 object(仅判null)
*/
public class checkemptyutil {
/**
* 判断对象是否为空.
* 根据实际类型自动选择判空策略.
*/
public static boolean isempty(object obj) {
if (obj == null) {
return true;
}
if (obj instanceof string) {
return ((string) obj).trim().isempty();
}
if (obj instanceof collection) {
return ((collection<?>) obj).isempty();
}
if (obj instanceof map) {
return ((map<?, ?>) obj).isempty();
}
if (obj.getclass().isarray()) {
return array.getlength(obj) == 0;
}
if (obj instanceof optional) {
return !((optional<?>) obj).ispresent();
}
return false;
}
/**
* 判断对象是否非空.
*/
public static boolean isnotempty(object obj) {
return !isempty(obj);
}
/**
* 任一参数为空返回true.
* 常用于参数校验:if (isorempty(a, b)) throw ...
*/
public static boolean isorempty(object... objs) {
if (objs == null) {
return true;
}
for (object obj : objs) {
if (isempty(obj)) {
return true;
}
}
return false;
}
/**
* 全部参数都为空返回true.
* 常用于条件判断:if (isandempty(a, b)) 都没传
*/
public static boolean isandempty(object... objs) {
if (objs == null) {
return true;
}
for (object obj : objs) {
if (isnotempty(obj)) {
return false;
}
}
return true;
}
}
3.2 dateutil(旧版日期工具)
package com.example.utils;
import java.text.simpledateformat;
import java.util.calendar;
import java.util.date;
import java.util.regex.pattern;
/**
* 日期工具类(基于 java.util.date).
*
* 核心特性:
* 1. 智能日期解析 - 根据字符串格式自动识别
* 2. 常用日期操作 - 月初/月末/日始/日终
* 3. 日期格式化 - 标准格式输出
*/
public class dateutil {
private static final pattern unix_timestamp = pattern.compile("^\\d{10}$");
private static final pattern java_timestamp = pattern.compile("^\\d{13}$");
private static final string standard_datetime = "yyyy-mm-dd hh:mm:ss";
private static final string standard_date = "yyyy-mm-dd";
/**
* 智能日期解析.
* 支持:时间戳(10位/13位)、标准格式、斜杠格式.
*
* @param text 日期字符串
* @return date 对象,解析失败返回 null
*/
public static date converttodate(string text) {
if (text == null || text.trim().isempty()) {
return null;
}
text = text.trim();
try {
switch (text.length()) {
case 10:
// unix 时间戳 或 yyyy-mm-dd
if (unix_timestamp.matcher(text).matches()) {
return new date(long.parselong(text) * 1000);
}
return new simpledateformat(standard_date).parse(text);
case 13:
// java 时间戳
if (java_timestamp.matcher(text).matches()) {
return new date(long.parselong(text));
}
return null;
case 19:
// yyyy-mm-dd hh:mm:ss
return new simpledateformat(standard_datetime).parse(text);
case 23:
// yyyy-mm-dd hh:mm:ss.sss
return new simpledateformat("yyyy-mm-dd hh:mm:ss.sss").parse(text);
default:
return new simpledateformat(standard_datetime).parse(text);
}
} catch (exception e) {
return null;
}
}
/** 获取日期的起始时刻(00:00:00.000). */
public static date getdaybegin(date date) {
calendar cal = calendar.getinstance();
cal.settime(date);
cal.set(calendar.hour_of_day, 0);
cal.set(calendar.minute, 0);
cal.set(calendar.second, 0);
cal.set(calendar.millisecond, 0);
return cal.gettime();
}
/** 获取日期的结束时刻(23:59:59.999). */
public static date getdayend(date date) {
calendar cal = calendar.getinstance();
cal.settime(date);
cal.set(calendar.hour_of_day, 23);
cal.set(calendar.minute, 59);
cal.set(calendar.second, 59);
cal.set(calendar.millisecond, 999);
return cal.gettime();
}
/** 格式化为标准日期时间字符串. */
public static string formatstandarddatetime(date date) {
if (date == null) return null;
return new simpledateformat(standard_datetime).format(date);
}
/** 获取 n 天后的日期. */
public static date getdateafter(date date, int days) {
calendar cal = calendar.getinstance();
cal.settime(date);
cal.add(calendar.day_of_month, days);
return cal.gettime();
}
}
3.3 stringutil(字符串/json 工具)
package com.example.utils;
import com.fasterxml.jackson.core.type.typereference;
import com.fasterxml.jackson.databind.deserializationfeature;
import com.fasterxml.jackson.databind.objectmapper;
import com.fasterxml.jackson.databind.serializationfeature;
import java.util.regex.pattern;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
/**
* 字符串和json工具类.
*
* 核心功能:
* 1. json 序列化/反序列化(容错模式)
* 2. 特殊字符检测和替换(中文/emoji/符号)
* 3. 驼峰拆分
*/
public class stringutil {
private static final logger logger = loggerfactory.getlogger(stringutil.class);
private static final pattern chinese_char = pattern.compile("[\\u4e00-\\u9fa5]");
private static final pattern emoji_char = pattern.compile("[\\ud800-\\udfff]");
// 全局单例 objectmapper(线程安全)
private static final objectmapper read_mapper = new objectmapper()
.configure(deserializationfeature.fail_on_unknown_properties, false);
private static final objectmapper write_mapper = new objectmapper()
.configure(serializationfeature.fail_on_empty_beans, false);
/**
* 对象序列化为 json 字符串.
* 异常时返回空字符串,不抛出异常.
*/
public static string getjsonstring(object obj) {
if (obj == null) {
return "";
}
if (obj instanceof string) {
return (string) obj;
}
try {
return write_mapper.writevalueasstring(obj);
} catch (exception e) {
logger.error("json序列化失败", e);
return "";
}
}
/**
* json 字符串反序列化为对象.
*/
public static <t> t parsejsonstring(string json, class<t> clazz) {
if (json == null || json.isempty()) {
return null;
}
try {
return read_mapper.readvalue(json, clazz);
} catch (exception e) {
logger.error("json反序列化失败", e);
return null;
}
}
/**
* json 字符串反序列化(泛型支持).
*/
public static <t> t parsejsonstring(string json, typereference<t> typeref) {
if (json == null || json.isempty()) {
return null;
}
try {
return read_mapper.readvalue(json, typeref);
} catch (exception e) {
logger.error("json反序列化失败", e);
return null;
}
}
/** 是否包含中文字符. */
public static boolean containschinese(string str) {
return str != null && chinese_char.matcher(str).find();
}
/** 是否包含 emoji 字符. */
public static boolean containsemoji(string str) {
return str != null && emoji_char.matcher(str).find();
}
/** 替换 emoji 为指定字符. */
public static string replaceemoji(string str, string replacement) {
if (str == null) return null;
return emoji_char.matcher(str).replaceall(replacement);
}
}
3.4 auth2sessionidutil(请求上下文工具)
package com.example.utils;
/**
* oauth2 请求级别上下文工具.
* 通过 threadlocal 存储当前请求的用户信息,在同一请求内全局可访问.
*
* 使用场景:
* - filter/interceptor 中设置(请求进入时)
* - service 层中读取(业务处理时)
* - filter 中清理(请求结束时)
*
* 注意:必须在请求结束时调用 delete() 清理,防止线程池复用导致数据串线.
*/
public final class auth2sessionidutil {
private static final threadlocal<string> sessionidlocal = new threadlocal<>();
private static final threadlocal<string> tokenlocal = new threadlocal<>();
private static final threadlocal<string> loginnamelocal = new threadlocal<>();
/** 获取当前请求的会话id. */
public static string getsessionid() {
return sessionidlocal.get();
}
public static void setsessionid(string sessionid) {
sessionidlocal.set(sessionid);
}
/** 获取当前请求的 oauth2 token. */
public static string gettoken() {
return tokenlocal.get();
}
public static void settoken(string token) {
tokenlocal.set(token);
}
/** 获取当前登录用户名. */
public static string getloginname() {
return loginnamelocal.get();
}
public static void setloginname(string loginname) {
loginnamelocal.set(loginname);
}
/**
* 清理所有 threadlocal 数据.
* 必须在请求结束时调用!防止线程池复用导致数据泄露.
*/
public static void delete() {
sessionidlocal.remove();
tokenlocal.remove();
loginnamelocal.remove();
}
}
3.5 pom.xml(工具库)
<project>
<groupid>com.example</groupid>
<artifactid>example-utils</artifactid>
<version>1.0.0</version>
<packaging>jar</packaging>
<dependencies>
<!-- json -->
<dependency>
<groupid>com.fasterxml.jackson.core</groupid>
<artifactid>jackson-databind</artifactid>
<scope>provided</scope>
</dependency>
<!-- servlet(获取ip等) -->
<dependency>
<groupid>javax.servlet</groupid>
<artifactid>javax.servlet-api</artifactid>
<scope>provided</scope>
</dependency>
<!-- spring context(国际化) -->
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-context</artifactid>
<scope>provided</scope>
</dependency>
<!-- 日志 -->
<dependency>
<groupid>org.slf4j</groupid>
<artifactid>slf4j-api</artifactid>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
四、引入方使用
4.1 添加依赖
<dependency>
<groupid>com.example</groupid>
<artifactid>example-utils</artifactid>
<version>1.0.0</version>
</dependency>
4.2 使用示例
@service
public class orderservice {
public void processorder(orderdto dto) {
// 参数校验
if (checkemptyutil.isorempty(dto.getordercode(), dto.getmemberid())) {
throw new illegalargumentexception("参数不能为空");
}
// 日期处理
date deliverydate = dateutil.converttodate(dto.getdeliverytime()); // 自动识别格式
date deadline = dateutil.getdateafter(deliverydate, 3); // 3天后
// json 序列化(记日志)
log.info("处理订单入参: {}", stringutil.getjsonstring(dto));
// 空值安全操作
if (checkemptyutil.isnotempty(dto.getitemlist())) {
dto.getitemlist().foreach(item -> {
// 业务逻辑...
});
}
}
}
五、关键设计总结
| 设计要点 | 实现方式 | 收益 |
|---|
| 多类型统一判空 | instanceof 分发 | 一个方法覆盖所有类型,减少重复代码 |
| 智能日期解析 | 按字符串长度 + 正则分发 | 无需调用方关心日期格式 |
| json 容错 | 序列化/反序列化异常返回 null | 不会因为一个字段异常导致整个请求失败 |
| 全局 objectmapper | 静态单例 + 线程安全配置 | 避免每次创建实例的开销 |
| threadlocal 上下文 | 请求级隔离用户信息 | service 层无需传参即可获取当前用户 |
| threadlocal 清理 | delete() 方法 | 防止线程池复用导致数据串线 |
| 纯静态工具类 | 无 spring.factories,无 bean 注册 | 任何项目引入即用,零配置 |
| provided scope | 核心依赖由引入方提供 | 不引入版本冲突 |
以上就是springboot中通用工具类库(utils)封装与使用实践的详细内容,更多关于springboot通用工具类库封装与使用的资料请关注代码网其它相关文章!
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论