feat: initial iShare project code

This commit is contained in:
purovps
2026-02-16 23:20:59 +08:00
parent 8c83a6fd46
commit 6f270a972e
1910 changed files with 218015 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common</artifactId>
<version>5.2.0</version>
</parent>
<artifactId>pigx-common-core</artifactId>
<packaging>jar</packaging>
<description>pigx 公共工具类核心包</description>
<dependencies>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-json</artifactId>
</dependency>
<!--mvc 相关配置-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<scope>provided</scope>
</dependency>
<!--server-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!--hibernate-validator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--json模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<!--TTL-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>${ttl.version}</version>
</dependency>
<!--swagger 依赖-->
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,86 @@
package com.pig4cloud.pigx.common.core.config;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.pig4cloud.pigx.common.core.jackson.PigxJavaTimeModule;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
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.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.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.StandardCharsets;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.TimeZone;
/**
* JacksonConfig 配置时间转换规则
* {@link com.pig4cloud.pigx.common.core.jackson.PigxJavaTimeModule}、默认时区等
*
* @author L.cm
* @author lengleng
* @author lishangbu
* @date 2020-06-15
*/
@Configuration
@ConditionalOnClass(ObjectMapper.class)
@AutoConfigureBefore(JacksonAutoConfiguration.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class JacksonConfiguration implements WebMvcConfigurer {
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());
};
}
/**
* 增加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;
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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.config;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
/**
* @author lengleng
* @date 2018/11/14
* <p>
* 国际化配置
*/
@Configuration
public class MessageSourceConfiguration {
@Bean
public MessageSource pigxMessageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:i18n/messages");
return messageSource;
}
}

View File

@@ -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.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author lengleng
* @date 2018/8/16 RestTemplate
*/
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

View File

@@ -0,0 +1,118 @@
package com.pig4cloud.pigx.common.core.constant;
/**
* @author lengleng
* @date 2019-04-28
* <p>
* 缓存的key 常量
*/
public interface CacheConstants {
/**
* 全局缓存,在缓存名称上加上该前缀表示该缓存不区分租户,比如:
* <p/>
* {@code @Cacheable(value = CacheConstants.GLOBALLY+CacheConstants.MENU_DETAILS, key = "#roleId + '_menu'", unless = "#result == null")}
*/
String GLOBALLY = "gl:";
/**
* 验证码前缀
*/
String DEFAULT_CODE_KEY = "DEFAULT_CODE_KEY:";
/**
* 菜单信息缓存
*/
String MENU_DETAILS = "menu_details";
/**
* 用户信息缓存
*/
String USER_DETAILS = "user_details";
/**
* 移动端用户信息缓存
*/
String USER_DETAILS_MINI = "user_details_mini";
/**
* 角色信息缓存
*/
String ROLE_DETAILS = "role_details";
/**
* 字典信息缓存
*/
String DICT_DETAILS = "dict_details";
/**
* oauth 客户端信息
*/
String CLIENT_DETAILS_KEY = "pigx_oauth:client:details";
/**
* spring boot admin 事件key
*/
String EVENT_KEY = GLOBALLY + "event_key";
/**
* 路由存放
*/
String ROUTE_KEY = GLOBALLY + "gateway_route_key";
/**
* 内存reload 时间
*/
String ROUTE_JVM_RELOAD_TOPIC = "gateway_jvm_route_reload_topic";
/**
* redis 重新加载 路由信息
*/
String ROUTE_REDIS_RELOAD_TOPIC = "upms_redis_route_reload_topic";
/**
* redis 重新加载客户端信息
*/
String CLIENT_REDIS_RELOAD_TOPIC = "upms_redis_client_reload_topic";
/**
* 公众号 reload
*/
String MP_REDIS_RELOAD_TOPIC = "mp_redis_reload_topic";
/**
* 支付 reload 事件
*/
String PAY_REDIS_RELOAD_TOPIC = "pay_redis_reload_topic";
/**
* 参数缓存
*/
String PARAMS_DETAILS = "params_details";
/**
* 租户缓存 (不区分租户)
*/
String TENANT_DETAILS = GLOBALLY + "tenant_details";
/**
* i18n缓存 (不区分租户)
*/
String I18N_DETAILS = GLOBALLY + "i18n_details";
/**
* 客户端配置缓存
*/
String CLIENT_FLAG = "client_config_flag";
/**
* 登录错误次数
*/
String LOGIN_ERROR_TIMES = "login_error_times";
/**
* oauth 缓存前缀
*/
String PROJECT_OAUTH_ACCESS = "token::access_token";
}

View File

@@ -0,0 +1,138 @@
/*
*
* 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.constant;
/**
* @author lengleng
* @date 2017/10/29
*/
public interface CommonConstants {
/**
* header 中租户ID
*/
String TENANT_ID = "TENANT-ID";
/**
* header 中版本信息
*/
String VERSION = "VERSION";
/**
* 租户ID
*/
Long TENANT_ID_1 = 1L;
/**
* 删除
*/
String STATUS_DEL = "1";
/**
* 正常
*/
String STATUS_NORMAL = "0";
/**
* 锁定
*/
String STATUS_LOCK = "9";
/**
* 菜单树根节点
*/
Long MENU_TREE_ROOT_ID = -1L;
/**
* 编码
*/
String UTF8 = "UTF-8";
/**
* 前端工程名
*/
String FRONT_END_PROJECT = "pigx-ui";
/**
* 移动端工程名
*/
String UNI_END_PROJECT = "pigx-app";
/**
* 后端工程名
*/
String BACK_END_PROJECT = "pigx";
/**
* 公共参数
*/
String PIG_PUBLIC_PARAM_KEY = "PIG_PUBLIC_PARAM_KEY";
/**
* 成功标记
*/
Integer SUCCESS = 0;
/**
* 失败标记
*/
Integer FAIL = 1;
/**
* 默认存储bucket
*/
String BUCKET_NAME = "lengleng";
/**
* 滑块验证码
*/
String IMAGE_CODE_TYPE = "blockPuzzle";
/**
* 验证码开关
*/
String CAPTCHA_FLAG = "captcha_flag";
/**
* 密码传输是否加密
*/
String ENC_FLAG = "enc_flag";
/**
* 客户端允许同时在线数量
*/
String ONLINE_QUANTITY = "online_quantity";
/**
* 请求开始时间
*/
String REQUEST_START_TIME = "REQUEST-START-TIME";
/**
* 当前页
*/
String CURRENT = "current";
/**
* size
*/
String SIZE = "size";
}

View File

