feat(pigx-common-core): 降级 Jackson 3 到 Jackson 2 并重构配置

This commit is contained in:
PIGCLOUD committed 2026-05-02 13:42:11 +08:00
1 parent e80b4f0b28
commit 7613f72673
24 files changed
+556 -328

No files matched your search

@@ -1,25 +1,29 @@
package com.pig4cloud.pigx.common.core.config;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.pig4cloud.pigx.common.core.jackson.PigxJavaTimeModule;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import com.pig4cloud.pigx.common.core.jackson.PigxLongModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
import org.springframework.boot.servlet.filter.OrderedCharacterEncodingFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.StandardCharsets;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.TimeZone;
@@ -32,55 +36,114 @@ import java.util.TimeZone;
* @author lishangbu
* @date 2020-06-15
*/
@Slf4j
@Configuration
@ConditionalOnClass(ObjectMapper.class)
@AutoConfigureBefore(JacksonAutoConfiguration.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@SuppressWarnings("removal")
public class JacksonConfiguration implements WebMvcConfigurer {
private static final String ASIA_SHANGHAI = "Asia/Shanghai";
private static final String ASIA_SHANGHAI = "Asia/Shanghai";
@Bean
@ConditionalOnMissingBean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return builder -> {
builder.locale(Locale.CHINA);
builder.timeZone(TimeZone.getTimeZone(ASIA_SHANGHAI));
builder.simpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);
builder.serializerByType(Long.class, ToStringSerializer.instance);
builder.modules(new PigxJavaTimeModule());
};
}
private final ObjectProvider<ObjectMapper> objectMapperProvider;
/**
* 增加GET请求参数中时间类型转换 {@link com.pig4cloud.pigx.common.core.jackson.PigxJavaTimeModule}
* <ul>
* <li>HH:mm:ss -> LocalTime</li>
* <li>yyyy-MM-dd -> LocalDate</li>
* <li>yyyy-MM-dd HH:mm:ss -> LocalDateTime</li>
* </ul>
* @param registry
*/
@Override
public void addFormatters(FormatterRegistry registry) {
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setTimeFormatter(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN));
registrar.setDateFormatter(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
registrar.setDateTimeFormatter(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
registrar.registerFormatters(registry);
}
public JacksonConfiguration(ObjectProvider<ObjectMapper> objectMapperProvider) {
this.objectMapperProvider = objectMapperProvider;
}
/**
* 避免form 提交 context-type 不规范中文乱码
* @return Filter
*/
@Bean
public OrderedCharacterEncodingFilter characterEncodingFilter() {
OrderedCharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(StandardCharsets.UTF_8.name());
filter.setForceEncoding(true);
filter.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filter;
}
/**
*
* 贡献 Jackson 2 的全局配置到 Spring 的 Jackson2ObjectMapperBuilder。
* <p>
* 必须使用 {@link org.springframework.boot.jackson2.autoconfigure.Jackson2ObjectMapperBuilderCustomizer}
* 而不是直接定义 {@link ObjectMapper}:
* 直接 new ObjectMapper 会绕过 builder pipeline,导致其它模块通过 customizer 注册的能力
* (例如 pigx-common-xss 的 String 反序列化 XSS 清洗)静默失效。
*/
@Bean
public org.springframework.boot.jackson2.autoconfigure.Jackson2ObjectMapperBuilderCustomizer pigxJackson2Customizer() {
// 序列化能力按职责拆分到独立 module:
// PigxJavaTimeModule —— Java 8 时间类型格式化
// PigxLongModule —— Long/long -> String,防 JS 精度丢失
return builder -> builder
.locale(Locale.CHINA)
.timeZone(TimeZone.getTimeZone(ASIA_SHANGHAI))
.simpleDateFormat(DatePattern.NORM_DATETIME_PATTERN)
.modulesToInstall(new PigxJavaTimeModule(), new PigxLongModule())
.featuresToDisable(
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
/**
* 增加GET请求参数中时间类型转换 {@link com.pig4cloud.pigx.common.core.jackson.PigxJavaTimeModule}
* <ul>
* <li>HH:mm:ss -> LocalTime</li>
* <li>yyyy-MM-dd -> LocalDate</li>
* <li>yyyy-MM-dd HH:mm:ss -> LocalDateTime</li>
* </ul>
* @param registry
*/
@Override
public void addFormatters(FormatterRegistry registry) {
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setTimeFormatter(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN));
registrar.setDateFormatter(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
registrar.setDateTimeFormatter(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
registrar.registerFormatters(registry);
}
/**
* 避免form 提交 context-type 不规范中文乱码
* @return Filter
*/
@Bean
public OrderedCharacterEncodingFilter characterEncodingFilter() {
OrderedCharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(StandardCharsets.UTF_8.name());
filter.setForceEncoding(true);
filter.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filter;
}
/**
* 用 Jackson 2 的 {@link org.springframework.http.converter.json.MappingJackson2HttpMessageConverter}
* 替换 Spring Boot 4 默认注册的
* Jackson 3 {@link JacksonJsonHttpMessageConverter},确保 Spring MVC 走 Jackson 2 链路。
* <p>
* 注入的 {@link ObjectMapper} 已被所有
* {@link org.springframework.boot.jackson2.autoconfigure.Jackson2ObjectMapperBuilderCustomizer}
* (包括 pigx-common-xss 的 {@code xssJacksonCustomizer})处理过,因此本 converter 同时具备
* XSS 反序列化清洗、时间格式、Long 字符串化等能力。
* <p>
* 替换策略:用 {@link ListIterator#set} 原地替换 Jackson 3 converter;找不到时把 Jackson 2
* converter 插到队首作为 fallback。不做 clear,以免破坏 byte[]、String、multipart
* 等其它默认 converter。
* @param converters 消息转换器列表
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
ObjectMapper objectMapper = objectMapperProvider.getIfAvailable();
if (objectMapper == null) {
log.warn("ObjectMapper 不可用,跳过 Spring MVC Jackson 2 替换;保留 Spring Boot 默认 converter 链。");
return;
}
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter jackson2Converter =
new org.springframework.http.converter.json.MappingJackson2HttpMessageConverter(objectMapper);
ListIterator<HttpMessageConverter<?>> it = converters.listIterator();
boolean replaced = false;
while (it.hasNext()) {
if (it.next() instanceof JacksonJsonHttpMessageConverter) {
it.set(jackson2Converter);
replaced = true;
}
}
if (!replaced) {
converters.add(0, jackson2Converter);
}
log.info("已配置 Spring MVC 使用 Jackson 2 HttpMessageConverter,version={}",
jackson2Converter.getObjectMapper().version());
}
}
@@ -2,7 +2,7 @@ package com.pig4cloud.pigx.common.core.config;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder;
import org.springframework.web.servlet.support.ExtendedServletRequestDataBinder;
/**
* priority 标头配置
@@ -90,11 +90,6 @@ public interface CacheConstants {
*/
String TENANT_DETAILS = GLOBALLY + "tenant_details";
/**
* i18n缓存 (不区分租户)
*/
String I18N_DETAILS = GLOBALLY + "i18n_details";
/**
* 客户端配置缓存
*/
@@ -105,4 +100,14 @@ public interface CacheConstants {
*/
String LOGIN_ERROR_TIMES = "login_error_times";
/**
* API Key 缓存(hash -> SysApiKey)
*/
String API_KEY_DETAILS = "api_key_details";
/**
* 网站配置聚合缓存(i18n + site config),租户隔离
*/
String SITE_CONFIG_DETAILS = "site_config_details";
}
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2018-2026, lengleng All rights reserved.
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -110,6 +110,16 @@ public interface CommonConstants {
*/
String IMAGE_CODE_CLICK_WORD = "clickWord";
/**
* 数学(算术)图形验证码类型
*/
String IMAGE_CODE_MATH = "math";
/**
* math 验证码凭据分隔符,约定格式 {@code randomStr---code}
*/
String CAPTCHA_VERIFICATION_SEPARATOR = "---";
/**
* 验证码开关
*/
@@ -1,6 +1,6 @@
/*
*
* Copyright (c) 2018-2026, lengleng All rights reserved.
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -25,238 +25,231 @@ package com.pig4cloud.pigx.common.core.constant;
*/
public interface SecurityConstants {
/**
* 启动时是否检查Inner注解安全性
*/
boolean INNER_CHECK = true;
/**
* 启动时是否检查Inner注解安全性
*/
boolean INNER_CHECK = true;
/**
* 刷新
*/
String REFRESH_TOKEN = "refresh_token";
/** 密码 */
String PASSWORD = "password";
/**
* 验证码有效期
*/
int CODE_TIME = 60;
/**
* 刷新
*/
String REFRESH_TOKEN = "refresh_token";
/**
* 验证码长度
*/
String CODE_SIZE = "4";
/**
* 验证码有效期
*/
int CODE_TIME = 60;
/**
* 角色前缀
*/
String ROLE = "ROLE_";
/**
* 验证码长度
*/
String CODE_SIZE = "4";
/**
* 前缀
*/
String PIGX_PREFIX = "pigx_";
/**
* 角色前缀
*/
String ROLE = "ROLE_";
/**
* token 相关前缀
*/
String TOKEN_PREFIX = "token:";
/**
* 前缀
*/
String PIGX_PREFIX = "pigx_";
/**
* oauth 相关前缀
*/
String OAUTH_PREFIX = "oauth:";
/**
* token 相关前缀
*/
String TOKEN_PREFIX = "token:";
/**
* 授权码模式code key 前缀
*/
String OAUTH_CODE_PREFIX = "oauth:code:";
/**
* oauth 相关前缀
*/
String OAUTH_PREFIX = "oauth:";
/**
* 项目的license
*/
String PIGX_LICENSE = "https://pig4cloud.com";
/**
* 授权码模式code key 前缀
*/
String OAUTH_CODE_PREFIX = "oauth:code:";
/**
* 内部
*/
String FROM_IN = "Y";
/**
* 项目的license
*/
String PIGX_LICENSE = "https://pig4cloud.com";
/**
* 标志
*/
String FROM = "from";
/**
* 内部
*/
String FROM_IN = "Y";
/**
* Feign 用户代理
*/
String FEIGN_USER_AGENT = "pigx-feign";
/**
* 标志
*/
String FROM = "from";
/**
* 请求header
*/
String HEADER_FROM_IN = FROM + "=" + FROM_IN;
/**
* Feign 用户代理
*/
String FEIGN_USER_AGENT = "pigx-feign";
/**
* OAUTH URL
*/
String OAUTH_TOKEN_URL = "/oauth2/token";
/**
* 请求header
*/
String HEADER_FROM_IN = FROM + "=" + FROM_IN;
/**
* 移动端授权
*/
String GRANT_MOBILE = "mobile";
/**
* OAUTH URL
*/
String OAUTH_TOKEN_URL = "/oauth2/token";
/**
* TOC 客户端
*/
String HEADER_TOC = "CLIENT-TOC";
/**
* 移动端授权
*/
String GRANT_MOBILE = "mobile";
/**
* TOC 客户端
*/
String HEADER_TOC_YES = "Y";
/**
* QQ获取token
*/
String QQ_AUTHORIZATION_CODE_URL = "https://graph.qq.com/oauth2.0/token?grant_type="
+ "authorization_code&code=%S&client_id=%s&redirect_uri=" + "%s&client_secret=%s";
/**
* QQ获取token
*/
String QQ_AUTHORIZATION_CODE_URL = "https://graph.qq.com/oauth2.0/token?grant_type="
+ "authorization_code&code=%S&client_id=%s&redirect_uri=" + "%s&client_secret=%s";
/**
* 微信获取OPENID
*/
String WX_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/oauth2/access_token"
+ "?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
/**
* 微信获取OPENID
*/
String WX_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/oauth2/access_token"
+ "?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
/**
* 微信小程序OPENID
*/
String MINI_APP_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/jscode2session"
+ "?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
/**
* 微信小程序OPENID
*/
String MINI_APP_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/jscode2session"
+ "?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
/**
* 码云获取token
*/
String GITEE_AUTHORIZATION_CODE_URL = "https://gitee.com/oauth/token?grant_type="
+ "authorization_code&code=%S&client_id=%s&redirect_uri=" + "%s&client_secret=%s";
/**
* 码云获取token
*/
String GITEE_AUTHORIZATION_CODE_URL = "https://gitee.com/oauth/token?grant_type="
+ "authorization_code&code=%S&client_id=%s&redirect_uri=" + "%s&client_secret=%s";
/**
* 开源中国获取token
*/
String OSC_AUTHORIZATION_CODE_URL = "https://www.oschina.net/action/openapi/token";
/**
* 开源中国获取token
*/
String OSC_AUTHORIZATION_CODE_URL = "https://www.oschina.net/action/openapi/token";
/**
* QQ获取用户信息
*/
String QQ_USER_INFO_URL = "https://graph.qq.com/oauth2.0/me?access_token=%s";
/**
* QQ获取用户信息
*/
String QQ_USER_INFO_URL = "https://graph.qq.com/oauth2.0/me?access_token=%s";
/**
* 码云获取用户信息
*/
String GITEE_USER_INFO_URL = "https://gitee.com/api/v5/user?access_token=%s";
/**
* 码云获取用户信息
*/
String GITEE_USER_INFO_URL = "https://gitee.com/api/v5/user?access_token=%s";
/**
* 开源中国用户信息
*/
String OSC_USER_INFO_URL = "https://www.oschina.net/action/openapi/user?access_token=%s&dataType=json";
/**
* 开源中国用户信息
*/
String OSC_USER_INFO_URL = "https://www.oschina.net/action/openapi/user?access_token=%s&dataType=json";
/**
* 钉钉获取 token
*/
String DING_OLD_GET_TOKEN = "https://oapi.dingtalk.com/gettoken";
/**
* 钉钉获取 token
*/
String DING_OLD_GET_TOKEN = "https://oapi.dingtalk.com/gettoken";
/**
* 钉钉同步部门列表
*/
String DING_OLD_DEPT_URL = "https://oapi.dingtalk.com/topapi/v2/department/listsub";
/**
* 钉钉同步部门列表
*/
String DING_OLD_DEPT_URL = "https://oapi.dingtalk.com/topapi/v2/department/listsub";
/**
* 钉钉部门用户id列表
*/
String DING_DEPT_USERIDS_URL = "https://oapi.dingtalk.com/topapi/user/listid";
/**
* 钉钉部门用户id列表
*/
String DING_DEPT_USERIDS_URL = "https://oapi.dingtalk.com/topapi/user/listid";
/**
* 钉钉用户详情
*/
String DING_USER_INFO_URL = "https://oapi.dingtalk.com/topapi/v2/user/get";
/**
* 钉钉用户详情
*/
String DING_USER_INFO_URL = "https://oapi.dingtalk.com/topapi/v2/user/get";
/**
* {bcrypt} 加密的特征码
*/
String BCRYPT = "{bcrypt}";
/**
* {bcrypt} 加密的特征码
*/
String BCRYPT = "{bcrypt}";
/**
* 客户端模式
*/
String CLIENT_CREDENTIALS = "client_credentials";
/**
* 客户端模式
*/
String CLIENT_CREDENTIALS = "client_credentials";
/**
* 客户端编号
*/
String CLIENT_ID = "client_id";
/**
* 客户端编号
*/
String CLIENT_ID = "client_id";
/**
* 客户端唯一令牌
*/
String CLIENT_RECREATE = "recreate_flag";
/**
* 客户端唯一令牌
*/
String CLIENT_RECREATE = "recreate_flag";
/**
* 用户ID字段
*/
String DETAILS_USER_ID = "user_id";
/**
* 用户ID字段
*/
String DETAILS_USER_ID = "user_id";
/**
* 用户名
*/
String DETAILS_USERNAME = "username";
/**
* 用户名
*/
String DETAILS_USERNAME = "username";
/**
* 姓名
*/
String NAME = "name";
/**
* 姓名
*/
String NAME = "name";
/**
* 协议字段
*/
String DETAILS_LICENSE = "license";
/**
* 协议字段
*/
String DETAILS_LICENSE = "license";
/**
* 激活字段 兼容外围系统接入
*/
String ACTIVE = "active";
/**
* 激活字段 兼容外围系统接入
*/
String ACTIVE = "active";
/**
* AES 加密
*/
String AES = "aes";
/**
* AES 加密
*/
String AES = "aes";
/**
* 授权码模式confirm
*/
String CUSTOM_CONSENT_PAGE_URI = "/oauth2/confirm_access";
/**
* 授权码模式confirm
*/
String CUSTOM_CONSENT_PAGE_URI = "/oauth2/confirm_access";
/**
* {noop} 加密的特征码
*/
String NOOP = "{noop}";
/**
* {noop} 加密的特征码
*/
String NOOP = "{noop}";
/**
* 短信登录 参数名称
*/
String SMS_PARAMETER_NAME = "mobile";
/**
* 短信登录 参数名称
*/
String SMS_PARAMETER_NAME = "mobile";
/**
* 手机号登录
*/
String APP = "mobile";
/**
* 手机号登录
*/
String APP = "mobile";
/**
* 用户信息
*/
String DETAILS_USER = "user_info";
/**
* 用户信息
*/
String DETAILS_USER = "user_info";
/**
* 不脱敏的权限
*/
String NO_MASK = "no_mask";
/**
* 不脱敏的权限
*/
String NO_MASK = "no_mask";
}
@@ -50,9 +50,4 @@ public interface ServiceNameConstants {
*/
String CODEGEN_SERVICE = "pigx-codegen";
/**
* AIGC智能模块
*/
String AIGC_SERVICE = "pigx-aigc-biz";
}
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author lengleng
@@ -10,7 +10,7 @@ import lombok.Getter;
* 验证码状态
*/
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
public enum CaptchaFlagTypeEnum {
/**
@@ -26,11 +26,11 @@ public enum CaptchaFlagTypeEnum {
/**
* 类型
*/
private String type;
private final String type;
/**
* 描述
*/
private String description;
private final String description;
}
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author lengleng
@@ -10,7 +10,7 @@ import lombok.Getter;
* 字典类型
*/
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
public enum DictTypeEnum {
/**
@@ -26,11 +26,11 @@ public enum DictTypeEnum {
/**
* 类型
*/
private String type;
private final String type;
/**
* 描述
*/
private String description;
private final String description;
}
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author lengleng
@@ -10,7 +10,7 @@ import lombok.Getter;
* 密码是否加密传输
*/
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
public enum EncFlagTypeEnum {
/**
@@ -26,11 +26,11 @@ public enum EncFlagTypeEnum {
/**
* 类型
*/
private String type;
private final String type;
/**
* 描述
*/
private String description;
private final String description;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2026, lengleng All rights reserved.
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -17,15 +17,15 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author lengleng
* @date 2018/8/15 社交登录类型
*/
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
public enum LoginTypeEnum {
/**
@@ -83,11 +83,11 @@ public enum LoginTypeEnum {
/**
* 类型
*/
private String type;
private final String type;
/**
* 描述
*/
private String description;
private final String description;
}
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author lengleng
@@ -10,7 +10,7 @@ import lombok.Getter;
* 菜单类型
*/
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
public enum MenuTypeEnum {
/**
@@ -31,11 +31,11 @@ public enum MenuTypeEnum {
/**
* 类型
*/
private String type;
private final String type;
/**
* 描述
*/
private String description;
private final String description;
}
@@ -0,0 +1,71 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author lengleng
* @date 2026-03-27
* <p>
* 公共参数类型
*/
@Getter
@RequiredArgsConstructor
public enum ParamTypeEnum {
/**
* 默认
*/
DEFAULT("0", "默认"),
/**
* 检索
*/
SEARCH("1", "检索"),
/**
* 原文
*/
ORIGINAL("2", "原文"),
/**
* 报表
*/
REPORT("3", "报表"),
/**
* 安全
*/
SECURITY("4", "安全"),
/**
* 文档
*/
DOCUMENT("5", "文档"),
/**
* 消息
*/
MESSAGE("6", "消息"),
/**
* 其他
*/
OTHER("9", "其他"),
/**
* 网站配置
*/
SITE_CONFIG("10", "网站配置");
/**
* 类型
*/
private final String type;
/**
* 描述
*/
private final String description;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2026, lengleng All rights reserved.
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -17,15 +17,15 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author lengleng
* @date 2018/9/30 流程状态
*/
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
public enum ProcessStatusEnum {
/**
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2026, lengleng All rights reserved.
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -17,15 +17,15 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author lengleng
* @date 2018/9/30 资源类型
*/
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
public enum ResourceTypeEnum {
/**
@@ -42,19 +42,19 @@ public enum StyleTypeEnum {
/**
* 类型
*/
private String style;
private final String style;
/**
* 描述
*/
private String description;
private final String description;
public static String getDesc(String style) {
return Arrays.stream(StyleTypeEnum.values())
.filter(styleTypeEnum -> styleTypeEnum.getStyle().equals(style))
.map(StyleTypeEnum::getDescription)
.findFirst()
.get()
.getDescription();
.orElse("");
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2026, lengleng All rights reserved.
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -17,15 +17,15 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author lengleng
* @date 2018/9/30 流程状态
*/
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
public enum TaskStatusEnum {
/**
@@ -1,10 +1,10 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
public enum UserTypeEnum {
TOB("0", "面向后台应用"), TOC("1", "面向小程序");
@@ -1,7 +1,7 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* yes and no enum
@@ -10,7 +10,7 @@ import lombok.Getter;
* @date 2023/10/25
*/
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
public enum YesNoEnum {
YES("1", "是"), NO("0", "否");
@@ -18,17 +18,15 @@ public enum YesNoEnum {
/**
* 编码
*/
private String code;
private final String code;
/**
* 描述
*/
private String desc;
private final String desc;
/**
* 通过布尔值获取代码
*
* @param bool 布尔
* @return {@link String }
*/
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.common.core.context;
import java.util.List;
/**
* 当前登录用户的最小上下文,仅暴露数据权限/审计/租户等通用能力所需字段。
* 安全实现独立于此接口,避免 data 等通用模块反向依赖 security。
*
* @author lengleng
*/
public interface UserContext {
String getUsername();
Long getDeptId();
List<Long> getRoleIds();
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.common.core.context;
/**
* 用户上下文供给方。security 模块作为唯一实现并以 Spring Bean 形式暴露,
* 通用模块(data、audit 等)只依赖该接口即可。
*
* @author lengleng
*/
public interface UserContextHolder {
/**
* 获取当前登录用户上下文。
* @return 未登录时返回 {@code null}
*/
UserContext get();
}
@@ -17,45 +17,45 @@ import java.time.format.DateTimeFormatter;
*/
public class PigxJavaTimeModule extends SimpleModule {
/**
* 指定序列化规则
*/
public PigxJavaTimeModule() {
super(PackageVersion.VERSION);
/**
* 指定序列化规则
*/
public PigxJavaTimeModule() {
super(PackageVersion.VERSION);
// ======================= 时间序列化规则 ===============================
// yyyy-MM-dd HH:mm:ss
this.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
// yyyy-MM-dd
this.addSerializer(LocalDate.class,
new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
// HH:mm:ss
this.addSerializer(LocalTime.class,
new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
// ======================= 时间序列化规则 ===============================
// yyyy-MM-dd HH:mm:ss
this.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
// yyyy-MM-dd
this.addSerializer(LocalDate.class,
new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
// HH:mm:ss
this.addSerializer(LocalTime.class,
new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
// Instant 类型序列化
this.addSerializer(Instant.class, InstantSerializer.INSTANCE);
// Instant 类型序列化
this.addSerializer(Instant.class, InstantSerializer.INSTANCE);
// Duration 类型序列化
this.addSerializer(Duration.class, DurationSerializer.INSTANCE);
// Duration 类型序列化
this.addSerializer(Duration.class, DurationSerializer.INSTANCE);
// ======================= 时间反序列化规则 ==============================
// yyyy-MM-dd HH:mm:ss
this.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
// yyyy-MM-dd
this.addDeserializer(LocalDate.class,
new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
// HH:mm:ss
this.addDeserializer(LocalTime.class,
new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
// Instant 反序列化
this.addDeserializer(Instant.class, InstantDeserializer.INSTANT);
// ======================= 时间反序列化规则 ==============================
// yyyy-MM-dd HH:mm:ss
this.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
// yyyy-MM-dd
this.addDeserializer(LocalDate.class,
new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
// HH:mm:ss
this.addDeserializer(LocalTime.class,
new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
// Instant 反序列化
this.addDeserializer(Instant.class, InstantDeserializer.INSTANT);
// Duration 反序列化
this.addDeserializer(Duration.class, DurationDeserializer.INSTANCE);
// Duration 反序列化
this.addDeserializer(Duration.class, DurationDeserializer.INSTANCE);
}
}
}
@@ -0,0 +1,22 @@
package com.pig4cloud.pigx.common.core.jackson;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
/**
* Long / long 序列化为 String 的 Jackson 模块,避免前端 JS Number 53-bit 精度丢失。
* <p>
* 与 {@link PigxJavaTimeModule} 拆开是为了职责单一:本 module 只处理整型序列化,
* 单独使用也能保证 Long 字符串化能力,不依赖 {@code JacksonConfiguration}。
*
* @author lengleng
*/
public class PigxLongModule extends SimpleModule {
public PigxLongModule() {
super("PigxLongModule");
this.addSerializer(Long.class, ToStringSerializer.instance);
this.addSerializer(Long.TYPE, ToStringSerializer.instance);
}
}
@@ -10,6 +10,7 @@ import java.lang.annotation.*;
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
public @interface TenantTable {
}
@@ -22,7 +22,7 @@ jasypt:
liteflow:
rule-source: rules/*-rule.xml
print-banner: false
print-execution-log: false
print-execution-log: true
enable: true
# 关闭连表插件的banner