添加单位信息表

This commit is contained in:
AlanScipio
2024-02-02 10:41:29 +08:00
parent 17adb9ba0f
commit 58fa00199e
31 changed files with 1906 additions and 1166 deletions

View File

@@ -2,11 +2,10 @@ package com.ruoyi.common.core.constant;
/**
* 通用常量信息
*
*
* @author ruoyi
*/
public class Constants
{
public class Constants {
/**
* UTF-8 字符集
*/
@@ -120,16 +119,16 @@ public class Constants
/**
* 自动识别json对象白名单配置仅允许解析的包名范围越小越安全
*/
public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi" };
public static final String[] JSON_WHITELIST_STR = {"org.springframework", "com.ruoyi"};
/**
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
*/
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
public static final String[] JOB_WHITELIST_STR = {"com.ruoyi"};
/**
* 定时任务违规的字符
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.ruoyi.common.core.utils.file" };
public static final String[] JOB_ERROR_STR = {"java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.ruoyi.common.core.utils.file"};
}

View File

@@ -1,98 +1,83 @@
package com.ruoyi.common.core.context;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.StringUtils;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 获取当前线程变量中的 用户id、用户名称、Token等信息
* 获取当前线程变量中的 用户id、用户名称、Token等信息
* 注意: 必须在网关通过请求头的方法传入同时在HeaderInterceptor拦截器设置值。 否则这里无法获取
*
* @author ruoyi
*/
public class SecurityContextHolder
{
public class SecurityContextHolder {
private static final TransmittableThreadLocal<Map<String, Object>> THREAD_LOCAL = new TransmittableThreadLocal<>();
public static void set(String key, Object value)
{
public static void set(String key, Object value) {
Map<String, Object> map = getLocalMap();
map.put(key, value == null ? StringUtils.EMPTY : value);
}
public static String get(String key)
{
public static String get(String key) {
Map<String, Object> map = getLocalMap();
return Convert.toStr(map.getOrDefault(key, StringUtils.EMPTY));
}
public static <T> T get(String key, Class<T> clazz)
{
public static <T> T get(String key, Class<T> clazz) {
Map<String, Object> map = getLocalMap();
return StringUtils.cast(map.getOrDefault(key, null));
}
public static Map<String, Object> getLocalMap()
{
public static Map<String, Object> getLocalMap() {
Map<String, Object> map = THREAD_LOCAL.get();
if (map == null)
{
if (map == null) {
map = new ConcurrentHashMap<String, Object>();
THREAD_LOCAL.set(map);
}
return map;
}
public static void setLocalMap(Map<String, Object> threadLocalMap)
{
public static void setLocalMap(Map<String, Object> threadLocalMap) {
THREAD_LOCAL.set(threadLocalMap);
}
public static Long getUserId()
{
public static Long getUserId() {
return Convert.toLong(get(SecurityConstants.DETAILS_USER_ID), 0L);
}
public static void setUserId(String account)
{
public static void setUserId(String account) {
set(SecurityConstants.DETAILS_USER_ID, account);
}
public static String getUserName()
{
public static String getUserName() {
return get(SecurityConstants.DETAILS_USERNAME);
}
public static void setUserName(String username)
{
public static void setUserName(String username) {
set(SecurityConstants.DETAILS_USERNAME, username);
}
public static String getUserKey()
{
public static String getUserKey() {
return get(SecurityConstants.USER_KEY);
}
public static void setUserKey(String userKey)
{
public static void setUserKey(String userKey) {
set(SecurityConstants.USER_KEY, userKey);
}
public static String getPermission()
{
public static String getPermission() {
return get(SecurityConstants.ROLE_PERMISSION);
}
public static void setPermission(String permissions)
{
public static void setPermission(String permissions) {
set(SecurityConstants.ROLE_PERMISSION, permissions);
}
public static void remove()
{
public static void remove() {
THREAD_LOCAL.remove();
}
}

View File

@@ -1,21 +1,28 @@
package com.ruoyi.common.core.domain;
import java.io.Serializable;
import com.ruoyi.common.core.constant.Constants;
import java.io.Serial;
import java.io.Serializable;
/**
* 响应信息主体
*
* @author ruoyi
*/
public class R<T> implements Serializable
{
public class R<T> implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 成功 */
/**
* 成功
*/
public static final int SUCCESS = Constants.SUCCESS;
/** 失败 */
/**
* 失败
*/
public static final int FAIL = Constants.FAIL;
private int code;
@@ -24,48 +31,39 @@ public class R<T> implements Serializable
private T data;
public static <T> R<T> ok()
{
public static <T> R<T> ok() {
return restResult(null, SUCCESS, null);
}
public static <T> R<T> ok(T data)
{
public static <T> R<T> ok(T data) {
return restResult(data, SUCCESS, null);
}
public static <T> R<T> ok(T data, String msg)
{
public static <T> R<T> ok(T data, String msg) {
return restResult(data, SUCCESS, msg);
}
public static <T> R<T> fail()
{
public static <T> R<T> fail() {
return restResult(null, FAIL, null);
}
public static <T> R<T> fail(String msg)
{
public static <T> R<T> fail(String msg) {
return restResult(null, FAIL, msg);
}
public static <T> R<T> fail(T data)
{
public static <T> R<T> fail(T data) {
return restResult(data, FAIL, null);
}
public static <T> R<T> fail(T data, String msg)
{
public static <T> R<T> fail(T data, String msg) {
return restResult(data, FAIL, msg);
}
public static <T> R<T> fail(int code, String msg)
{
public static <T> R<T> fail(int code, String msg) {
return restResult(null, code, msg);
}
private static <T> R<T> restResult(T data, int code, String msg)
{
private static <T> R<T> restResult(T data, int code, String msg) {
R<T> apiResult = new R<>();
apiResult.setCode(code);
apiResult.setData(data);
@@ -73,43 +71,35 @@ public class R<T> implements Serializable
return apiResult;
}
public int getCode()
{
public int getCode() {
return code;
}
public void setCode(int code)
{
public void setCode(int code) {
this.code = code;
}
public String getMsg()
{
public String getMsg() {
return msg;
}
public void setMsg(String msg)
{
public void setMsg(String msg) {
this.msg = msg;
}
public T getData()
{
public T getData() {
return data;
}
public void setData(T data)
{
public void setData(T data) {
this.data = data;
}
public static <T> Boolean isError(R<T> ret)
{
public static <T> Boolean isError(R<T> ret) {
return !isSuccess(ret);
}
public static <T> Boolean isSuccess(R<T> ret)
{
public static <T> Boolean isSuccess(R<T> ret) {
return R.SUCCESS == ret.getCode();
}
}

View File

@@ -2,29 +2,29 @@ package com.ruoyi.common.core.enums;
/**
* 用户状态
*
*
* @author ruoyi
*/
public enum UserStatus
{
OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
public enum UserStatus {
OK("0", "正常"),
DISABLE("1", "停用"),
DELETED("2", "删除"),
;
private final String code;
private final String info;
UserStatus(String code, String info)
{
UserStatus(String code, String info) {
this.code = code;
this.info = info;
}
public String getCode()
{
public String getCode() {
return code;
}
public String getInfo()
{
public String getInfo() {
return info;
}
}

View File

@@ -1,12 +1,13 @@
package com.ruoyi.common.core.text;
import com.ruoyi.common.core.utils.StringUtils;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import com.ruoyi.common.core.utils.StringUtils;
/**
* 字符集工具类
*
*
* @author ruoyi
*/
public class CharsetKit
@@ -19,15 +20,15 @@ public class CharsetKit
public static final String GBK = "GBK";
/** ISO-8859-1 */
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
public static final Charset CHARSET_ISO_8859_1 = StandardCharsets.ISO_8859_1;
/** UTF-8 */
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
public static final Charset CHARSET_UTF_8 = StandardCharsets.UTF_8;
/** GBK */
public static final Charset CHARSET_GBK = Charset.forName(GBK);
/**
* 转换为Charset对象
*
*
* @param charset 字符集,为空则返回默认字符集
* @return Charset
*/
@@ -38,7 +39,7 @@ public class CharsetKit
/**
* 转换字符串的字符集编码
*
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8
@@ -51,7 +52,7 @@ public class CharsetKit
/**
* 转换字符串的字符集编码
*
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8

View File

@@ -4,11 +4,10 @@ import com.ruoyi.common.core.utils.StringUtils;
/**
* 字符串格式化
*
*
* @author ruoyi
*/
public class StrFormatter
{
public class StrFormatter {
public static final String EMPTY_JSON = "{}";
public static final char C_BACKSLASH = '\\';
public static final char C_DELIM_START = '{';
@@ -22,15 +21,13 @@ public class StrFormatter
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
*
* @param strPattern 字符串模板
* @param argArray 参数列表
* @param argArray 参数列表
* @return 结果
*/
public static String format(final String strPattern, final Object... argArray)
{
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
{
public static String format(final String strPattern, final Object... argArray) {
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) {
return strPattern;
}
final int strPatternLength = strPattern.length();
@@ -40,43 +37,30 @@ public class StrFormatter
int handledPosition = 0;
int delimIndex;// 占位符所在位置
for (int argIndex = 0; argIndex < argArray.length; argIndex++)
{
for (int argIndex = 0; argIndex < argArray.length; argIndex++) {
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
if (delimIndex == -1)
{
if (handledPosition == 0)
{
if (delimIndex == -1) {
if (handledPosition == 0) {
return strPattern;
}
else
{ // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
} else { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
sbuf.append(strPattern, handledPosition, strPatternLength);
return sbuf.toString();
}
}
else
{
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
{
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
{
} else {
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) {
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) {
// 转义符之前还有一个转义符,占位符依旧有效
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
else
{
} else {
// 占位符被转义
argIndex--;
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(C_DELIM_START);
handledPosition = delimIndex + 1;
}
}
else
{
} else {
// 正常占位符
sbuf.append(strPattern, handledPosition, delimIndex);
sbuf.append(Convert.utf8Str(argArray[argIndex]));

View File

@@ -1,23 +1,19 @@
package com.ruoyi.common.core.utils;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.*;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;
/**
* 时间工具类
*
* @author ruoyi
*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
public static String YYYY = "yyyy";
public static String YYYY_MM = "yyyy-MM";
@@ -28,7 +24,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static String[] parsePatterns = {
private static final String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
@@ -38,8 +34,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
*
* @return Date() 当前日期
*/
public static Date getNowDate()
{
public static Date getNowDate() {
return new Date();
}
@@ -48,44 +43,34 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
*
* @return String
*/
public static String getDate()
{
public static String getDate() {
return dateTimeNow(YYYY_MM_DD);
}
public static final String getTime()
{
public static String getTime() {
return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
}
public static final String dateTimeNow()
{
public static String dateTimeNow() {
return dateTimeNow(YYYYMMDDHHMMSS);
}
public static final String dateTimeNow(final String format)
{
public static String dateTimeNow(final String format) {
return parseDateToStr(format, new Date());
}
public static final String dateTime(final Date date)
{
public static String dateTime(final Date date) {
return parseDateToStr(YYYY_MM_DD, date);
}
public static final String parseDateToStr(final String format, final Date date)
{
public static String parseDateToStr(final String format, final Date date) {
return new SimpleDateFormat(format).format(date);
}
public static final Date dateTime(final String format, final String ts)
{
try
{
public static Date dateTime(final String format, final String ts) {
try {
return new SimpleDateFormat(format).parse(ts);
}
catch (ParseException e)
{
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
@@ -93,8 +78,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/**
* 日期路径 即年/月/日 如2018/08/08
*/
public static final String datePath()
{
public static String datePath() {
Date now = new Date();
return DateFormatUtils.format(now, "yyyy/MM/dd");
}
@@ -102,8 +86,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/**
* 日期路径 即年/月/日 如20180808
*/
public static final String dateTime()
{
public static String dateTime() {
Date now = new Date();
return DateFormatUtils.format(now, "yyyyMMdd");
}
@@ -111,18 +94,13 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/**
* 日期型字符串转化为日期 格式
*/
public static Date parseDate(Object str)
{
if (str == null)
{
public static Date parseDate(Object str) {
if (str == null) {
return null;
}
try
{
try {
return parseDate(str.toString(), parsePatterns);
}
catch (ParseException e)
{
} catch (ParseException e) {
return null;
}
}
@@ -130,8 +108,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/**
* 获取服务器启动时间
*/
public static Date getServerStartDate()
{
public static Date getServerStartDate() {
long time = ManagementFactory.getRuntimeMXBean().getStartTime();
return new Date(time);
}
@@ -139,12 +116,11 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/**
* 计算时间差
*
* @param endDate 最后时间
* @param endDate 最后时间
* @param startTime 开始时间
* @return 时间差(天/小时/分钟)
*/
public static String timeDistance(Date endDate, Date startTime)
{
public static String timeDistance(Date endDate, Date startTime) {
long nd = 1000 * 24 * 60 * 60;
long nh = 1000 * 60 * 60;
long nm = 1000 * 60;
@@ -165,8 +141,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/**
* 增加 LocalDateTime ==> Date
*/
public static Date toDate(LocalDateTime temporalAccessor)
{
public static Date toDate(LocalDateTime temporalAccessor) {
ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}
@@ -174,8 +149,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
/**
* 增加 LocalDate ==> Date
*/
public static Date toDate(LocalDate temporalAccessor)
{
public static Date toDate(LocalDate temporalAccessor) {
LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());

View File

@@ -1,37 +1,33 @@
package com.ruoyi.common.core.utils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.apache.commons.lang3.exception.ExceptionUtils;
/**
* 错误信息处理类。
*
* @author ruoyi
*/
public class ExceptionUtil
{
public class ExceptionUtil {
/**
* 获取exception的详细错误信息。
*/
public static String getExceptionMessage(Throwable e)
{
public static String getExceptionMessage(Throwable e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw, true));
return sw.toString();
}
public static String getRootErrorMessage(Exception e)
{
public static String getRootErrorMessage(Exception e) {
Throwable root = ExceptionUtils.getRootCause(e);
root = (root == null ? e : root);
if (root == null)
{
if (root == null) {
return "";
}
String msg = root.getMessage();
if (msg == null)
{
if (msg == null) {
return "null";
}
return StringUtils.defaultString(msg);

View File

@@ -7,16 +7,14 @@ import com.ruoyi.common.core.web.page.TableSupport;
/**
* 分页工具类
*
*
* @author ruoyi
*/
public class PageUtils extends PageHelper
{
public class PageUtils extends PageHelper {
/**
* 设置请求分页数据
*/
public static void startPage()
{
public static void startPage() {
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
@@ -28,8 +26,7 @@ public class PageUtils extends PageHelper
/**
* 清理分页的线程变量
*/
public static void clearPage()
{
public static void clearPage() {
PageHelper.clearPage();
}
}

View File

@@ -9,106 +9,72 @@ import org.springframework.stereotype.Component;
/**
* spring工具类 方便在非spring管理环境中获取bean
*
*
* @author ruoyi
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor
{
/** Spring应用上下文环境 */
public final class SpringUtils implements BeanFactoryPostProcessor {
/**
* Spring应用上下文环境
*/
private static ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringUtils.beanFactory = beanFactory;
}
/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws org.springframework.beans.BeansException
*
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException
{
public static <T> T getBean(String name) throws BeansException {
return (T) beanFactory.getBean(name);
}
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*
*/
public static <T> T getBean(Class<T> clz) throws BeansException
{
public static <T> T getBean(Class<T> clz) throws BeansException {
T result = (T) beanFactory.getBean(clz);
return result;
}
/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义则返回true
*
* @param name
* @return boolean
*/
public static boolean containsBean(String name)
{
public static boolean containsBean(String name) {
return beanFactory.containsBean(name);
}
/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到将会抛出一个异常NoSuchBeanDefinitionException
*
* @param name
* @return boolean
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
{
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return beanFactory.isSingleton(name);
}
/**
* @param name
* @return Class 注册对象的类型
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
{
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return beanFactory.getType(name);
}
/**
* 如果给定的bean名字在bean定义中有别名则返回这些别名
*
* @param name
* @return
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
{
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
return beanFactory.getAliases(name);
}
/**
* 获取aop代理对象
*
* @param invoker
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getAopProxy(T invoker)
{
public static <T> T getAopProxy(T invoker) {
return (T) AopContext.currentProxy();
}
}

View File

@@ -1,191 +1,178 @@
package com.ruoyi.common.core.utils;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.text.StrFormatter;
import org.springframework.util.AntPathMatcher;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.springframework.util.AntPathMatcher;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.text.StrFormatter;
/**
* 字符串工具类
*
*
* @author ruoyi
*/
public class StringUtils extends org.apache.commons.lang3.StringUtils
{
/** 空字符串 */
private static final String NULLSTR = "";
public class StringUtils extends org.apache.commons.lang3.StringUtils {
/** 下划线 */
/**
* 空字符串
*/
private static final String NULL_STR = "";
/**
* 下划线
*/
private static final char SEPARATOR = '_';
/**
* 获取参数不为空值
*
*
* @param value defaultValue 要判断的value
* @return value 返回值
*/
public static <T> T nvl(T value, T defaultValue)
{
public static <T> T nvl(T value, T defaultValue) {
return value != null ? value : defaultValue;
}
/**
* * 判断一个Collection是否为空 包含ListSetQueue
*
*
* @param coll 要判断的Collection
* @return true为空 false非空
*/
public static boolean isEmpty(Collection<?> coll)
{
public static boolean isEmpty(Collection<?> coll) {
return isNull(coll) || coll.isEmpty();
}
/**
* * 判断一个Collection是否非空包含ListSetQueue
*
*
* @param coll 要判断的Collection
* @return true非空 false
*/
public static boolean isNotEmpty(Collection<?> coll)
{
public static boolean isNotEmpty(Collection<?> coll) {
return !isEmpty(coll);
}
/**
* * 判断一个对象数组是否为空
*
*
* @param objects 要判断的对象数组
** @return true为空 false非空
* * @return true为空 false非空
*/
public static boolean isEmpty(Object[] objects)
{
public static boolean isEmpty(Object[] objects) {
return isNull(objects) || (objects.length == 0);
}
/**
* * 判断一个对象数组是否非空
*
*
* @param objects 要判断的对象数组
* @return true非空 false
*/
public static boolean isNotEmpty(Object[] objects)
{
public static boolean isNotEmpty(Object[] objects) {
return !isEmpty(objects);
}
/**
* * 判断一个Map是否为空
*
*
* @param map 要判断的Map
* @return true为空 false非空
*/
public static boolean isEmpty(Map<?, ?> map)
{
public static boolean isEmpty(Map<?, ?> map) {
return isNull(map) || map.isEmpty();
}
/**
* * 判断一个Map是否为空
*
*
* @param map 要判断的Map
* @return true非空 false
*/
public static boolean isNotEmpty(Map<?, ?> map)
{
public static boolean isNotEmpty(Map<?, ?> map) {
return !isEmpty(map);
}
/**
* * 判断一个字符串是否为空串
*
*
* @param str String
* @return true为空 false非空
*/
public static boolean isEmpty(String str)
{
return isNull(str) || NULLSTR.equals(str.trim());
public static boolean isEmpty(String str) {
return isNull(str) || NULL_STR.equals(str.trim());
}
/**
* * 判断一个字符串是否为非空串
*
*
* @param str String
* @return true非空串 false空串
*/
public static boolean isNotEmpty(String str)
{
public static boolean isNotEmpty(String str) {
return !isEmpty(str);
}
/**
* * 判断一个对象是否为空
*
*
* @param object Object
* @return true为空 false非空
*/
public static boolean isNull(Object object)
{
public static boolean isNull(Object object) {
return object == null;
}
/**
* * 判断一个对象是否非空
*
*
* @param object Object
* @return true非空 false
*/
public static boolean isNotNull(Object object)
{
public static boolean isNotNull(Object object) {
return !isNull(object);
}
/**
* * 判断一个对象是否是数组类型Java基本型别的数组
*
*
* @param object 对象
* @return true是数组 false不是数组
*/
public static boolean isArray(Object object)
{
public static boolean isArray(Object object) {
return isNotNull(object) && object.getClass().isArray();
}
/**
* 去空格
*/
public static String trim(String str)
{
public static String trim(String str) {
return (str == null ? "" : str.trim());
}
/**
* 截取字符串
*
* @param str 字符串
*
* @param str 字符串
* @param start 开始
* @return 结果
*/
public static String substring(final String str, int start)
{
if (str == null)
{
return NULLSTR;
public static String substring(final String str, int start) {
if (str == null) {
return NULL_STR;
}
if (start < 0)
{
if (start < 0) {
start = str.length() + start;
}
if (start < 0)
{
if (start < 0) {
start = 0;
}
if (start > str.length())
{
return NULLSTR;
if (start > str.length()) {
return NULL_STR;
}
return str.substring(start);
@@ -193,44 +180,36 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/**
* 截取字符串
*
* @param str 字符串
*
* @param str 字符串
* @param start 开始
* @param end 结束
* @param end 结束
* @return 结果
*/
public static String substring(final String str, int start, int end)
{
if (str == null)
{
return NULLSTR;
public static String substring(final String str, int start, int end) {
if (str == null) {
return NULL_STR;
}
if (end < 0)
{
if (end < 0) {
end = str.length() + end;
}
if (start < 0)
{
if (start < 0) {
start = str.length() + start;
}
if (end > str.length())
{
if (end > str.length()) {
end = str.length();
}
if (start > end)
{
return NULLSTR;
if (start > end) {
return NULL_STR;
}
if (start < 0)
{
if (start < 0) {
start = 0;
}
if (end < 0)
{
if (end < 0) {
end = 0;
}
@@ -239,22 +218,18 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/**
* 判断是否为空,并且不是空白字符
*
*
* @param str 要判断的value
* @return 结果
*/
public static boolean hasText(String str)
{
public static boolean hasText(String str) {
return (str != null && !str.isEmpty() && containsText(str));
}
private static boolean containsText(CharSequence str)
{
private static boolean containsText(CharSequence str) {
int strLen = str.length();
for (int i = 0; i < strLen; i++)
{
if (!Character.isWhitespace(str.charAt(i)))
{
for (int i = 0; i < strLen; i++) {
if (!Character.isWhitespace(str.charAt(i))) {
return true;
}
}
@@ -269,15 +244,13 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
*
* @param template 文本模板,被替换的部分用 {} 表示
* @param params 参数值
* @param params 参数值
* @return 格式化后的文本
*/
public static String format(String template, Object... params)
{
if (isEmpty(params) || isEmpty(template))
{
public static String format(String template, Object... params) {
if (isEmpty(params) || isEmpty(template)) {
return template;
}
return StrFormatter.format(template, params);
@@ -285,12 +258,11 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/**
* 是否为http(s)://开头
*
*
* @param link 链接
* @return 结果
*/
public static boolean ishttp(String link)
{
public static boolean ishttp(String link) {
return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
}
@@ -298,21 +270,15 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
* 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
*
* @param collection 给定的集合
* @param array 给定的数组
* @param array 给定的数组
* @return boolean 结果
*/
public static boolean containsAny(Collection<String> collection, String... array)
{
if (isEmpty(collection) || isEmpty(array))
{
public static boolean containsAny(Collection<String> collection, String... array) {
if (isEmpty(collection) || isEmpty(array)) {
return false;
}
else
{
for (String str : array)
{
if (collection.contains(str))
{
} else {
for (String str : array) {
if (collection.contains(str)) {
return true;
}
}
@@ -323,10 +289,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/**
* 驼峰转下划线命名
*/
public static String toUnderScoreCase(String str)
{
if (str == null)
{
public static String toUnderScoreCase(String str) {
if (str == null) {
return null;
}
StringBuilder sb = new StringBuilder();
@@ -336,31 +300,23 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
boolean curreCharIsUpperCase = true;
// 下一字符是否大写
boolean nexteCharIsUpperCase = true;
for (int i = 0; i < str.length(); i++)
{
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (i > 0)
{
if (i > 0) {
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
}
else
{
} else {
preCharIsUpperCase = false;
}
curreCharIsUpperCase = Character.isUpperCase(c);
if (i < (str.length() - 1))
{
if (i < (str.length() - 1)) {
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
}
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
{
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
sb.append(SEPARATOR);
}
else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
{
} else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) {
sb.append(SEPARATOR);
}
sb.append(Character.toLowerCase(c));
@@ -371,19 +327,15 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/**
* 是否包含字符串
*
* @param str 验证字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strs)
{
if (str != null && strs != null)
{
for (String s : strs)
{
if (str.equalsIgnoreCase(trim(s)))
{
public static boolean inStringIgnoreCase(String str, String... strs) {
if (str != null && strs != null) {
for (String s : strs) {
if (str.equalsIgnoreCase(trim(s))) {
return true;
}
}
@@ -393,31 +345,25 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/**
* 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如HELLO_WORLD->HelloWorld
*
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String convertToCamelCase(String name)
{
public static String convertToCamelCase(String name) {
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty())
{
if (name == null || name.isEmpty()) {
// 没必要转换
return "";
}
else if (!name.contains("_"))
{
} else if (!name.contains("_")) {
// 不含下划线,仅将首字母大写
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels)
{
for (String camel : camels) {
// 跳过原始字符串中开头、结尾的下换线或双重下划线
if (camel.isEmpty())
{
if (camel.isEmpty()) {
continue;
}
// 首字母大写
@@ -431,34 +377,25 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
* 驼峰式命名法
* 例如user_name->userName
*/
public static String toCamelCase(String s)
{
if (s == null)
{
public static String toCamelCase(String s) {
if (s == null) {
return null;
}
if (s.indexOf(SEPARATOR) == -1)
{
if (s.indexOf(SEPARATOR) == -1) {
return s;
}
s = s.toLowerCase();
StringBuilder sb = new StringBuilder(s.length());
boolean upperCase = false;
for (int i = 0; i < s.length(); i++)
{
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == SEPARATOR)
{
if (c == SEPARATOR) {
upperCase = true;
}
else if (upperCase)
{
} else if (upperCase) {
sb.append(Character.toUpperCase(c));
upperCase = false;
}
else
{
} else {
sb.append(c);
}
}
@@ -467,21 +404,17 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, List<String> strs)
{
if (isEmpty(str) || isEmpty(strs))
{
public static boolean matches(String str, List<String> strs) {
if (isEmpty(str) || isEmpty(strs)) {
return false;
}
for (String pattern : strs)
{
if (isMatch(pattern, str))
{
for (String pattern : strs) {
if (isMatch(pattern, str)) {
return true;
}
}
@@ -489,70 +422,57 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
}
/**
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串,不可跨层级;
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串,不可跨层级;
* ** 表示任意层路径;
*
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return
* @param url 需要匹配的url
*/
public static boolean isMatch(String pattern, String url)
{
public static boolean isMatch(String pattern, String url) {
AntPathMatcher matcher = new AntPathMatcher();
return matcher.match(pattern, url);
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj)
{
public static <T> T cast(Object obj) {
return (T) obj;
}
/**
* 数字左边补齐0使之达到指定长度。注意如果数字转换为字符串后长度大于size则只保留 最后size个字符。
*
* @param num 数字对象
*
* @param num 数字对象
* @param size 字符串指定长度
* @return 返回数字的字符串格式,该字符串为指定长度。
*/
public static final String padl(final Number num, final int size)
{
public static String padl(final Number num, final int size) {
return padl(num.toString(), size, '0');
}
/**
* 字符串左补齐。如果原始字符串s长度大于size则只保留最后size个字符。
*
* @param s 原始字符串
*
* @param s 原始字符串
* @param size 字符串指定长度
* @param c 用于补齐的字符
* @param c 用于补齐的字符
* @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
*/
public static final String padl(final String s, final int size, final char c)
{
public static String padl(final String s, final int size, final char c) {
final StringBuilder sb = new StringBuilder(size);
if (s != null)
{
if (s != null) {
final int len = s.length();
if (s.length() <= size)
{
for (int i = size - len; i > 0; i--)
{
if (s.length() <= size) {
for (int i = size - len; i > 0; i--) {
sb.append(c);
}
sb.append(s);
}
else
{
} else {
return s.substring(len - size, len);
}
}
else
{
for (int i = size; i > 0; i--)
{
} else {
for (int i = size; i > 0; i--) {
sb.append(c);
}
}

View File

@@ -2,48 +2,43 @@ package com.ruoyi.common.core.utils.uuid;
/**
* ID生成器工具类
*
*
* @author ruoyi
*/
public class IdUtils
{
public class IdUtils {
/**
* 获取随机UUID
*
*
* @return 随机UUID
*/
public static String randomUUID()
{
public static String randomUUID() {
return UUID.randomUUID().toString();
}
/**
* 简化的UUID去掉了横线
*
*
* @return 简化的UUID去掉了横线
*/
public static String simpleUUID()
{
public static String simpleUUID() {
return UUID.randomUUID().toString(true);
}
/**
* 获取随机UUID使用性能更好的ThreadLocalRandom生成UUID
*
*
* @return 随机UUID
*/
public static String fastUUID()
{
public static String fastUUID() {
return UUID.fastUUID().toString();
}
/**
* 简化的UUID去掉了横线使用性能更好的ThreadLocalRandom生成UUID
*
*
* @return 简化的UUID去掉了横线
*/
public static String fastSimpleUUID()
{
public static String fastSimpleUUID() {
return UUID.fastUUID().toString(true);
}
}

View File

@@ -1,14 +1,14 @@
package com.ruoyi.common.core.utils.uuid;
import java.util.concurrent.atomic.AtomicInteger;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author ruoyi 序列生成类
*/
public class Seq
{
public class Seq {
// 通用序列类型
public static final String commSeqType = "COMMON";
@@ -16,34 +16,31 @@ public class Seq
public static final String uploadSeqType = "UPLOAD";
// 通用接口序列数
private static AtomicInteger commSeq = new AtomicInteger(1);
private static final AtomicInteger commSeq = new AtomicInteger(1);
// 上传接口序列数
private static AtomicInteger uploadSeq = new AtomicInteger(1);
private static final AtomicInteger uploadSeq = new AtomicInteger(1);
// 机器标识
private static final String machineCode = "A";
/**
* 获取通用序列号
*
*
* @return 序列值
*/
public static String getId()
{
public static String getId() {
return getId(commSeqType);
}
/**
* 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串
*
*
* @return 序列值
*/
public static String getId(String type)
{
public static String getId(String type) {
AtomicInteger atomicInt = commSeq;
if (uploadSeqType.equals(type))
{
if (uploadSeqType.equals(type)) {
atomicInt = uploadSeq;
}
return getId(atomicInt, 3);
@@ -51,13 +48,12 @@ public class Seq
/**
* 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串
*
*
* @param atomicInt 序列数
* @param length 数值长度
* @param length 数值长度
* @return 序列值
*/
public static String getId(AtomicInteger atomicInt, int length)
{
public static String getId(AtomicInteger atomicInt, int length) {
String result = DateUtils.dateTimeNow();
result += machineCode;
result += getSeq(atomicInt, length);
@@ -66,18 +62,16 @@ public class Seq
/**
* 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数
*
*
* @return 序列值
*/
private synchronized static String getSeq(AtomicInteger atomicInt, int length)
{
private synchronized static String getSeq(AtomicInteger atomicInt, int length) {
// 先取值再+1
int value = atomicInt.getAndIncrement();
// 如果更新后值>=10 的 (length)幂次方则重置为1
int maxSeq = (int) Math.pow(10, length);
if (atomicInt.get() >= maxSeq)
{
if (atomicInt.get() >= maxSeq) {
atomicInt.set(1);
}
// 转字符串用0左补齐

View File

@@ -1,52 +1,53 @@
package com.ruoyi.common.core.utils.uuid;
import com.ruoyi.common.core.exception.UtilException;
import java.io.Serial;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import com.ruoyi.common.core.exception.UtilException;
/**
* 提供通用唯一识别码universally unique identifierUUID实现
*
* @author ruoyi
*/
public final class UUID implements java.io.Serializable, Comparable<UUID>
{
public final class UUID implements java.io.Serializable, Comparable<UUID> {
@Serial
private static final long serialVersionUID = -1185015143654744140L;
/**
* SecureRandom 的单例
*
*/
private static class Holder
{
private static class Holder {
static final SecureRandom numberGenerator = getSecureRandom();
}
/** 此UUID的最高64有效位 */
/**
* 此UUID的最高64有效位
*/
private final long mostSigBits;
/** 此UUID的最低64有效位 */
/**
* 此UUID的最低64有效位
*/
private final long leastSigBits;
/**
* 私有构造
*
*
* @param data 数据
*/
private UUID(byte[] data)
{
private UUID(byte[] data) {
long msb = 0;
long lsb = 0;
assert data.length == 16 : "data must be 16 bytes in length";
for (int i = 0; i < 8; i++)
{
for (int i = 0; i < 8; i++) {
msb = (msb << 8) | (data[i] & 0xff);
}
for (int i = 8; i < 16; i++)
{
for (int i = 8; i < 16; i++) {
lsb = (lsb << 8) | (data[i] & 0xff);
}
this.mostSigBits = msb;
@@ -56,43 +57,39 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
/**
* 使用指定的数据构造新的 UUID。
*
* @param mostSigBits 用于 {@code UUID} 的最高有效 64 位
* @param mostSigBits 用于 {@code UUID} 的最高有效 64 位
* @param leastSigBits 用于 {@code UUID} 的最低有效 64 位
*/
public UUID(long mostSigBits, long leastSigBits)
{
public UUID(long mostSigBits, long leastSigBits) {
this.mostSigBits = mostSigBits;
this.leastSigBits = leastSigBits;
}
/**
* 获取类型 4伪随机生成的UUID 的静态工厂。
*
* 获取类型 4伪随机生成的UUID 的静态工厂。
*
* @return 随机生成的 {@code UUID}
*/
public static UUID fastUUID()
{
public static UUID fastUUID() {
return randomUUID(false);
}
/**
* 获取类型 4伪随机生成的UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
*
*
* @return 随机生成的 {@code UUID}
*/
public static UUID randomUUID()
{
public static UUID randomUUID() {
return randomUUID(true);
}
/**
* 获取类型 4伪随机生成的UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
*
*
* @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能
* @return 随机生成的 {@code UUID}
*/
public static UUID randomUUID(boolean isSecure)
{
public static UUID randomUUID(boolean isSecure) {
final Random ng = isSecure ? Holder.numberGenerator : getRandom();
byte[] randomBytes = new byte[16];
@@ -108,18 +105,13 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
* 根据指定的字节数组获取类型 3基于名称的UUID 的静态工厂。
*
* @param name 用于构造 UUID 的字节数组。
*
* @return 根据指定数组生成的 {@code UUID}
*/
public static UUID nameUUIDFromBytes(byte[] name)
{
public static UUID nameUUIDFromBytes(byte[] name) {
MessageDigest md;
try
{
try {
md = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException nsae)
{
} catch (NoSuchAlgorithmException nsae) {
throw new InternalError("MD5 not supported");
}
byte[] md5Bytes = md.digest(name);
@@ -136,29 +128,25 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
* @param name 指定 {@code UUID} 字符串
* @return 具有指定值的 {@code UUID}
* @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常
*
*/
public static UUID fromString(String name)
{
public static UUID fromString(String name) {
String[] components = name.split("-");
if (components.length != 5)
{
if (components.length != 5) {
throw new IllegalArgumentException("Invalid UUID string: " + name);
}
for (int i = 0; i < 5; i++)
{
for (int i = 0; i < 5; i++) {
components[i] = "0x" + components[i];
}
long mostSigBits = Long.decode(components[0]).longValue();
long mostSigBits = Long.decode(components[0]);
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[1]).longValue();
mostSigBits |= Long.decode(components[1]);
mostSigBits <<= 16;
mostSigBits |= Long.decode(components[2]).longValue();
mostSigBits |= Long.decode(components[2]);
long leastSigBits = Long.decode(components[3]).longValue();
long leastSigBits = Long.decode(components[3]);
leastSigBits <<= 48;
leastSigBits |= Long.decode(components[4]).longValue();
leastSigBits |= Long.decode(components[4]);
return new UUID(mostSigBits, leastSigBits);
}
@@ -168,8 +156,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
*
* @return 此 UUID 的 128 位值中的最低有效 64 位。
*/
public long getLeastSignificantBits()
{
public long getLeastSignificantBits() {
return leastSigBits;
}
@@ -178,8 +165,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
*
* @return 此 UUID 的 128 位值中最高有效 64 位。
*/
public long getMostSignificantBits()
{
public long getMostSignificantBits() {
return mostSigBits;
}
@@ -196,8 +182,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
*
* @return 此 {@code UUID} 的版本号
*/
public int version()
{
public int version() {
// Version is bits masked by 0x000000000000F000 in MS long
return (int) ((mostSigBits >> 12) & 0x0f);
}
@@ -215,8 +200,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
*
* @return 此 {@code UUID} 相关联的变体号
*/
public int variant()
{
public int variant() {
// This field is composed of a varying number of bits.
// 0 - - Reserved for NCS backward compatibility
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
@@ -238,8 +222,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
*
* @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。
*/
public long timestamp() throws UnsupportedOperationException
{
public long timestamp() throws UnsupportedOperationException {
checkTimeBase();
return (mostSigBits & 0x0FFFL) << 48//
| ((mostSigBits >> 16) & 0x0FFFFL) << 32//
@@ -256,11 +239,9 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
* UnsupportedOperationException。
*
* @return 此 {@code UUID} 的时钟序列
*
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
*/
public int clockSequence() throws UnsupportedOperationException
{
public int clockSequence() throws UnsupportedOperationException {
checkTimeBase();
return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
}
@@ -275,11 +256,9 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
* 如果此 UUID 不是基于时间的 UUID则此方法抛出 UnsupportedOperationException。
*
* @return 此 {@code UUID} 的节点值
*
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
*/
public long node() throws UnsupportedOperationException
{
public long node() throws UnsupportedOperationException {
checkTimeBase();
return leastSigBits & 0x0000FFFFFFFFFFFFL;
}
@@ -289,7 +268,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述:
*
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
@@ -302,15 +281,14 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
*
* </blockquote>
*
* @return 此{@code UUID} 的字符串表现形式
* @see #toString(boolean)
*/
@Override
public String toString()
{
public String toString() {
return toString(false);
}
@@ -319,7 +297,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
*
* <p>
* UUID 的字符串表示形式由此 BNF 描述:
*
*
* <pre>
* {@code
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
@@ -332,37 +310,32 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
* hexDigit = [0-9a-fA-F]
* }
* </pre>
*
*
* </blockquote>
*
* @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串
* @return 此{@code UUID} 的字符串表现形式
*/
public String toString(boolean isSimple)
{
public String toString(boolean isSimple) {
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
// time_low
builder.append(digits(mostSigBits >> 32, 8));
if (false == isSimple)
{
if (!isSimple) {
builder.append('-');
}
// time_mid
builder.append(digits(mostSigBits >> 16, 4));
if (false == isSimple)
{
if (!isSimple) {
builder.append('-');
}
// time_high_and_version
builder.append(digits(mostSigBits, 4));
if (false == isSimple)
{
if (!isSimple) {
builder.append('-');
}
// variant_and_sequence
builder.append(digits(leastSigBits >> 48, 4));
if (false == isSimple)
{
if (!isSimple) {
builder.append('-');
}
// node
@@ -377,8 +350,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
* @return UUID 的哈希码值。
*/
@Override
public int hashCode()
{
public int hashCode() {
long hilo = mostSigBits ^ leastSigBits;
return ((int) (hilo >> 32)) ^ (int) hilo;
}
@@ -389,14 +361,11 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
* 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值每一位均相同结果才为 {@code true}。
*
* @param obj 要与之比较的对象
*
* @return 如果对象相同,则返回 {@code true};否则返回 {@code false}
*/
@Override
public boolean equals(Object obj)
{
if ((null == obj) || (obj.getClass() != UUID.class))
{
public boolean equals(Object obj) {
if ((null == obj) || (obj.getClass() != UUID.class)) {
return false;
}
UUID id = (UUID) obj;
@@ -412,13 +381,10 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
* 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。
*
* @param val 与此 UUID 比较的 UUID
*
* @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。
*
*/
@Override
public int compareTo(UUID val)
{
public int compareTo(UUID val) {
// The ordering is intentionally set up so that the UUIDs
// can simply be numerically compared as two numbers
return (this.mostSigBits < val.mostSigBits ? -1 : //
@@ -430,15 +396,15 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
// -------------------------------------------------------------------------------------------------------------------
// Private method start
/**
* 返回指定数字对应的hex值
*
* @param val 值
*
* @param val
* @param digits 位
* @return 值
*/
private static String digits(long val, int digits)
{
private static String digits(long val, int digits) {
long hi = 1L << (digits * 4);
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}
@@ -446,27 +412,21 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
/**
* 检查是否为time-based版本UUID
*/
private void checkTimeBase()
{
if (version() != 1)
{
private void checkTimeBase() {
if (version() != 1) {
throw new UnsupportedOperationException("Not a time-based UUID");
}
}
/**
* 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG)
*
*
* @return {@link SecureRandom}
*/
public static SecureRandom getSecureRandom()
{
try
{
public static SecureRandom getSecureRandom() {
try {
return SecureRandom.getInstance("SHA1PRNG");
}
catch (NoSuchAlgorithmException e)
{
} catch (NoSuchAlgorithmException e) {
throw new UtilException(e);
}
}
@@ -474,11 +434,10 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
/**
* 获取随机数生成器对象<br>
* ThreadLocalRandom是JDK 7之后提供并发产生随机数能够解决多个线程发生的竞争争夺。
*
*
* @return {@link ThreadLocalRandom}
*/
public static ThreadLocalRandom getRandom()
{
public static ThreadLocalRandom getRandom() {
return ThreadLocalRandom.current();
}
}

View File

@@ -0,0 +1,346 @@
package com.ruoyi.common.core.utils.uuid.snowflake;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Enumeration;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Pattern;
/**
* 基于Twitter的Snowflake算法实现分布式高效有序ID生产黑科技(sequence)——升级版Snowflake
*
* <br>
* SnowFlake的结构如下(每部分用-分开):<br>
* <br>
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
* <br>
* 1位标识由于long基本类型在Java中是带符号的最高位是符号位正数是0负数是1所以id一般是正数最高位是0<br>
* <br>
* 41位时间截(毫秒级)注意41位时间截不是存储当前时间的时间截而是存储时间截的差值当前时间截 - 开始时间截)
* 得到的值这里的的开始时间截一般是我们的id生成器开始使用的时间由我们程序来指定的如下START_TIME属性。41位的时间截可以使用69年年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
* <br>
* 10位的数据机器位可以部署在1024个节点包括5位dataCenterId和5位workerId<br>
* <br>
* 12位序列毫秒内的计数12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
* <br>
* <br>
* 加起来刚好64位为一个Long型。<br>
* SnowFlake的优点是整体上按照时间自增排序并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分)并且效率较高经测试SnowFlake每秒能够产生26万ID左右。
* <p>
* <p>
* 特性:
* 1.支持自定义允许时间回拨的范围<p>
* 2.解决跨毫秒起始值每次为0开始的情况避免末尾必定为偶数而不便于取余使用问题<p>
* 3.解决高并发场景中获取时间戳性能问题<p>
* 4.支撑根据IP末尾数据作为workerId
* 5.时间回拨方案思考1024个节点中分配10个点作为时间回拨序号连续10次时间回拨的概率较小
* <p>
* 常见问题:
* 1.时间回拨问题
* 2.机器id的分配和回收问题
* 3.机器id的上限问题
*
* @author lry
* @author Alan Scipio
* @version 3.0
* @see <a href="https://gitee.com/yu120/sequence">来源(码云)</a>
* @see <a href="https://github.com/yu120/neural">来源(Github)</a>
*/
class Sequence {
/**
* 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
*/
private long twepoch;
/**
* 时间戳的bit位数标准为41位
*/
private long timestampBits;
/**
* 机房id的bit位数标准为5位
*/
private long datacenterIdBits;
/**
* 机器id的bit位数标准为5位
*/
private long workerIdBits;
/**
* 序列号的bit位数即每毫秒内产生的id数标准为2的12次方个
*/
private long sequenceBits;
protected long maxDatacenterId;
protected long maxWorkerId;
private long workerIdShift;
private long datacenterIdShift;
/**
* 时间戳左移动位
*/
private long timestampLeftShift;
/**
* 序列号掩码
*/
private long sequenceMask;
/**
* 时间戳掩码
*/
private long timestampMask;
/**
* 所属机房id
*/
private final long datacenterId;
/**
* 所属机器id
*/
private final long workerId;
/**
* 并发控制序列
*/
private long sequence = 0L;
/**
* 上次生产 ID 时间戳
*/
private long lastTimestamp = -1L;
private static volatile InetAddress LOCAL_ADDRESS = null;
private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$");
public Sequence() {
this.datacenterId = getDatacenterId();
this.workerId = getMaxWorkerId(datacenterId);
}
/**
* 有参构造器
*
* @param workerId 工作机器 ID
* @param datacenterId 序列号
*/
public Sequence(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("Worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("Datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
/**
* {@link SequenceBuilder}专用:初始化自定义的基础设定
*
* @param tsepoch 起始时间
* @param timestampBits 时间戳的bit位数
* @param datacenterIdBits dataCenterId的bit位数
* @param workerIdBits workerId的bit位数
* @param sequenceBits 序列号的bit位数
*/
void init(long tsepoch, long timestampBits, long datacenterIdBits, long workerIdBits, long sequenceBits) {
this.twepoch = tsepoch;
this.timestampBits = timestampBits;
this.datacenterIdBits = datacenterIdBits;
this.workerIdBits = workerIdBits;
this.sequenceBits = sequenceBits;
maxDatacenterId = ~(-1L << datacenterIdBits);
maxWorkerId = ~(-1L << workerIdBits);
workerIdShift = sequenceBits;
datacenterIdShift = sequenceBits + workerIdBits;
timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
sequenceMask = ~(-1L << sequenceBits);
timestampMask = ~(-1L << timestampBits);
}
/**
* 基于网卡MAC地址计算余数作为数据中心
* <p>
* 可自定扩展
*/
protected long getDatacenterId() {
long id = 0L;
try {
NetworkInterface network = NetworkInterface.getByInetAddress(getLocalAddress());
if (null == network) {
id = 1L;
} else {
byte[] mac = network.getHardwareAddress();
if (null != mac) {
id = ((0x000000FF & (long) mac[mac.length - 2]) | (0x0000FF00 & (((long) mac[mac.length - 1]) << 8))) >> 6;
id = id % (maxDatacenterId + 1);
}
}
} catch (Exception e) {
System.err.println(" getDatacenterId: " + e);
}
return id;
}
/**
* 基于 MAC + PID 的 hashcode 获取16个低位
* <p>
* 可自定扩展
*/
protected long getMaxWorkerId(long datacenterId) {
StringBuilder mpId = new StringBuilder();
mpId.append(datacenterId);
String name = ManagementFactory.getRuntimeMXBean().getName();
if (name != null && name.length() > 0) {
// GET jvmPid
mpId.append(name.split("@")[0]);
}
// MAC + PID 的 hashcode 获取16个低位
return (mpId.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
}
/**
* 获取下一个 ID
*
* @return next id
*/
public synchronized long nextId() {
long timestamp = timeGen();
// 闰秒
if (timestamp < lastTimestamp) {
long offset = lastTimestamp - timestamp;
if (offset <= 5) {
try {
// 休眠双倍差值后重新获取,再次校验
wait(offset << 1);
timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset));
}
}
if (lastTimestamp == timestamp) {
// 相同毫秒内,序列号自增
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
// 同一毫秒的序列数已经达到最大
timestamp = tilNextMillis(lastTimestamp);
}
} else {
// 不同毫秒内,序列号置为 1 - 3 随机数
sequence = ThreadLocalRandom.current().nextLong(1, 3);
}
lastTimestamp = timestamp;
long timePart = (timestamp - twepoch) & timestampMask;
// 时间戳部分 | 数据中心部分 | 机器标识部分 | 序列号部分
return (timePart << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift)
| sequence;
}
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
protected long timeGen() {
return SystemClock.INSTANCE.currentTimeMillis();
}
public LocalDateTime getStartEpoch() {
return Instant.ofEpochMilli(twepoch).atZone(ZoneId.systemDefault()).toLocalDateTime();
}
public long getTotalBits() {
return (timestampBits + datacenterIdBits + workerIdBits + sequenceBits + 1);
}
/**
* Find first valid IP from local network card
*
* @return first valid local IP
*/
public static InetAddress getLocalAddress() {
if (LOCAL_ADDRESS != null) {
return LOCAL_ADDRESS;
}
LOCAL_ADDRESS = getLocalAddress0();
return LOCAL_ADDRESS;
}
private static InetAddress getLocalAddress0() {
InetAddress localAddress = null;
try {
localAddress = InetAddress.getLocalHost();
if (isValidAddress(localAddress)) {
return localAddress;
}
} catch (Throwable e) {
System.err.println("Failed to retrieving ip address, " + e);
}
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
if (interfaces != null) {
while (interfaces.hasMoreElements()) {
try {
NetworkInterface network = interfaces.nextElement();
Enumeration<InetAddress> addresses = network.getInetAddresses();
while (addresses.hasMoreElements()) {
try {
InetAddress address = addresses.nextElement();
if (isValidAddress(address)) {
return address;
}
} catch (Throwable e) {
System.err.println("Failed to retrieving ip address, " + e);
}
}
} catch (Throwable e) {
System.err.println("Failed to retrieving ip address, " + e);
}
}
}
} catch (Throwable e) {
System.err.println("Failed to retrieving ip address, " + e);
}
System.err.println("Could not get local host ip address, will use 127.0.0.1 instead.");
return localAddress;
}
private static boolean isValidAddress(InetAddress address) {
if (address == null || address.isLoopbackAddress()) {
return false;
}
String name = address.getHostAddress();
return (name != null && !"0.0.0.0".equals(name) && !"127.0.0.1".equals(name) && IP_PATTERN.matcher(name).matches());
}
}

View File

@@ -0,0 +1,93 @@
package com.ruoyi.common.core.utils.uuid.snowflake;
/**
* @author Alan Scipio
* create date: 2022/9/27
*/
public class SequenceBuilder {
/**
* 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
*/
private long twepoch = 1664268238500L;
/**
* 时间戳的bit位数标准为41位
*/
private long timestampBits = 41L;
/**
* 机房id的bit位数标准为5位
*/
private long datacenterIdBits = 5L;
/**
* 机器id的bit位数标准为5位
*/
private long workerIdBits = 5L;
/**
* 序列号的bit位数即每毫秒内产生的id数标准为2的12次方个
*/
private long sequenceBits = 12L;
/**
* 所属机房id
*/
private Long datacenterId;
/**
* 所属机器id
*/
private Long workerId;
public static SequenceBuilder builder() {
return new SequenceBuilder();
}
public Sequence build() {
Sequence sequence;
if (datacenterId != null && workerId != null) {
sequence = new Sequence(workerId, datacenterId);
} else {
sequence = new Sequence();
}
sequence.init(twepoch, timestampBits, datacenterIdBits, workerIdBits, sequenceBits);
return sequence;
}
public SequenceBuilder setTwepoch(long twepoch) {
this.twepoch = twepoch;
return this;
}
public SequenceBuilder setTimestampBits(long timestampBits) {
this.timestampBits = timestampBits;
return this;
}
public SequenceBuilder setDatacenterIdBits(long datacenterIdBits) {
this.datacenterIdBits = datacenterIdBits;
return this;
}
public SequenceBuilder setWorkerIdBits(long workerIdBits) {
this.workerIdBits = workerIdBits;
return this;
}
public SequenceBuilder setSequenceBits(long sequenceBits) {
this.sequenceBits = sequenceBits;
return this;
}
public SequenceBuilder setDatacenterId(Long datacenterId) {
this.datacenterId = datacenterId;
return this;
}
public SequenceBuilder setWorkerId(Long workerId) {
this.workerId = workerId;
return this;
}
}

View File

@@ -0,0 +1,63 @@
package com.ruoyi.common.core.utils.uuid.snowflake;
import java.util.HashMap;
import java.util.Map;
/**
* 雪花算法下的ID生成器
*
* @author Alan Scipio
* @since 2022/7/15
*/
public class SnowFlakeIdGenerator {
//默认id生成器不指定机器id和数据中心id
private static final String DEFAULT_SEQ = "defaultSeq";
private static final Map<String, Sequence> SEQUENCE_MAP = new HashMap<>();
private SnowFlakeIdGenerator() {
}
/**
* 本项目的基础设定
*/
private static SequenceBuilder defaultBuilder() {
return SequenceBuilder.builder()
.setTwepoch(1657864986440L) //起始时间戳
.setTimestampBits(40L) //时间戳的bit位数
.setDatacenterIdBits(1L) //数据中心的bit位数
.setWorkerIdBits(2L) //机器id的bit位数
.setSequenceBits(4L); //序列号的bit位数
}
/**
* 雪花算法下生成ID
*/
public static long nextIdLong() {
Sequence sequence = SEQUENCE_MAP.computeIfAbsent(DEFAULT_SEQ, key -> defaultBuilder().build());
return sequence.nextId();
}
/**
* 雪花算法下生成ID
*
* @param workerId 机器ID
* @param datacenterId 数据中心ID
*/
public static long nextIdLong(long workerId, long datacenterId) {
Sequence sequence = SEQUENCE_MAP.computeIfAbsent(workerId + "-" + datacenterId, key -> defaultBuilder()
.setWorkerId(workerId)
.setDatacenterId(datacenterId)
.build());
return sequence.nextId();
}
public static String nextId() {
return nextIdLong() + "";
}
public static String nextId(long workerId, long datacenterId) {
return nextIdLong(workerId, datacenterId) + "";
}
}

View File

@@ -0,0 +1,79 @@
package com.ruoyi.common.core.utils.uuid.snowflake;
import java.sql.Timestamp;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
* System Clock
* <p>
* 利用ScheduledExecutorService实现高并发场景下System.currentTimeMillis()的性能问题的优化.
*
* @author lry
*/
enum SystemClock {
// ====
INSTANCE(1);
private final long period;
private final AtomicLong nowTime;
private boolean started = false;
private ScheduledExecutorService executorService;
SystemClock(long period) {
this.period = period;
this.nowTime = new AtomicLong(System.currentTimeMillis());
}
/**
* The initialize scheduled executor service
*/
public void initialize() {
if (started) {
return;
}
this.executorService = new ScheduledThreadPoolExecutor(1, r -> {
Thread thread = new Thread(r, "system-clock");
thread.setDaemon(true);
return thread;
});
executorService.scheduleAtFixedRate(() -> nowTime.set(System.currentTimeMillis()),
this.period, this.period, TimeUnit.MILLISECONDS);
Runtime.getRuntime().addShutdownHook(new Thread(this::destroy));
started = true;
}
/**
* The get current time milliseconds
*
* @return long time
*/
public long currentTimeMillis() {
return started ? nowTime.get() : System.currentTimeMillis();
}
/**
* The get string current time
*
* @return string time
*/
public String currentTime() {
return new Timestamp(currentTimeMillis()).toString();
}
/**
* The destroy of executor service
*/
public void destroy() {
if (executorService != null) {
executorService.shutdown();
}
}
}

View File

@@ -1,104 +1,104 @@
package com.ruoyi.common.core.web.domain;
import java.util.HashMap;
import java.util.Objects;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.utils.StringUtils;
import java.io.Serial;
import java.util.HashMap;
import java.util.Objects;
/**
* 操作消息提醒
*
*
* @author ruoyi
*/
public class AjaxResult extends HashMap<String, Object>
{
public class AjaxResult extends HashMap<String, Object> {
@Serial
private static final long serialVersionUID = 1L;
/** 状态码 */
/**
* 状态码
*/
public static final String CODE_TAG = "code";
/** 返回内容 */
/**
* 返回内容
*/
public static final String MSG_TAG = "msg";
/** 数据对象 */
/**
* 数据对象
*/
public static final String DATA_TAG = "data";
/**
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
*/
public AjaxResult()
{
public AjaxResult() {
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
*
* @param code 状态码
* @param msg 返回内容
* @param msg 返回内容
*/
public AjaxResult(int code, String msg)
{
public AjaxResult(int code, String msg) {
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
*
* @param code 状态码
* @param msg 返回内容
* @param msg 返回内容
* @param data 数据对象
*/
public AjaxResult(int code, String msg, Object data)
{
public AjaxResult(int code, String msg, Object data) {
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
if (StringUtils.isNotNull(data))
{
if (StringUtils.isNotNull(data)) {
super.put(DATA_TAG, data);
}
}
/**
* 返回成功消息
*
*
* @return 成功消息
*/
public static AjaxResult success()
{
public static AjaxResult success() {
return AjaxResult.success("操作成功");
}
/**
* 返回成功数据
*
*
* @return 成功消息
*/
public static AjaxResult success(Object data)
{
public static AjaxResult success(Object data) {
return AjaxResult.success("操作成功", data);
}
/**
* 返回成功消息
*
*
* @param msg 返回内容
* @return 成功消息
*/
public static AjaxResult success(String msg)
{
public static AjaxResult success(String msg) {
return AjaxResult.success(msg, null);
}
/**
* 返回成功消息
*
* @param msg 返回内容
*
* @param msg 返回内容
* @param data 数据对象
* @return 成功消息
*/
public static AjaxResult success(String msg, Object data)
{
public static AjaxResult success(String msg, Object data) {
return new AjaxResult(HttpStatus.SUCCESS, msg, data);
}
@@ -108,65 +108,59 @@ public class AjaxResult extends HashMap<String, Object>
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult warn(String msg)
{
public static AjaxResult warn(String msg) {
return AjaxResult.warn(msg, null);
}
/**
* 返回警告消息
*
* @param msg 返回内容
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static AjaxResult warn(String msg, Object data)
{
public static AjaxResult warn(String msg, Object data) {
return new AjaxResult(HttpStatus.WARN, msg, data);
}
/**
* 返回错误消息
*
*
* @return 错误消息
*/
public static AjaxResult error()
{
public static AjaxResult error() {
return AjaxResult.error("操作失败");
}
/**
* 返回错误消息
*
*
* @param msg 返回内容
* @return 错误消息
*/
public static AjaxResult error(String msg)
{
public static AjaxResult error(String msg) {
return AjaxResult.error(msg, null);
}
/**
* 返回错误消息
*
* @param msg 返回内容
*
* @param msg 返回内容
* @param data 数据对象
* @return 错误消息
*/
public static AjaxResult error(String msg, Object data)
{
public static AjaxResult error(String msg, Object data) {
return new AjaxResult(HttpStatus.ERROR, msg, data);
}
/**
* 返回错误消息
*
*
* @param code 状态码
* @param msg 返回内容
* @param msg 返回内容
* @return 错误消息
*/
public static AjaxResult error(int code, String msg)
{
public static AjaxResult error(int code, String msg) {
return new AjaxResult(code, msg, null);
}
@@ -175,8 +169,7 @@ public class AjaxResult extends HashMap<String, Object>
*
* @return 结果
*/
public boolean isSuccess()
{
public boolean isSuccess() {
return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
}
@@ -185,8 +178,7 @@ public class AjaxResult extends HashMap<String, Object>
*
* @return 结果
*/
public boolean isWarn()
{
public boolean isWarn() {
return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
}
@@ -195,21 +187,15 @@ public class AjaxResult extends HashMap<String, Object>
*
* @return 结果
*/
public boolean isError()
{
public boolean isError() {
return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
}
/**
* 方便链式调用
*
* @param key
* @param value
* @return
*/
@Override
public AjaxResult put(String key, Object value)
{
public AjaxResult put(String key, Object value) {
super.put(key, value);
return this;
}

View File

@@ -0,0 +1,41 @@
package com.ruoyi.common.core.web.domain;
import java.io.Serial;
/**
* 扩展的基础实体类
*
* @author Alan Scipio
* created on 2024/2/2
*/
public class ExtBaseEntity extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 逻辑删除标志。true已删除false未删除
*/
private Integer deleteFlag;
/**
* 更新次数(乐观锁)
*/
private Integer updateCount;
public Integer getDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(Integer deleteFlag) {
this.deleteFlag = deleteFlag;
}
public Integer getUpdateCount() {
return updateCount;
}
public void setUpdateCount(Integer updateCount) {
this.updateCount = updateCount;
}
}

View File

@@ -1,79 +1,80 @@
package com.ruoyi.common.core.web.domain;
import java.io.Serial;
import java.util.ArrayList;
import java.util.List;
/**
* Tree基类
*
*
* @author ruoyi
*/
public class TreeEntity extends BaseEntity
{
public class TreeEntity extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/** 父菜单名称 */
/**
* 父菜单名称
*/
private String parentName;
/** 父菜单ID */
/**
* 父菜单ID
*/
private Long parentId;
/** 显示顺序 */
/**
* 显示顺序
*/
private Integer orderNum;
/** 祖级列表 */
/**
* 祖级列表
*/
private String ancestors;
/** 子部门 */
/**
* 子部门
*/
private List<?> children = new ArrayList<>();
public String getParentName()
{
public String getParentName() {
return parentName;
}
public void setParentName(String parentName)
{
public void setParentName(String parentName) {
this.parentName = parentName;
}
public Long getParentId()
{
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId)
{
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public Integer getOrderNum()
{
public Integer getOrderNum() {
return orderNum;
}
public void setOrderNum(Integer orderNum)
{
public void setOrderNum(Integer orderNum) {
this.orderNum = orderNum;
}
public String getAncestors()
{
public String getAncestors() {
return ancestors;
}
public void setAncestors(String ancestors)
{
public void setAncestors(String ancestors) {
this.ancestors = ancestors;
}
public List<?> getChildren()
{
public List<?> getChildren() {
return children;
}
public void setChildren(List<?> children)
{
public void setChildren(List<?> children) {
this.children = children;
}
}

View File

@@ -4,98 +4,90 @@ import com.ruoyi.common.core.utils.StringUtils;
/**
* 分页数据
*
*
* @author ruoyi
*/
public class PageDomain
{
/** 当前记录起始索引 */
public class PageDomain {
/**
* 当前记录起始索引
*/
private Integer pageNum;
/** 每页显示记录数 */
/**
* 每页显示记录数
*/
private Integer pageSize;
/** 排序列 */
/**
* 排序列
*/
private String orderByColumn;
/** 排序的方向desc或者asc */
/**
* 排序的方向desc或者asc
*/
private String isAsc = "asc";
/** 分页参数合理化 */
/**
* 分页参数合理化
*/
private Boolean reasonable = true;
public String getOrderBy()
{
if (StringUtils.isEmpty(orderByColumn))
{
public String getOrderBy() {
if (StringUtils.isEmpty(orderByColumn)) {
return "";
}
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
}
public Integer getPageNum()
{
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum)
{
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public Integer getPageSize()
{
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize)
{
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public String getOrderByColumn()
{
public String getOrderByColumn() {
return orderByColumn;
}
public void setOrderByColumn(String orderByColumn)
{
public void setOrderByColumn(String orderByColumn) {
this.orderByColumn = orderByColumn;
}
public String getIsAsc()
{
public String getIsAsc() {
return isAsc;
}
public void setIsAsc(String isAsc)
{
if (StringUtils.isNotEmpty(isAsc))
{
public void setIsAsc(String isAsc) {
if (StringUtils.isNotEmpty(isAsc)) {
// 兼容前端排序类型
if ("ascending".equals(isAsc))
{
if ("ascending".equals(isAsc)) {
isAsc = "asc";
}
else if ("descending".equals(isAsc))
{
} else if ("descending".equals(isAsc)) {
isAsc = "desc";
}
this.isAsc = isAsc;
}
}
public Boolean getReasonable()
{
if (StringUtils.isNull(reasonable))
{
public Boolean getReasonable() {
if (StringUtils.isNull(reasonable)) {
return Boolean.TRUE;
}
return reasonable;
}
public void setReasonable(Boolean reasonable)
{
public void setReasonable(Boolean reasonable) {
this.reasonable = reasonable;
}
}

View File

@@ -1,85 +1,84 @@
package com.ruoyi.common.core.web.page;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 表格分页数据对象
*
*
* @author ruoyi
*/
public class TableDataInfo implements Serializable
{
public class TableDataInfo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 总记录数 */
/**
* 总记录数
*/
private long total;
/** 列表数据 */
/**
* 列表数据
*/
private List<?> rows;
/** 消息状态码 */
/**
* 消息状态码
*/
private int code;
/** 消息内容 */
/**
* 消息内容
*/
private String msg;
/**
* 表格数据对象
*/
public TableDataInfo()
{
public TableDataInfo() {
}
/**
* 分页
*
* @param list 列表数据
*
* @param list 列表数据
* @param total 总记录数
*/
public TableDataInfo(List<?> list, int total)
{
public TableDataInfo(List<?> list, int total) {
this.rows = list;
this.total = total;
}
public long getTotal()
{
public long getTotal() {
return total;
}
public void setTotal(long total)
{
public void setTotal(long total) {
this.total = total;
}
public List<?> getRows()
{
public List<?> getRows() {
return rows;
}
public void setRows(List<?> rows)
{
public void setRows(List<?> rows) {
this.rows = rows;
}
public int getCode()
{
public int getCode() {
return code;
}
public void setCode(int code)
{
public void setCode(int code) {
this.code = code;
}
public String getMsg()
{
public String getMsg() {
return msg;
}
public void setMsg(String msg)
{
public void setMsg(String msg) {
this.msg = msg;
}
}

View File

@@ -5,11 +5,10 @@ import com.ruoyi.common.core.utils.ServletUtils;
/**
* 表格数据处理
*
*
* @author ruoyi
*/
public class TableSupport
{
public class TableSupport {
/**
* 当前记录起始索引
*/
@@ -38,8 +37,7 @@ public class TableSupport
/**
* 封装分页对象
*/
public static PageDomain getPageDomain()
{
public static PageDomain getPageDomain() {
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
@@ -49,8 +47,7 @@ public class TableSupport
return pageDomain;
}
public static PageDomain buildPageRequest()
{
public static PageDomain buildPageRequest() {
return getPageDomain();
}
}

View File

@@ -1,32 +1,29 @@
package com.ruoyi.common.core.xss;
import com.ruoyi.common.core.utils.StringUtils;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import com.ruoyi.common.core.utils.StringUtils;
/**
* 自定义xss校验注解实现
*
*
* @author ruoyi
*/
public class XssValidator implements ConstraintValidator<Xss, String>
{
public class XssValidator implements ConstraintValidator<Xss, String> {
private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />";
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext)
{
if (StringUtils.isBlank(value))
{
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
if (StringUtils.isBlank(value)) {
return true;
}
return !containsHtml(value);
}
public static boolean containsHtml(String value)
{
public static boolean containsHtml(String value) {
Pattern pattern = Pattern.compile(HTML_PATTERN);
Matcher matcher = pattern.matcher(value);
return matcher.matches();