@@ -0,0 +1,21 @@
package com.pig4cloud.pigx.common.core.constant;
/**
* 分页相关的参数
*
* @author lishangbu
* @date 2018/11/22
*/
public interface PaginationConstants {
/**
* 当前页
*/
String CURRENT = "current";
/**
* 每页大小
*/
String SIZE = "size";
}

View File

@@ -0,0 +1,252 @@
/*
*
* 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.constant;
/**
* @author lengleng
* @date 2017-12-18
*/
public interface SecurityConstants {
/**
* 启动时是否检查Inner注解安全性
*/
boolean INNER_CHECK = true;
/**
* 刷新
*/
String REFRESH_TOKEN = "refresh_token";
/**
* 验证码有效期
*/
int CODE_TIME = 60;
/**
* 验证码长度
*/
String CODE_SIZE = "4";
/**
* 角色前缀
*/
String ROLE = "ROLE_";
/**
* 前缀
*/
String PIGX_PREFIX = "pigx_";
/**
* token 相关前缀
*/
String TOKEN_PREFIX = "token:";
/**
* oauth 相关前缀
*/
String OAUTH_PREFIX = "oauth:";
/**
* 授权码模式code key 前缀
*/
String OAUTH_CODE_PREFIX = "oauth:code:";
/**
* 项目的license
*/
String PIGX_LICENSE = "https://pig4cloud.com";
/**
* 内部
*/
String FROM_IN = "Y";
/**
* 标志
*/
String FROM = "from";
/**
* 请求header
*/
String HEADER_FROM_IN = FROM + "=" + FROM_IN;
/**
* OAUTH URL
*/
String OAUTH_TOKEN_URL = "/oauth2/token";
/**
* 移动端授权
*/
String GRANT_MOBILE = "mobile";
/**
* TOC 客户端
*/
String HEADER_TOC = "CLIENT-TOC";
/**
* 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";
/**
* 微信获取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";
/**
* 码云获取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";
/**
* 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 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";
/**
* 钉钉同步部门列表
*/
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";
/**
* 钉钉用户详情
*/
String DING_USER_INFO_URL = "https://oapi.dingtalk.com/topapi/v2/user/get";
/**
* {bcrypt} 加密的特征码
*/
String BCRYPT = "{bcrypt}";
/**
* 客户端模式
*/
String CLIENT_CREDENTIALS = "client_credentials";
/**
* 客户端编号
*/
String CLIENT_ID = "client_id";
/**
* 客户端唯一令牌
*/
String CLIENT_RECREATE = "recreate_flag";
/**
* 用户ID字段
*/
String DETAILS_USER_ID = "user_id";
/**
* 用户名
*/
String DETAILS_USERNAME = "username";
/**
* 姓名
*/
String NAME = "name";
/**
* 协议字段
*/
String DETAILS_LICENSE = "license";
/**
* 激活字段 兼容外围系统接入
*/
String ACTIVE = "active";
/**
* AES 加密
*/
String AES = "aes";
/**
* 授权码模式confirm
*/
String CUSTOM_CONSENT_PAGE_URI = "/token/confirm_access";
/**
* {noop} 加密的特征码
*/
String NOOP = "{noop}";
/**
* 短信登录 参数名称
*/
String SMS_PARAMETER_NAME = "mobile";
/**
* 手机号登录
*/
String APP = "mobile";
/**
* 用户信息
*/
String DETAILS_USER = "user_info";
}

View File

@@ -0,0 +1,55 @@
/*
*
* 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.constant;
/**
* @author lengleng
* @date 2018年06月22日16:41:01 服务名称
*/
public interface ServiceNameConstants {
/**
* 认证中心
*/
String AUTH_SERVICE = "pigx-auth";
/**
* UMPS模块
*/
// String UPMS_SERVICE = "pigx-upms-biz";
String UPMS_SERVICE = "as-upms-biz";
/**
* app服务
*/
// String APP_SERVER = "pigx-app-server-biz";
String APP_SERVER = "as-app-server-biz";
/**
* 流程引擎
*/
String FLOW_ENGINE_SERVER = "pigx-flow-engine-biz";
/**
* 流程工单
*/
String FLOW_TASK_SERVER = "pigx-flow-task-biz";
}

View File

@@ -0,0 +1,36 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2020-11-18
* <p>
* 验证码状态
*/
@Getter
@AllArgsConstructor
public enum CaptchaFlagTypeEnum {
/**
* 开启验证码
*/
ON("1", "开启验证码"),
/**
* 关闭验证码
*/
OFF("0", "关闭验证码");
/**
* 类型
*/
private String type;
/**
* 描述
*/
private String description;
}

View File

@@ -0,0 +1,36 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2019-05-16
* <p>
* 字典类型
*/
@Getter
@AllArgsConstructor
public enum DictTypeEnum {
/**
* 字典类型-系统内置(不可修改)
*/
SYSTEM("1", "系统内置"),
/**
* 字典类型-业务类型
*/
BIZ("0", "业务类");
/**
* 类型
*/
private String type;
/**
* 描述
*/
private String description;
}

View File

@@ -0,0 +1,36 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2020-11-18
* <p>
* 密码是否加密传输
*/
@Getter
@AllArgsConstructor
public enum EncFlagTypeEnum {
/**
* 是
*/
YES("1", ""),
/**
* 否
*/
NO("0", "");
/**
* 类型
*/
private String type;
/**
* 描述
*/
private String description;
}

View File

@@ -0,0 +1,93 @@
/*
* 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.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2018/8/15 社交登录类型
*/
@Getter
@AllArgsConstructor
public enum LoginTypeEnum {
/**
* 账号密码登录
*/
PWD("PWD", "账号密码登录"),
/**
* 验证码登录
*/
SMS("SMS", "验证码登录"),
APPSMS("APP-SMS", "APP验证码登录"),
/**
* QQ登录
*/
QQ("QQ", "QQ登录"),
/**
* 微信登录
*/
WECHAT("WX", "微信登录"),
/**
* 微信小程序
*/
MINI_APP("MINI", "微信小程序"),
/**
* 码云登录
*/
GITEE("GITEE", "码云登录"),
/**
* 开源中国登录
*/
OSC("OSC", "开源中国登录"),
/**
* 钉钉
*/
DINGTALK("DINGTALK", "钉钉"),
/**
* 企业微信
*/
WEIXIN_CP("WEIXIN_CP", "企业微信"),
/**
* CAS 登录
*/
CAS("CAS", "CAS 登录");
/**
* 类型
*/
private String type;
/**
* 描述
*/
private String description;
}

View File

@@ -0,0 +1,41 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2020-02-17
* <p>
* 菜单类型
*/
@Getter
@AllArgsConstructor
public enum MenuTypeEnum {
/**
* 左侧菜单
*/
LEFT_MENU("0", "left"),
/**
* 顶部菜单
*/
TOP_MENU("2", "top"),
/**
* 按钮
*/
BUTTON("1", "button");
/**
* 类型
*/
private String type;
/**
* 描述
*/
private String description;
}

View File

@@ -0,0 +1,46 @@
/*
* 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.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2018/9/30 流程状态
*/
@Getter
@AllArgsConstructor
public enum ProcessStatusEnum {
/**
* 激活
*/
ACTIVE("active"),
/**
* 暂停
*/
SUSPEND("suspend");
/**
* 状态
*/
private final String status;
}

View File

@@ -0,0 +1,51 @@
/*
* 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.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2018/9/30 资源类型
*/
@Getter
@AllArgsConstructor
public enum ResourceTypeEnum {
/**
* 图片资源
*/
IMAGE("image", "图片资源"),
/**
* xml资源
*/
XML("xml", "xml资源");
/**
* 类型
*/
private final String type;
/**
* 描述
*/
private final String description;
}

View File

@@ -0,0 +1,57 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* @author lengleng
* @date 2020-01-19
* <p>
* 前端类型类型
*/
@Getter
@AllArgsConstructor
public enum StyleTypeEnum {
/**
* 前端类型-avue 风格
*/
AVUE("0", "avue"),
/**
* 前端类型-element 风格
*/
ELEMENT("1", "element"),
/**
* 前端风格-uview 风格
*/
UVIEW("2", "uview"),
/**
* magic
*/
MAGIC("3", "magic"),
/**
* element-plus
*/
PLUS("4", "plus");
/**
* 类型
*/
private String style;
/**
* 描述
*/
private String description;
public static String getDecs(String style) {
return Arrays.stream(StyleTypeEnum.values()).filter(styleTypeEnum -> styleTypeEnum.getStyle().equals(style))
.findFirst().get().getDescription();
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2018/9/30 流程状态
*/
@Getter
@AllArgsConstructor
public enum TaskStatusEnum {
/**
* 未提交
*/
UNSUBMIT("0", "未提交"),
/**
* 审核中
*/
CHECK("1", "审核中"),
/**
* 已完成
*/
COMPLETED("2", "已完成"),
/**
* 驳回
*/
OVERRULE("9", "驳回");
/**
* 类型
*/
private final String status;
/**
* 描述
*/
private final String description;
}

View File

@@ -0,0 +1,22 @@
package com.pig4cloud.pigx.common.core.constant.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum UserTypeEnum {
TOB("0", "面向后台应用"), TOC("1", "面向小程序");
/**
* 类型
*/
private final String status;
/**
* 描述
*/
private final String description;
}

View File

@@ -0,0 +1,49 @@
/*
*
* 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.exception;
import lombok.NoArgsConstructor;
/**
* @author lengleng
* @date 😴2018年06月22日16:21:57
*/
@NoArgsConstructor
public class CheckedException extends RuntimeException {
private static final long serialVersionUID = 1L;
public CheckedException(String message) {
super(message);
}
public CheckedException(Throwable cause) {
super(cause);
}
public CheckedException(String message, Throwable cause) {
super(message, cause);
}
public CheckedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@@ -0,0 +1,113 @@
package com.pig4cloud.pigx.common.core.exception;
/**
* 错误编码
*
* @author lengleng
* @date 2022/3/30
*/
public interface ErrorCodes {
/**
* 系统编码错误
*/
String SYS_PARAM_CONFIG_ERROR = "sys.param.config.error";
/**
* 系统内置参数不能删除
*/
String SYS_PARAM_DELETE_SYSTEM = "sys.param.delete.system";
/**
* 用户已存在
*/
String SYS_USER_USERNAME_EXISTING = "sys.user.username.existing";
/**
* 用户已存在
*/
String SYS_USER_PHONE_EXISTING = "sys.user.phone.existing";
/**
* 用户原密码错误,修改失败
*/
String SYS_USER_UPDATE_PASSWORDERROR = "sys.user.update.passwordError";
/**
* 用户信息为空
*/
String SYS_USER_USERINFO_EMPTY = "sys.user.userInfo.empty";
/**
* 获取当前用户信息失败
*/
String SYS_USER_QUERY_ERROR = "sys.user.query.error";
String SYS_USER_IMPORT_SUCCEED = "sys.user.import.succeed";
/**
* 部门名称不存在
*/
String SYS_DEPT_DEPTNAME_INEXISTENCE = "sys.dept.deptName.inexistence";
/**
* 岗位名称不存在
*/
String SYS_POST_POSTNAME_INEXISTENCE = "sys.post.postName.inexistence";
/**
* 岗位名称或编码已经存在
*/
String SYS_POST_NAMEORCODE_EXISTING = "sys.post.nameOrCode.existing";
/**
* 角色名称不存在
*/
String SYS_ROLE_ROLENAME_INEXISTENCE = "sys.role.roleName.inexistence";
/**
* 角色名或角色编码已经存在
*/
String SYS_ROLE_NAMEORCODE_EXISTING = "sys.role.nameOrCode.existing";
/**
* 菜单存在下级节点 删除失败
*/
String SYS_MENU_DELETE_EXISTING = "sys.menu.delete.existing";
/**
* 系统内置字典不允许删除
*/
String SYS_DICT_DELETE_SYSTEM = "sys.dict.delete.system";
/**
* 系统内置字典不能修改
*/
String SYS_DICT_UPDATE_SYSTEM = "sys.dict.update.system";
/**
* 验证码发送频繁
*/
String SYS_APP_SMS_OFTEN = "sys.app.sms.often";
/**
* 手机号未注册
*/
String SYS_APP_PHONE_UNREGISTERED = "sys.app.phone.unregistered";
/**
* 企微调用接口错误
*/
String SYS_CONNECT_CP_DEPT_SYNC_ERROR = "sys.connect.cp.dept.sync.error";
/**
* 企微调用接口错误
*/
String SYS_CONNECT_CP_USER_SYNC_ERROR = "sys.connect.cp.user.sync.error";
/**
* 用户信息为空
*/
String APP_USER_USERINFO_EMPTY = "app.user.userInfo.empty";
}

View File

@@ -0,0 +1,37 @@
/*
*
* 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.exception;
/**
* @author lengleng
* @date 2018年06月22日16:22:15
*/
public class ValidateCodeException extends RuntimeException {
private static final long serialVersionUID = -7285211528095468156L;
public ValidateCodeException() {
}
public ValidateCodeException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,44 @@
package com.pig4cloud.pigx.common.core.factory;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
import org.springframework.lang.Nullable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
/**
* @author lengleng
* @date 2022/3/29
* <p>
* 读取自定义 yaml 文件工厂类
*/
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {
Properties propertiesFromYaml = loadYamlIntoProperties(resource);
String sourceName = name != null ? name : resource.getResource().getFilename();
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
}
private Properties loadYamlIntoProperties(EncodedResource resource) throws FileNotFoundException {
try {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
}
catch (IllegalStateException e) {
Throwable cause = e.getCause();
if (cause instanceof FileNotFoundException)
throw (FileNotFoundException) e.getCause();
throw e;
}
}
}

View File

@@ -0,0 +1,64 @@
package com.pig4cloud.pigx.common.core.jackson;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.PackageVersion;
import com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
/**
* java 8 时间默认序列化
*
* @author L.cm
* @author lishanbu
*/
public class PigxJavaTimeModule extends SimpleModule {
/**
* 指定序列化规则
*/
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)));
// Instant 类型序列化
this.addSerializer(Instant.class, InstantSerializer.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);
}
}

View File

@@ -0,0 +1,60 @@
/*
* 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.sensitive;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 对象脱敏注解
*
* @author mayee
* @version v1.0
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerialize.class)
public @interface Sensitive {
/**
* 脱敏数据类型, 非Customer时, 将忽略 refixNoMaskLen 和 suffixNoMaskLen 和 maskStr
*/
SensitiveTypeEnum type() default SensitiveTypeEnum.CUSTOMER;
/**
* 前置不需要打码的长度
*/
int prefixNoMaskLen() default 0;
/**
* 后置不需要打码的长度
*/
int suffixNoMaskLen() default 0;
/**
* 用什么打码
*/
String maskStr() default "*";
}

View File

@@ -0,0 +1,110 @@
/*
* 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.sensitive;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.pig4cloud.pigx.common.core.util.DesensitizedUtils;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.io.IOException;
import java.util.Objects;
/**
* @author lengleng
* @date 2019-08-13
* <p>
* 脱敏序列化
*/
@NoArgsConstructor
@AllArgsConstructor
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {
private SensitiveTypeEnum type;
private Integer prefixNoMaskLen;
private Integer suffixNoMaskLen;
private String maskStr;
@Override
public void serialize(final String origin, final JsonGenerator jsonGenerator,
final SerializerProvider serializerProvider) throws IOException {
switch (type) {
case CHINESE_NAME:
jsonGenerator.writeString(DesensitizedUtils.chineseName(origin));
break;
case ID_CARD:
jsonGenerator.writeString(DesensitizedUtils.idCardNum(origin));
break;
case FIXED_PHONE:
jsonGenerator.writeString(DesensitizedUtils.fixedPhone(origin));
break;
case MOBILE_PHONE:
jsonGenerator.writeString(DesensitizedUtils.mobilePhone(origin));
break;
case ADDRESS:
jsonGenerator.writeString(DesensitizedUtils.address(origin));
break;
case EMAIL:
jsonGenerator.writeString(DesensitizedUtils.email(origin));
break;
case BANK_CARD:
jsonGenerator.writeString(DesensitizedUtils.bankCard(origin));
break;
case PASSWORD:
jsonGenerator.writeString(DesensitizedUtils.password(origin));
break;
case KEY:
jsonGenerator.writeString(DesensitizedUtils.key(origin));
break;
case CUSTOMER:
jsonGenerator
.writeString(DesensitizedUtils.desValue(origin, prefixNoMaskLen, suffixNoMaskLen, maskStr));
break;
default:
throw new IllegalArgumentException("Unknow sensitive type enum " + type);
}
}
@Override
public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider,
final BeanProperty beanProperty) throws JsonMappingException {
if (beanProperty != null) {
if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class);
if (sensitive == null) {
sensitive = beanProperty.getContextAnnotation(Sensitive.class);
}
if (sensitive != null) {
return new SensitiveSerialize(sensitive.type(), sensitive.prefixNoMaskLen(),
sensitive.suffixNoMaskLen(), sensitive.maskStr());
}
}
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
}
return serializerProvider.findNullValueSerializer(null);
}
}

View File

@@ -0,0 +1,69 @@
/*
* 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.sensitive;
/**
* 敏感信息枚举类
*
* @author mayee
* @version v1.0
**/
public enum SensitiveTypeEnum {
/**
* 自定义
*/
CUSTOMER,
/**
* 用户名, 刘*华, 徐*
*/
CHINESE_NAME,
/**
* 身份证号, 110110********1234
*/
ID_CARD,
/**
* 座机号, ****1234
*/
FIXED_PHONE,
/**
* 手机号, 176****1234
*/
MOBILE_PHONE,
/**
* 地址, 北京********
*/
ADDRESS,
/**
* 电子邮件, s*****o@xx.com
*/
EMAIL,
/**
* 银行卡, 622202************1234
*/
BANK_CARD,
/**
* 密码, 永远是 ******, 与长度无关
*/
PASSWORD,
/**
* 密钥, 【密钥】密钥除了最后三位其他都是***, 与长度无关
*/
KEY
}

View File

@@ -0,0 +1,113 @@
/*
*
* 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.util;
import lombok.experimental.UtilityClass;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.web.method.HandlerMethod;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* 类工具类
*
* @author L.cm
*/
@UtilityClass
public class ClassUtils extends org.springframework.util.ClassUtils {
private final ParameterNameDiscoverer PARAMETERNAMEDISCOVERER = new DefaultParameterNameDiscoverer();
/**
* 获取方法参数信息
* @param constructor 构造器
* @param parameterIndex 参数序号
* @return {MethodParameter}
*/
public MethodParameter getMethodParameter(Constructor<?> constructor, int parameterIndex) {
MethodParameter methodParameter = new SynthesizingMethodParameter(constructor, parameterIndex);
methodParameter.initParameterNameDiscovery(PARAMETERNAMEDISCOVERER);
return methodParameter;
}
/**
* 获取方法参数信息
* @param method 方法
* @param parameterIndex 参数序号
* @return {MethodParameter}
*/
public MethodParameter getMethodParameter(Method method, int parameterIndex) {
MethodParameter methodParameter = new SynthesizingMethodParameter(method, parameterIndex);
methodParameter.initParameterNameDiscovery(PARAMETERNAMEDISCOVERER);
return methodParameter;
}
/**
* 获取Annotation
* @param method Method
* @param annotationType 注解类
* @param <A> 泛型标记
* @return {Annotation}
*/
public <A extends Annotation> A getAnnotation(Method method, Class<A> annotationType) {
Class<?> targetClass = method.getDeclaringClass();
// The method may be on an interface, but we need attributes from the target
// class.
// If the target class is null, the method will be unchanged.
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
// If we are dealing with method with generic parameters, find the original
// method.
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
// 先找方法,再找方法上的类
A annotation = AnnotatedElementUtils.findMergedAnnotation(specificMethod, annotationType);
if (null != annotation) {
return annotation;
}
// 获取类上面的Annotation可能包含组合注解故采用spring的工具类
return AnnotatedElementUtils.findMergedAnnotation(specificMethod.getDeclaringClass(), annotationType);
}
/**
* 获取Annotation
* @param handlerMethod HandlerMethod
* @param annotationType 注解类
* @param <A> 泛型标记
* @return {Annotation}
*/
public <A extends Annotation> A getAnnotation(HandlerMethod handlerMethod, Class<A> annotationType) {
// 先找方法,再找方法上的类
A annotation = handlerMethod.getMethodAnnotation(annotationType);
if (null != annotation) {
return annotation;
}
// 获取类上面的Annotation可能包含组合注解故采用spring的工具类
Class<?> beanType = handlerMethod.getBeanType();
return AnnotatedElementUtils.findMergedAnnotation(beanType, annotationType);
}
}

View File

@@ -0,0 +1,171 @@
/*
* 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.util;
import cn.hutool.core.util.StrUtil;
/**
* 脱敏工具类
*
* @author mayee
* @version v1.0
**/
public class DesensitizedUtils {
/**
* 对字符串进行脱敏操作
* @param origin 原始字符串
* @param prefixNoMaskLen 左侧需要保留几位明文字段
* @param suffixNoMaskLen 右侧需要保留几位明文字段
* @param maskStr 用于遮罩的字符串, 如'*'
* @return 脱敏后结果
*/
public static String desValue(String origin, int prefixNoMaskLen, int suffixNoMaskLen, String maskStr) {
if (origin == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0, n = origin.length(); i < n; i++) {
if (i < prefixNoMaskLen) {
sb.append(origin.charAt(i));
continue;
}
if (i > (n - suffixNoMaskLen - 1)) {
sb.append(origin.charAt(i));
continue;
}
sb.append(maskStr);
}
return sb.toString();
}
/**
* 【中文姓名】只显示最后一个汉字,其他隐藏为星号,比如:**梦
* @param fullName 姓名
* @return 结果
*/
public static String chineseName(String fullName) {
if (fullName == null) {
return null;
}
return desValue(fullName, 0, 1, "*");
}
/**
* 【身份证号】显示前六位, 四位其他隐藏。共计18位或者15位比如340304*******1234
* @param id 身份证号码
* @return 结果
*/
public static String idCardNum(String id) {
return desValue(id, 6, 4, "*");
}
/**
* 【固定电话】后四位,其他隐藏,比如 ****1234
* @param num 固定电话
* @return 结果
*/
public static String fixedPhone(String num) {
return desValue(num, 0, 4, "*");
}
/**
* 【手机号码】前三位后四位其他隐藏比如135****6810
* @param num 手机号码
* @return 结果
*/
public static String mobilePhone(String num) {
return desValue(num, 3, 4, "*");
}
/**
* 【地址】只显示到地区,不显示详细地址,比如:北京市海淀区****
* @param address 地址
* @return 结果
*/
public static String address(String address) {
return desValue(address, 6, 0, "*");
}
/**
* 【电子邮箱 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示比如d**@126.com
* @param email 电子邮箱
* @return 结果
*/
public static String email(String email) {
if (email == null) {
return null;
}
int index = StrUtil.indexOf(email, '@');
if (index <= 1) {
return email;
}
String preEmail = desValue(email.substring(0, index), 1, 0, "*");
return preEmail + email.substring(index);
}
/**
* 【银行卡号】前六位后四位其他用星号隐藏每位1个星号比如622260**********1234
* @param cardNum 银行卡号
* @return 结果
*/
public static String bankCard(String cardNum) {
return desValue(cardNum, 6, 4, "*");
}
/**
* 【密码】密码的全部字符都用*代替,比如:******
* @param password 密码
* @return 结果
*/
public static String password(String password) {
if (password == null) {
return null;
}
return "******";
}
/**
* 【密钥】密钥除了最后三位,全部都用*代替,比如:***xdS 脱敏后长度为6如果明文长度不足三位则按实际长度显示剩余位置补*
* @param key 密钥
* @return 结果
*/
public static String key(String key) {
if (key == null) {
return null;
}
int viewLength = 6;
StringBuilder tmpKey = new StringBuilder(desValue(key, 0, 3, "*"));
if (tmpKey.length() > viewLength) {
return tmpKey.substring(tmpKey.length() - viewLength);
}
else if (tmpKey.length() < viewLength) {
int buffLength = viewLength - tmpKey.length();
for (int i = 0; i < buffLength; i++) {
tmpKey.insert(0, "*");
}
return tmpKey.toString();
}
else {
return tmpKey.toString();
}
}
}

View File

@@ -0,0 +1,25 @@
package com.pig4cloud.pigx.common.core.util;
/**
* @author lengleng
* @date 2020/9/29
* <p>
* 字符串处理,方便其他模块解耦处理
*/
public interface KeyStrResolver {
/**
* 字符串加工
* @param in 输入字符串
* @param split 分割符
* @return 输出字符串
*/
String extract(String in, String split);
/**
* 字符串获取
* @return 模块返回字符串
*/
String key();
}

View File

@@ -0,0 +1,47 @@
package com.pig4cloud.pigx.common.core.util;
import lombok.experimental.UtilityClass;
import org.springframework.context.MessageSource;
import java.util.Locale;
/**
* i18n 工具类
*
* @author lengleng
* @date 2022/3/30
*/
@UtilityClass
public class MsgUtils {
/**
* 通过code 获取中文错误信息
* @param code
* @return
*/
public String getMessage(String code) {
MessageSource messageSource = SpringContextHolder.getBean("pigxMessageSource");
return messageSource.getMessage(code, null, Locale.CHINA);
}
/**
* 通过code 和参数获取中文错误信息
* @param code
* @return
*/
public String getMessage(String code, Object... objects) {
MessageSource messageSource = SpringContextHolder.getBean("pigxMessageSource");
return messageSource.getMessage(code, objects, Locale.CHINA);
}
/**
* security 通过code 和参数获取中文错误信息
* @param code
* @return
*/
public String getSecurityMessage(String code, Object... objects) {
MessageSource messageSource = SpringContextHolder.getBean("securityMessageSource");
return messageSource.getMessage(code, objects, Locale.CHINA);
}
}

View File

@@ -0,0 +1,100 @@
/*
*
* 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.util;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 响应信息主体
*
* @param <T>
* @author lengleng
*/
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Schema(description = "响应信息主体")
public class R<T> implements Serializable {
private static final long serialVersionUID = 1L;
@Getter
@Setter
@Schema(description = "返回标记:成功标记=0失败标记=1")
private int code;
@Getter
@Setter
@Schema(description = "返回信息")
private String msg;
@Getter
@Setter
@Schema(description = "数据")
private T data;
public static <T> R<T> ok() {
return restResult(null, CommonConstants.SUCCESS, null);
}
public static <T> R<T> ok(T data) {
return restResult(data, CommonConstants.SUCCESS, null);
}
public static <T> R<T> ok(T data, String msg) {
return restResult(data, CommonConstants.SUCCESS, msg);
}
public static <T> R<T> failed() {
return restResult(null, CommonConstants.FAIL, null);
}
public static <T> R<T> failed(String msg) {
return restResult(null, CommonConstants.FAIL, msg);
}
public static <T> R<T> failed(T data) {
return restResult(data, CommonConstants.FAIL, null);
}
public static <T> R<T> failed(T data, String msg) {
return restResult(data, CommonConstants.FAIL, msg);
}
static <T> R<T> restResult(T data, int code, String msg) {
R<T> apiResult = new R<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
return apiResult;
}
public boolean isOk() {
return this.code == CommonConstants.SUCCESS;
}
}

View File

@@ -0,0 +1,289 @@
/*
*
* 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.util;
import cn.hutool.core.util.ObjectUtil;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
/**
* 简化{@code R<T>} 的访问操作,例子 <pre>
* R<Integer> result = R.ok(0);
* // 使用场景1: 链式操作: 断言然后消费
* RetOps.of(result)
* .assertCode(-1,r -> new RuntimeException("error "+r.getCode()))
* .assertDataNotEmpty(r -> new IllegalStateException("oops!"))
* .useData(System.out::println);
*
* // 使用场景2: 读取原始值(data),这里返回的是Optional
* RetOps.of(result).getData().orElse(null);
*
* // 使用场景3: 类型转换
* R<String> s = RetOps.of(result)
* .assertDataNotNull(r -> new IllegalStateException("nani??"))
* .map(i -> Integer.toHexString(i))
* .peek();
* </pre>
*
* @author CJ (power4j@outlook.com)
* @date 2022/5/12
* @since 4.4
*/
public class RetOps<T> {
/** 状态码为成功 */
public static final Predicate<R<?>> CODE_SUCCESS = r -> CommonConstants.SUCCESS == r.getCode();
/** 数据有值 */
public static final Predicate<R<?>> HAS_DATA = r -> ObjectUtil.isNotEmpty(r.getData());
/** 数据有值,并且包含元素 */
public static final Predicate<R<?>> HAS_ELEMENT = r -> ObjectUtil.isNotEmpty(r.getData());
/** 状态码为成功并且有值 */
public static final Predicate<R<?>> DATA_AVAILABLE = CODE_SUCCESS.and(HAS_DATA);
private final R<T> original;
// ~ 初始化
// ===================================================================================================
RetOps(R<T> original) {
this.original = original;
}
public static <T> RetOps<T> of(R<T> original) {
return new RetOps<>(Objects.requireNonNull(original));
}
// ~ 杂项方法
// ===================================================================================================
/**
* 观察原始值
* @return R
*/
public R<T> peek() {
return original;
}
/**
* 读取{@code code}的值
* @return 返回code的值
*/
public int getCode() {
return original.getCode();
}
/**
* 读取{@code data}的值
* @return 返回 Optional 包装的data
*/
public Optional<T> getData() {
return Optional.ofNullable(original.getData());
}
/**
* 有条件地读取{@code data}的值
* @param predicate 断言函数
* @return 返回 Optional 包装的data,如果断言失败返回empty
*/
public Optional<T> getDataIf(Predicate<? super R<?>> predicate) {
return predicate.test(original) ? getData() : Optional.empty();
}
/**
* 读取{@code msg}的值
* @return 返回Optional包装的 msg
*/
public Optional<String> getMsg() {
return Optional.ofNullable(original.getMsg());
}
/**
* 对{@code code}的值进行相等性测试
* @param value 基准值
* @return 返回ture表示相等
*/
public boolean codeEquals(int value) {
return original.getCode() == value;
}
/**
* 对{@code code}的值进行相等性测试
* @param value 基准值
* @return 返回ture表示不相等
*/
public boolean codeNotEquals(int value) {
return !codeEquals(value);
}
/**
* 是否成功
* @return 返回ture表示成功
* @see CommonConstants#SUCCESS
*/
public boolean isSuccess() {
return codeEquals(CommonConstants.SUCCESS);
}
/**
* 是否失败
* @return 返回ture表示失败
*/
public boolean notSuccess() {
return !isSuccess();
}
// ~ 链式操作
// ===================================================================================================
/**
* 断言{@code code}的值
* @param expect 预期的值
* @param func 用户函数,负责创建异常对象
* @param <Ex> 异常类型
* @return 返回实例,以便于继续进行链式操作
* @throws Ex 断言失败时抛出
*/
public <Ex extends Exception> RetOps<T> assertCode(int expect, Function<? super R<T>, ? extends Ex> func)
throws Ex {
if (codeNotEquals(expect)) {
throw func.apply(original);
}
return this;
}
/**
* 断言成功
* @param func 用户函数,负责创建异常对象
* @param <Ex> 异常类型
* @return 返回实例,以便于继续进行链式操作
* @throws Ex 断言失败时抛出
*/
public <Ex extends Exception> RetOps<T> assertSuccess(Function<? super R<T>, ? extends Ex> func) throws Ex {
return assertCode(CommonConstants.SUCCESS, func);
}
/**
* 断言业务数据有值
* @param func 用户函数,负责创建异常对象
* @param <Ex> 异常类型
* @return 返回实例,以便于继续进行链式操作
* @throws Ex 断言失败时抛出
*/
public <Ex extends Exception> RetOps<T> assertDataNotNull(Function<? super R<T>, ? extends Ex> func) throws Ex {
if (Objects.isNull(original.getData())) {
throw func.apply(original);
}
return this;
}
/**
* 断言业务数据有值,并且包含元素
* @param func 用户函数,负责创建异常对象
* @param <Ex> 异常类型
* @return 返回实例,以便于继续进行链式操作
* @throws Ex 断言失败时抛出
*/
public <Ex extends Exception> RetOps<T> assertDataNotEmpty(Function<? super R<T>, ? extends Ex> func) throws Ex {
if (ObjectUtil.isEmpty(original.getData())) {
throw func.apply(original);
}
return this;
}
/**
* 对业务数据(data)转换
* @param mapper 业务数据转换函数
* @param <U> 数据类型
* @return 返回新实例,以便于继续进行链式操作
*/
public <U> RetOps<U> map(Function<? super T, ? extends U> mapper) {
R<U> result = R.restResult(mapper.apply(original.getData()), original.getCode(), original.getMsg());
return of(result);
}
/**
* 对业务数据(data)转换
* @param predicate 断言函数
* @param mapper 业务数据转换函数
* @param <U> 数据类型
* @return 返回新实例,以便于继续进行链式操作
* @see RetOps#CODE_SUCCESS
* @see RetOps#HAS_DATA
* @see RetOps#HAS_ELEMENT
* @see RetOps#DATA_AVAILABLE
*/
public <U> RetOps<U> mapIf(Predicate<? super R<T>> predicate, Function<? super T, ? extends U> mapper) {
R<U> result = R.restResult(mapper.apply(original.getData()), original.getCode(), original.getMsg());
return of(result);
}
// ~ 数据消费
// ===================================================================================================
/**
* 消费数据,注意此方法保证数据可用
* @param consumer 消费函数
*/
public void useData(Consumer<? super T> consumer) {
consumer.accept(original.getData());
}
/**
* 条件消费(错误代码匹配某个值)
* @param consumer 消费函数
* @param codes 错误代码集合,匹配任意一个则调用消费函数
*/
public void useDataOnCode(Consumer<? super T> consumer, int... codes) {
useDataIf(o -> Arrays.stream(codes).filter(c -> original.getCode() == c).findFirst().isPresent(), consumer);
}
/**
* 条件消费(错误代码表示成功)
* @param consumer 消费函数
*/
public void useDataIfSuccess(Consumer<? super T> consumer) {
useDataIf(CODE_SUCCESS, consumer);
}
/**
* 条件消费
* @param predicate 断言函数
* @param consumer 消费函数,断言函数返回{@code true}时被调用
* @see RetOps#CODE_SUCCESS
* @see RetOps#HAS_DATA
* @see RetOps#HAS_ELEMENT
* @see RetOps#DATA_AVAILABLE
*/
public void useDataIf(Predicate<? super R<T>> predicate, Consumer<? super T> consumer) {
if (predicate.test(original)) {
consumer.accept(original.getData());
}
}
}

View File

@@ -0,0 +1,127 @@
/*
*
* 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.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author lengleng
* @date 2018/6/27 Spring 工具类
*/
@Slf4j
@Service
@Lazy(false)
public class SpringContextHolder implements BeanFactoryPostProcessor, ApplicationContextAware, DisposableBean {
private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext = null;
/**
* 取得存储在静态变量中的ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* BeanFactoryPostProcessor, 注入Context到静态变量中.
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
SpringContextHolder.beanFactory = factory;
}
/**
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextHolder.applicationContext = applicationContext;
}
public static ListableBeanFactory getBeanFactory() {
return null == beanFactory ? applicationContext : beanFactory;
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
return (T) getBeanFactory().getBean(name);
}
/**
* 从静态变量applicationContext中取得Bean, Map<Bean名称实现类></>
*/
public static <T> Map<String, T> getBeansOfType(Class<T> type) {
return getBeanFactory().getBeansOfType(type);
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(Class<T> requiredType) {
return getBeanFactory().getBean(requiredType);
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
public static void clearHolder() {
if (log.isDebugEnabled()) {
log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
}
applicationContext = null;
}
/**
* 发布事件
* @param event
*/
public static void publishEvent(ApplicationEvent event) {
if (applicationContext == null) {
return;
}
applicationContext.publishEvent(event);
}
/**
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
*/
@Override
public void destroy() {
SpringContextHolder.clearHolder();
}
}

View File

@@ -0,0 +1,31 @@
package com.pig4cloud.pigx.common.core.util;
/**
* 校验类型
*
* @author lengleng
* @date 2022/4/26
*/
public class ValidGroup {
/**
* 插入组
*
* @author lengleng
* @date 2022/4/26
*/
public static interface Insert {
}
/**
* 编辑组
*
* @author lengleng
* @date 2022/4/26
*/
public static interface Update {
}
}

View File

@@ -0,0 +1,239 @@
/*
*
* 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.util;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
/**
* Miscellaneous utilities for web applications.
*
* @author L.cm
*/
@Slf4j
@UtilityClass
public class WebUtils extends org.springframework.web.util.WebUtils {
private final String BASIC_ = "Basic ";
private final String UNKNOWN = "unknown";
/**
* 判断是否ajax请求 spring ajax 返回含有 ResponseBody 或者 RestController注解
* @param handlerMethod HandlerMethod
* @return 是否ajax请求
*/
public boolean isBody(HandlerMethod handlerMethod) {
ResponseBody responseBody = ClassUtils.getAnnotation(handlerMethod, ResponseBody.class);
return responseBody != null;
}
/**
* 读取cookie
* @param name cookie name
* @return cookie value
*/
public String getCookieVal(String name) {
HttpServletRequest request = WebUtils.getRequest();
Assert.notNull(request, "request from RequestContextHolder is null");
return getCookieVal(request, name);
}
/**
* 读取cookie
* @param request HttpServletRequest
* @param name cookie name
* @return cookie value
*/
public String getCookieVal(HttpServletRequest request, String name) {
Cookie cookie = getCookie(request, name);
return cookie != null ? cookie.getValue() : null;
}
/**
* 清除 某个指定的cookie
* @param response HttpServletResponse
* @param key cookie key
*/
public void removeCookie(HttpServletResponse response, String key) {
setCookie(response, key, null, 0);
}
/**
* 设置cookie
* @param response HttpServletResponse
* @param name cookie name
* @param value cookie value
* @param maxAgeInSeconds maxage
*/
public void setCookie(HttpServletResponse response, String name, String value, int maxAgeInSeconds) {
Cookie cookie = new Cookie(name, value);
cookie.setPath("/");
cookie.setMaxAge(maxAgeInSeconds);
cookie.setHttpOnly(true);
response.addCookie(cookie);
}
/**
* 获取 HttpServletRequest
* @return {HttpServletRequest}
*/
public HttpServletRequest getRequest() {
try {
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
return ((ServletRequestAttributes) requestAttributes).getRequest();
}
catch (Exception e) {
return null;
}
}
/**
* 获取 HttpServletResponse
* @return {HttpServletResponse}
*/
public HttpServletResponse getResponse() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
}
/**
* 返回json
* @param response HttpServletResponse
* @param result 结果对象
*/
public void renderJson(HttpServletResponse response, Object result) {
renderJson(response, result, MediaType.APPLICATION_JSON_VALUE);
}
/**
* 返回json
* @param response HttpServletResponse
* @param result 结果对象
* @param contentType contentType
*/
public void renderJson(HttpServletResponse response, Object result, String contentType) {
response.setCharacterEncoding("UTF-8");
response.setContentType(contentType);
try (PrintWriter out = response.getWriter()) {
out.append(JSONUtil.toJsonStr(result));
}
catch (IOException e) {
log.error(e.getMessage(), e);
}
}
/**
* 获取ip
* @return {String}
*/
public String getIP() {
return getIP(WebUtils.getRequest());
}
/**
* 获取ip
* @param request HttpServletRequest
* @return {String}
*/
public String getIP(HttpServletRequest request) {
Assert.notNull(request, "HttpServletRequest is null");
String ip = request.getHeader("X-Requested-For");
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StrUtil.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return StrUtil.isBlank(ip) ? null : ip.split(",")[0];
}
/**
* 解析 client id
* @param header
* @param defVal
* @return 如果解析失败返回默认值
*/
public String extractClientId(String header, final String defVal) {
if (header == null || !header.startsWith(BASIC_)) {
log.debug("请求头中client信息为空: {}", header);
return defVal;
}
byte[] base64Token = header.substring(6).getBytes(StandardCharsets.UTF_8);
byte[] decoded;
try {
decoded = Base64.decode(base64Token);
}
catch (IllegalArgumentException e) {
log.debug("Failed to decode basic authentication token: {}", header);
return defVal;
}
String token = new String(decoded, StandardCharsets.UTF_8);
int delim = token.indexOf(":");
if (delim == -1) {
log.debug("Invalid basic authentication token: {}", header);
return defVal;
}
return token.substring(0, delim);
}
/**
* 从请求头中解析 client id
* @param header
* @return
*/
public Optional<String> extractClientId(String header) {
return Optional.ofNullable(extractClientId(header, null));
}
}

View File

@@ -0,0 +1,4 @@
com.pig4cloud.pigx.common.core.config.JacksonConfiguration
com.pig4cloud.pigx.common.core.config.MessageSourceConfiguration
com.pig4cloud.pigx.common.core.config.RestTemplateConfiguration
com.pig4cloud.pigx.common.core.util.SpringContextHolder

View File

@@ -0,0 +1,16 @@
${AnsiColor.BRIGHT_YELLOW}
::::::::: ::::::::::: :::::::: ::: :::
:+: :+: :+: :+: :+: :+: :+:
+:+ +:+ +:+ +:+ +:+ +:+
+#++:++#+ +#+ :#: +#++:+
+#+ +#+ +#+ +#+# +#+ +#+
#+# #+# #+# #+# #+# #+#
### ########### ######## ### ###
www.pig4cloud.com
Pig Microservice Architecture
${AnsiColor.DEFAULT}

View File

@@ -0,0 +1,21 @@
sys.user.update.passwordError=\u539F\u5BC6\u7801\u9519\u8BEF\uFF0C\u4FEE\u6539\u5931\u8D25
sys.user.query.error=\u83B7\u53D6\u5F53\u524D\u7528\u6237\u4FE1\u606F\u5931\u8D25
sys.user.import.succeed=\u7528\u6237\u5BFC\u5165\u6210\u529F\uFF0C\u9ED8\u8BA4\u5BC6\u7801\u4E3A\u624B\u673A\u53F7
sys.user.username.existing={0} \u7528\u6237\u540D\u5DF2\u5B58\u5728
sys.user.phone.existing={0} \u624b\u673a\u53f7\u5df2\u5b58\u5728
sys.user.userInfo.empty={0} \u7528\u6237\u4FE1\u606F\u4E3A\u7A7A
sys.dept.deptName.inexistence={0} \u90E8\u95E8\u540D\u79F0\u4E0D\u5B58\u5728
sys.post.postName.inexistence={0} \u5C97\u4F4D\u540D\u79F0\u4E0D\u5B58\u5728
sys.post.nameOrCode.existing={0} {1} \u5C97\u4F4D\u540D\u6216\u5C97\u4F4D\u7F16\u7801\u5DF2\u7ECF\u5B58\u5728
sys.role.roleName.inexistence={0} \u89D2\u8272\u540D\u79F0\u4E0D\u5B58\u5728
sys.role.nameOrCode.existing={0} {1} \u89D2\u8272\u540D\u6216\u89D2\u8272\u7F16\u7801\u5DF2\u7ECF\u5B58\u5728
sys.param.delete.system=\u7CFB\u7EDF\u5185\u7F6E\u53C2\u6570\u4E0D\u80FD\u5220\u9664
sys.param.config.error={0} \u7CFB\u7EDF\u53C2\u6570\u914D\u7F6E\u9519\u8BEF
sys.menu.delete.existing=\u83DC\u5355\u542B\u6709\u4E0B\u7EA7\u4E0D\u80FD\u5220\u9664
sys.app.sms.often=\u9A8C\u8BC1\u7801\u53D1\u9001\u8FC7\u9891\u7E41
sys.app.phone.unregistered={0} \u624B\u673A\u53F7\u672A\u6CE8\u518C
sys.dict.delete.system=\u7CFB\u7EDF\u5185\u7F6E\u5B57\u5178\u9879\u76EE\u4E0D\u80FD\u5220\u9664
sys.dict.update.system=\u7CFB\u7EDF\u5185\u7F6E\u5B57\u5178\u9879\u76EE\u4E0D\u80FD\u4FEE\u6539
sys.connect.cp.dept.sync.error=\u83B7\u53D6\u4F01\u4E1A\u5FAE\u4FE1\u90E8\u95E8\u5217\u8868\u5931\u8D25
sys.connect.cp.user.sync.error=\u83B7\u53D6\u4F01\u4E1A\u5FAE\u4FE1\u7528\u6237\u5217\u8868\u5931\u8D25
app.user.userInfo.empty={0} \u7528\u6237\u4FE1\u606F\u4E3A\u7A7A