This commit is contained in:
clay
2024-03-06 17:44:09 +08:00
commit adaec0eadd
1493 changed files with 219939 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>common</artifactId>
<groupId>cn.fateverse</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common-core</artifactId>
<description>common-core核心模块</description>
<properties>
<guava.version>30.1-jre</guava.version>
</properties>
<dependencies>
<!-- Alibaba Fastjson -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>compile</scope>
</dependency>
<!-- Apache Lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,26 @@
package cn.fateverse.common.core.annotaion;
import cn.fateverse.common.core.enums.MethodEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* mybatis自动注入时间
*
* @author Clay
* @date 2023-05-05
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoTime {
/**
* sql 方法 INSERT,UPDATE
* @return 方法类型
*/
MethodEnum method();
}

View File

@@ -0,0 +1,30 @@
package cn.fateverse.common.core.annotaion;
import cn.fateverse.common.core.enums.AutoUserEnum;
import cn.fateverse.common.core.enums.MethodEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* mybatis自动注入用户信息
*
* @author Clay
* @date 2023-05-05
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoUser {
AutoUserEnum value() default AutoUserEnum.USER_NAME;
/**
* sql 方法 INSERT,UPDATE
*
* @return 方法类型
*/
MethodEnum method();
}

View File

@@ -0,0 +1,17 @@
package cn.fateverse.common.core.annotaion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 开启mybatis自动注入的能力
*
* @author Clay
* @date 2023-05-05
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface EnableAutoField {
}

View File

@@ -0,0 +1,45 @@
package cn.fateverse.common.core.annotaion;
import java.lang.annotation.*;
/**
* 用户实体类需要excel导出的字段
*
* @author Clay
* @date 2022/12/19
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Excel {
/**
* 字段描述
*/
String value() default "";
/**
* 字段排序
*/
int order() default Integer.MAX_VALUE;
/**
* 时间格式
*/
String dateFormat() default "yyyy-MM-dd";
/**
* 字典类型
*/
String dictType() default "";
/**
* 导出时在excel中每个列的高度 单位为字符
* 占时未实现后其迭代
*/
double height() default 14;
/**
* 导出时在excel中每个列的宽 单位为字符
* 占时未实现后其迭代
*/
double width() default 16;
}

View File

@@ -0,0 +1,26 @@
package cn.fateverse.common.core.annotaion;
import java.lang.annotation.*;
/**
* 用于标注当前对象中存在@Excel注解标注的需要导出的字段
*
* @author Clay
* @date 2022/12/19
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Excels {
/**
* 字段描述
*/
String value() default "";
/**
* 字段排序
*/
int order() default Integer.MAX_VALUE;
}

View File

@@ -0,0 +1,23 @@
package cn.fateverse.common.core.annotaion;
import cn.fateverse.common.core.enums.GenIdEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自动生成id
*
* @author Clay
* @date 2023-05-05
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface GenerateId {
GenIdEnum idType() default GenIdEnum.UUID;
}

View File

@@ -0,0 +1,29 @@
package cn.fateverse.common.core.constant;
/**
* 缓存key
* @author Clay
* @date 2022/11/9
*/
public class CacheConstants {
/**
* 验证码 redis key
*/
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* 路由缓存地址
*/
public static final String ROUTE_CACHE_KEY = "router_key:";
/**
* 登录用户 redis key
*/
public static final String LOGIN_TOKEN_KEY = "login_info:";
/**
* 字典类型 redis key
*/
public static final String DICT_KEY = "dict:";
}

View File

@@ -0,0 +1,38 @@
package cn.fateverse.common.core.constant;
/**
* 通用常量信息
*
* @author Clay
*/
public class Constants {
/**
* 令牌前缀
*/
public static final String TOKEN_PREFIX = "Bearer ";
/**
* http请求
*/
public static final String HTTP = "http://";
/**
* https请求
*/
public static final String HTTPS = "https://";
/**
* 令牌前缀
*/
public static final String LOGIN_USER_KEY = "login_user_key";
/**
* 验证码有效期(分钟)
*/
public static final long CAPTCHA_EXPIRATION = 2;
public static final String UTF8 = "UTF-8";
}

View File

@@ -0,0 +1,20 @@
package cn.fateverse.common.core.constant;
/**
* @author Clay
* @date 2023-05-25
*/
public class DateConstants {
public static String YYYY = "yyyy";
public static String YYYY_MM = "yyyy-MM";
public static String YYYY_MM_DD = "yyyy-MM-dd";
public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
}

View File

@@ -0,0 +1,48 @@
package cn.fateverse.common.core.constant;
/**
* 用户常量信息
*
* @author Clay
*/
public class UserConstants {
/**
* 平台内系统用户的唯一标志
*/
public static final String SYS_USER = "SYS_USER";
/**
* 匿名用户
*/
public static final String ANONYMOUS_USER = "anonymousUser";
/**
* 正常状态
*/
public static final String NORMAL = "0";
/**
* 异常状态
*/
public static final String EXCEPTION = "1";
/**
* 部门停用状态
*/
public static final String DEPT_DISABLE = "1";
/**
* Layout组件标识
*/
public final static String LAYOUT = "Layout";
/**
* 校验返回结果码
*/
public final static String UNIQUE = "0";
public final static String NOT_UNIQUE = "1";
}

View File

@@ -0,0 +1,89 @@
package cn.fateverse.common.core.entity;
import cn.fateverse.common.core.annotaion.AutoTime;
import cn.fateverse.common.core.annotaion.AutoUser;
import cn.fateverse.common.core.enums.MethodEnum;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @author Clay
* @date 2022/10/30
*/
public class BaseEntity implements Serializable {
/**
* 创建者
*/
@AutoUser(method = MethodEnum.INSERT)
private Object createBy;
/**
* 创建时间
*/
@AutoTime(method = MethodEnum.INSERT)
@JsonFormat(locale = "zh",timezone = "GMT+8",pattern = "yyyy-MM-dd")
private Date createTime;
/**
* 更新者
*/
@AutoUser(method = MethodEnum.UPDATE)
private Object updateBy;
/**
* 更新时间
*/
@AutoTime(method = MethodEnum.UPDATE)
@JsonFormat(locale = "zh",timezone = "GMT+8",pattern = "yyyy-MM-dd")
private Date updateTime;
/**
* 备注信息
*/
private String remark;
public Object getCreateBy() {
return createBy;
}
public void setCreateBy(Object createBy) {
this.createBy = createBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Object getUpdateBy() {
return updateBy;
}
public void setUpdateBy(Object updateBy) {
this.updateBy = updateBy;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}

View File

@@ -0,0 +1,19 @@
package cn.fateverse.common.core.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @author Clay
* @date 2023-11-14 21:11
*/
@Data
public class IdWrapper implements Serializable {
private Long id;
private List<Long> ids;
}

View File

@@ -0,0 +1,26 @@
package cn.fateverse.common.core.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author Clay
* @date 2022/11/4
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Option {
/**
* 节点ID
*/
private Object value;
/**
* 节点名称
*/
private String label;
}

View File

@@ -0,0 +1,39 @@
package cn.fateverse.common.core.entity;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* Treeselect树结构实体类
*
* @author Clay
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OptionTree implements Serializable {
/**
* 节点ID
*/
private Object value;
/**
* 节点名称
*/
private Object label;
/**
* 子节点
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<OptionTree> children;
}

View File

@@ -0,0 +1,44 @@
package cn.fateverse.common.core.entity;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
/**
* @author Clay
* @date 2022/10/30
*/
@Data
public class PageInfo {
/**
* 当前记录起始索引
*/
private Integer pageNum;
/**
* 每页显示记录数
*/
private Integer pageSize;
/**
* 排序列
*/
private String orderByColumn;
/**
* 排序的方向desc或者asc
*/
private String isAsc = "asc";
/**
* 分页参数合理化
*/
private Boolean reasonable = true;
public String getOrderBy() {
if (StrUtil.isEmpty(orderByColumn)) {
return "";
}
return StrUtil.toUnderlineCase(orderByColumn) + " " + isAsc;
}
}

View File

@@ -0,0 +1,27 @@
package cn.fateverse.common.core.entity;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @author Clay
* @date 2022/11/9
*/
@Data
public class QueryTime implements Serializable {
/**
* 筛选创建时间的开始时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/**
* 筛选创建时间的结束时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
}

View File

@@ -0,0 +1,15 @@
package cn.fateverse.common.core.enums;
/**
* @author Clay
* @date 2023-05-05
*/
public enum AutoUserEnum {
/**
* 用户信息
*/
USER_NAME,
USER_ID,
NICK_NAME,
;
}

View File

@@ -0,0 +1,17 @@
package cn.fateverse.common.core.enums;
/**
* @author Clay
* @date 2023-05-05
*/
public enum GenIdEnum {
/**
* id生成类型
*/
UUID,
SNOWFLAKE
;
}

View File

@@ -0,0 +1,37 @@
package cn.fateverse.common.core.enums;
/**
* @author Clay
* @date 2022/11/9
*/
public enum MenuEnum {
/**
* 状态信息
*/
DIRECTORY("D", "目录"),
MENU("M", "菜单"),
BUTTON("B", "按钮"),
LAYOUT("LAYOUT", "Layout"),
PARENT_VIEW("PARENT_VIEW", "ParentView"),
;
private final String code;
private final String info;
MenuEnum(String code, String info) {
this.code = code;
this.info = info;
}
public String getCode() {
return code;
}
public String getInfo() {
return info;
}
}

View File

@@ -0,0 +1,15 @@
package cn.fateverse.common.core.enums;
/**
* @author Clay
* @date 2023-05-05
*/
public enum MethodEnum {
/**
* 需要设置的方法
*/
UPDATE,
INSERT,
;
}

View File

@@ -0,0 +1,47 @@
package cn.fateverse.common.core.enums;
import org.springframework.http.HttpStatus;
/**
* @author Clay
* @date 2023-05-10
*/
public enum ResultEnum {
/**
* 返回状态枚举
*/
SUCCESS(1000, "操作成功", HttpStatus.OK),
NO_DATA(1001, "查询结果为空", HttpStatus.OK),
RESUBMIT_LOCK(2002, "重复提交", HttpStatus.INTERNAL_SERVER_ERROR),
ERROR(2000, "操作失败", HttpStatus.INTERNAL_SERVER_ERROR),
SYS_ERROR(2001, "系统异常", HttpStatus.INTERNAL_SERVER_ERROR),
SENTINEL_FLOW(3000, "限流了", HttpStatus.INTERNAL_SERVER_ERROR),
SENTINEL_PARAM_FLOW(3000, "热点参数限流", HttpStatus.INTERNAL_SERVER_ERROR),
SENTINEL_SYSTEM(3000, "系统规则负载等不满足要求", HttpStatus.INTERNAL_SERVER_ERROR),
SENTINEL_AUTHORITY(3000, "授权规则不通过", HttpStatus.UNAUTHORIZED),
SENTINEL_DEGRADE(3000, "降级了", HttpStatus.INTERNAL_SERVER_ERROR),
;
ResultEnum(int code, String msg, HttpStatus status) {
this.code = code;
this.msg = msg;
this.status = status;
}
public final int code;
public final String msg;
public final transient HttpStatus status;
}

View File

@@ -0,0 +1,32 @@
package cn.fateverse.common.core.enums;
/**
* @author Clay
* @date 2022/11/6
*/
public enum StateEnum {
/**
* 状态信息
*/
NORMAL("1", "正常"),
DISABLE("0", "停用");
private final String code;
private final String info;
StateEnum(String code, String info) {
this.code = code;
this.info = info;
}
public String getCode() {
return code;
}
public String getInfo() {
return info;
}
}

View File

@@ -0,0 +1,33 @@
package cn.fateverse.common.core.enums;
/**
* 用户状态
*
* @author Clay
* @date 2022/10/30
*/
public enum UserState {
/**
* 用户状态信息
*/
DISABLE("0", "停用"),
OK("1", "正常"),
DELETED("2", "删除");
private final String code;
private final String info;
UserState(String code, String info) {
this.code = code;
this.info = info;
}
public String getCode() {
return code;
}
public String getInfo() {
return info;
}
}

View File

@@ -0,0 +1,81 @@
package cn.fateverse.common.core.exception;
/**
* 基础异常
*
* @author Clay
* @date 2022/10/30
*/
public class BaseException extends RuntimeException {
/**
* 所属模块
*/
private String module;
/**
* 错误码
*/
private String code;
/**
* 错误码对应的参数
*/
private Object[] args;
/**
* 错误消息
*/
private String defaultMessage;
public BaseException(String module, String code, Object[] args, String defaultMessage) {
this.module = module;
this.code = code;
this.args = args;
this.defaultMessage = defaultMessage;
}
public BaseException(String module, String code, Object[] args) {
this(module, code, args, null);
}
public BaseException(String module, String defaultMessage) {
this(module, null, null, defaultMessage);
}
public BaseException(String code, Object[] args) {
this(null, code, args, null);
}
public BaseException(String defaultMessage) {
this(null, null, null, defaultMessage);
}
@Override
public String getMessage() {
String message = null;
if (message == null) {
message = defaultMessage;
}
return message;
}
public String getModule() {
return module;
}
public String getCode() {
return code;
}
public Object[] getArgs() {
return args;
}
public String getDefaultMessage() {
return defaultMessage;
}
}

View File

@@ -0,0 +1,44 @@
package cn.fateverse.common.core.exception;
/**
* 自定义异常
*
* @author Clay
* @date 2022/10/29
*/
public class CustomException extends RuntimeException {
private Integer code;
private String message;
public CustomException(String message) {
this.message = message;
}
public CustomException(String message, Integer code) {
this.message = message;
this.code = code;
}
public CustomException(String message, Throwable e) {
super(message, e);
this.message = message;
}
public CustomException() {
}
@Override
public String getMessage() {
return message;
}
public Integer getCode() {
return code;
}
}

View File

@@ -0,0 +1,10 @@
package cn.fateverse.common.core.exception;
import cn.fateverse.common.core.enums.ResultEnum;
public class TierDownException extends CustomException {
public TierDownException(String message) {
super(ResultEnum.SYS_ERROR.msg);
}
}

View File

@@ -0,0 +1,15 @@
package cn.fateverse.common.core.exception;
/**
* 用户信息异常类
*
* @author Clay
* @date 2022/10/30
*/
public class UserException extends BaseException {
public UserException(String code, Object[] args) {
super("user", code, args, null);
}
}

View File

@@ -0,0 +1,16 @@
package cn.fateverse.common.core.exception;
/**
* 用户密码不正确或不符合规范异常类
*
* @author Clay
* @date 2022/10/30
*/
public class UserPasswordNotMatchException extends UserException {
public UserPasswordNotMatchException() {
super("user.password.not.match", null);
}
}

View File

@@ -0,0 +1,149 @@
package cn.fateverse.common.core.result;
import cn.fateverse.common.core.enums.ResultEnum;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.springframework.http.HttpStatus;
import java.io.Serializable;
/**
* 返回结果集
*
* @author: Clay
* @date: 2022/5/31 10:00
*/
public class Result<T> implements Serializable {
private Integer code;
private String msg;
private T data;
private transient HttpStatus status;
public Result() {
}
public Result(Integer code, String msg, T data, HttpStatus status) {
this.code = code;
this.msg = msg;
this.data = data;
this.status = status;
}
public static <T> Result<T> ok(Integer code, String msg, T data) {
return new Result<>(code, msg, data, HttpStatus.OK);
}
public static <T> Result<T> ok(Integer code, String msg, T data, HttpStatus status) {
return new Result<>(code, msg, data, status);
}
public static <T> Result<T> ok(String msg, T data) {
return Result.ok(ResultEnum.SUCCESS.code, msg, data, ResultEnum.SUCCESS.status);
}
public static <T> Result<T> ok(Integer code, T data) {
return Result.ok(code, ResultEnum.SUCCESS.msg, data);
}
public static <T> Result<T> ok(String msg) {
return ok(ResultEnum.SUCCESS.code, msg, null);
}
public static <T> Result<T> ok(T data) {
return Result.ok(ResultEnum.SUCCESS.msg, data);
}
public static <T> Result<T> ok() {
return Result.ok(ResultEnum.SUCCESS.msg, null);
}
public static <T> Result<T> error(String msg, T data) {
return Result.error(ResultEnum.ERROR.code, msg, data);
}
public static <T> Result<T> error(Integer code, String msg) {
return Result.error(code, msg, null);
}
public static <T> Result<T> notFound(String msg) {
return Result.error(HttpStatus.NOT_FOUND.value(), msg, null, HttpStatus.NOT_FOUND);
}
public static <T> Result<T> error(Integer code, String msg, T data) {
return new Result<>(code, msg, data, HttpStatus.INTERNAL_SERVER_ERROR);
}
public static <T> Result<T> error(Integer code, String msg, T data, HttpStatus status) {
return new Result<>(code, msg, data, status);
}
public static <T> Result<T> unauthorized(String msg) {
return new Result<>(HttpStatus.UNAUTHORIZED.value(), msg, null, HttpStatus.UNAUTHORIZED);
}
public static <T> Result<T> error(HttpStatus status, String msg) {
return new Result<>(status.value(), msg, null, status);
}
public static <T> Result<T> error(ResultEnum resultEnum) {
return Result.error(resultEnum.code, resultEnum.msg, null, resultEnum.status);
}
public static <T> Result<T> error(String msg) {
return Result.error(ResultEnum.ERROR.code, msg, null, ResultEnum.ERROR.status);
}
public static <T> Result<T> error() {
return Result.error(ResultEnum.ERROR.code, ResultEnum.ERROR.msg, null);
}
public static <T> Result<T> info(String msg) {
return Result.ok(ResultEnum.NO_DATA.code, msg, null);
}
public static <T> Result<T> info(ResultEnum resultEnum) {
return Result.error(resultEnum.code, resultEnum.msg, null, resultEnum.status);
}
public static <T> Result<T> noData() {
return Result.ok(ResultEnum.NO_DATA.code, ResultEnum.NO_DATA.msg, null);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@JsonIgnore
public HttpStatus getStatus() {
return status;
}
@JsonIgnore
public void setStatus(HttpStatus status) {
this.status = status;
}
}

View File

@@ -0,0 +1,46 @@
package cn.fateverse.common.core.result.page;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 表格分页数据对象
*
* @author binlin
*/
@Data
public class TableDataInfo<T> implements Serializable {
/**
* 总记录数
*/
private long total;
/**
* 列表数据
*/
private List<T> rows;
/**
* 表格数据对象
*/
public TableDataInfo() {
}
/**
* 分页
*
* @param list 列表数据
* @param total 总记录数
*/
public TableDataInfo(List<T> list, int total) {
this.rows = list;
this.total = total;
}
}

View File

@@ -0,0 +1,272 @@
package cn.fateverse.common.core.utils;
import cn.fateverse.common.core.annotaion.AutoTime;
import cn.fateverse.common.core.annotaion.AutoUser;
import cn.fateverse.common.core.constant.UserConstants;
import cn.fateverse.common.core.enums.AutoUserEnum;
import cn.fateverse.common.core.enums.MethodEnum;
import cn.fateverse.common.core.exception.CustomException;
import com.alibaba.fastjson2.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Set;
/**
* @author Clay
* @date 2023-05-25
*/
public class AutoSetValueUtils {
private static final Logger log = LoggerFactory.getLogger(AutoSetValueUtils.class);
public static final String LONG_TYPE = "java.lang.Long";
public static final String OBJECT_TYPE = "java.lang.Object";
public static final String STRING_TYPE = "java.lang.String";
public static String BASE_PACKAGE;
static {
BASE_PACKAGE = getBasePackage(AutoSetValueUtils.class);
}
public static String getBasePackage(Class<?> clazz) {
String typeName = clazz.getTypeName();
int fastIndex = typeName.indexOf(".");
return typeName.substring(0, typeName.indexOf(".", fastIndex + 1));
}
/**
* 自动设置userID
*
* @param parameter 参数
* @param methodEnum sql方法
* @param field 字段
*/
public static void autoUser(Object parameter, MethodEnum methodEnum, Field field) {
//获取到设置用户id的注解
AutoUser autoUser = field.getAnnotation(AutoUser.class);
if (null != autoUser && autoUser.method() == methodEnum) {
SecurityContext context = SecurityContextHolder.getContext();
if (context == null) {
return;
}
Object principal = context.getAuthentication().getPrincipal();
if (null == principal || UserConstants.ANONYMOUS_USER.equals(principal)) {
return;
}
JSONObject user = ReflectUserUtils.getUser(principal);
AutoUserEnum value = autoUser.value();
Class<?> type = field.getType();
Object object = null;
String typeName = type.getTypeName();
if (value == AutoUserEnum.USER_ID) {
//设置用户id
long userId = user.getLongValue("userId");
switch (typeName) {
case OBJECT_TYPE:
case LONG_TYPE:
object = userId;
break;
case STRING_TYPE:
object = Long.toString(userId);
break;
default:
break;
}
} else if (value == AutoUserEnum.USER_NAME || value == AutoUserEnum.NICK_NAME) {
object = value == AutoUserEnum.USER_NAME ? user.getString("userName") : user.getString("nickName");
if (!(OBJECT_TYPE.equals(typeName) || STRING_TYPE.equals(typeName))) {
throw new CustomException("数据类型不配配,Field字段类型为" + typeName + "不能放入String类型的数据");
}
} else {
return;
}
try {
field.setAccessible(true);
field.set(parameter, object);
} catch (IllegalAccessException e) {
log.error("字段:{}自动设置参数失败", field.getName());
}
}
}
/**
* 自动设置时间
*
* @param parameter 参数
* @param methodEnum sql方法
* @param field 字段
*/
public static void autoTime(Object parameter, MethodEnum methodEnum, Field field) {
//获取到设置时间的注解
AutoTime autoTime = field.getAnnotation(AutoTime.class);
if (null != autoTime && autoTime.method() == methodEnum) {
field.setAccessible(true);
Class<?> type = field.getType();
Object time = null;
try {
time = type.newInstance();
field.set(parameter, time);
} catch (InstantiationException | IllegalAccessException e) {
log.error("字段:{}自动设置参数失败,参数为:{}", field.getName(), time);
}
}
}
/**
* 自动设置userID
*
* @param parameter 参数
* @param methodEnum sql方法
* @param fields 字段
*/
public static void autoUserNew(Object parameter, MethodEnum methodEnum, Set<Field> fields) {
SecurityContext context = SecurityContextHolder.getContext();
if (context == null) {
return;
}
Authentication authentication = context.getAuthentication();
if (null == authentication) {
return;
}
Object principal = authentication.getPrincipal();
if (null == principal || UserConstants.ANONYMOUS_USER.equals(principal)) {
return;
}
JSONObject user = ReflectUserUtils.getUser(principal);
for (Field field : fields) {
setUser(methodEnum, user, parameter, field);
}
}
/**
* 自动设置时间
*
* @param parameter 参数
* @param methodEnum sql方法
* @param fields 字段
*/
public static void autoTimeNew(Object parameter, MethodEnum methodEnum, Set<Field> fields) {
for (Field field : fields) {
setTime(methodEnum, parameter, field);
}
}
/**
* 自动设置userID
*
* @param list 参数
* @param methodEnum sql方法
* @param fields 字段
*/
public static void autoUserList(List<Object> list, MethodEnum methodEnum, Set<Field> fields) {
if (fields.isEmpty()) {
return;
}
SecurityContext context = SecurityContextHolder.getContext();
if (context == null) {
return;
}
Object principal = context.getAuthentication().getPrincipal();
if (null == principal || UserConstants.ANONYMOUS_USER.equals(principal)) {
return;
}
JSONObject user = ReflectUserUtils.getUser(principal);
for (Object param : list) {
for (Field field : fields) {
setUser(methodEnum, user, param, field);
}
}
}
/**
* 设置用户通用函数
*
* @param methodEnum 方法类型
* @param user 用户信息
* @param param 参数对象
* @param field 字段对象
*/
private static void setUser(MethodEnum methodEnum, JSONObject user, Object param, Field field) {
long userId = user.getLongValue("userId");
//获取到设置用户id的注解
AutoUser autoUser = field.getAnnotation(AutoUser.class);
if (null != autoUser && autoUser.method() == methodEnum) {
AutoUserEnum value = autoUser.value();
Class<?> type = field.getType();
Object object = null;
String typeName = type.getTypeName();
if (value == AutoUserEnum.USER_ID) {
//设置用户id
if (type == Object.class || type == Long.class) {
object = userId;
} else if (type == String.class) {
object = Long.toString(userId);
}
} else if (value == AutoUserEnum.USER_NAME || value == AutoUserEnum.NICK_NAME) {
object = value == AutoUserEnum.USER_NAME ? user.getString("userName") : user.getString("nickName");
if (!(type == Object.class || type == Long.class)) {
throw new CustomException("数据类型不配配,Field字段类型为" + typeName + "不能放入String类型的数据");
}
} else {
return;
}
try {
field.setAccessible(true);
field.set(param, object);
} catch (IllegalAccessException e) {
log.error("字段:{}自动设置参数失败", field.getName());
}
}
}
/**
* 自动设置时间
*
* @param list 参数
* @param methodEnum sql方法
* @param fields 时间
*/
public static void autoTimeList(List<Object> list, MethodEnum methodEnum, Set<Field> fields) {
if (fields.isEmpty()) {
return;
}
for (Object param : list) {
for (Field field : fields) {
setTime(methodEnum, param, field);
}
}
}
/**
* 设置时间
*
* @param methodEnum 方法类型
* @param param 参数对象
* @param field 字段
*/
private static void setTime(MethodEnum methodEnum, Object param, Field field) {
//获取到设置时间的注解
AutoTime autoTime = field.getAnnotation(AutoTime.class);
if (null != autoTime && autoTime.method() == methodEnum) {
field.setAccessible(true);
Class<?> type = field.getType();
Object time = null;
try {
time = type.newInstance();
field.set(param, time);
} catch (InstantiationException | IllegalAccessException e) {
log.error("字段:{}自动设置参数失败,参数为:{}", field.getName(), time);
}
}
}
}

View File

@@ -0,0 +1,36 @@
package cn.fateverse.common.core.utils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author Clay
* @date 2023-05-10
*/
public class HttpServletUtils {
/**
* 获取request信息
* @return
*/
public static HttpServletRequest getRequest() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
return attributes.getRequest();
}
/**
* 获取http响应对象
*
* @return response
*/
public static HttpServletResponse getResponse() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
return attributes.getResponse();
}
}

View File

@@ -0,0 +1,56 @@
package cn.fateverse.common.core.utils;
import cn.fateverse.common.core.exception.CustomException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @author Clay
* @date 2023-10-15
*/
public class IpBackUtils {
public static final String BLACK_LIST = "black:list:";
public final static String BLACK_LIST_IPV_4 = BLACK_LIST + "ipv4";
public final static String BLACK_LIST_IPV_6 = BLACK_LIST + "ipv6";
public final static String BLACK_LIST_IP = BLACK_LIST + "ip";
public final static String IPV_4 = "ipv4";
public final static String IPV_6 = "ipv6";
public static long ipToDecimal(String ipAddress) {
try {
// 将IP地址拆分为四个部分
String[] ipParts = ipAddress.split("\\.");
// 将每个部分转换为整数
long decimalNumber = 0;
for (int i = 0; i < 4; i++) {
long ipPart = Long.parseLong(ipParts[i]);
// 每个部分的权重为256的(3-i)次方
decimalNumber += ipPart * Math.pow(256, 3 - i);
}
return decimalNumber;
} catch (Exception e) {
return 0;
}
}
public static String getIpType(String ip) {
try {
InetAddress address = InetAddress.getByName(ip);
if (address instanceof Inet4Address) {
return IPV_4;
} else if (address instanceof Inet6Address) {
return IPV_6;
}
} catch (UnknownHostException e) {
throw new CustomException("无效ip地址");
}
throw new CustomException("无效ip地址");
}
}

View File

@@ -0,0 +1,167 @@
package cn.fateverse.common.core.utils;
import cn.hutool.http.HtmlUtil;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* 获取IP方法
*
* @author binlin
*/
public class IpUtils {
public static String getIpAdder(HttpServletRequest request) {
if (request == null) {
return "unknown";
}
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.removeHtmlTag(ip);
}
public static boolean internalIp(String ip) {
byte[] addr = textToNumericFormatV4(ip);
return internalIp(addr) || "127.0.0.1".equals(ip);
}
private static boolean internalIp(byte[] addr) {
if (ObjectUtils.isEmpty(addr) || addr.length < 2) {
return true;
}
final byte b0 = addr[0];
final byte b1 = addr[1];
// 10.x.x.x/8
final byte SECTION_1 = 0x0A;
// 172.16.x.x/12
final byte SECTION_2 = (byte) 0xAC;
final byte SECTION_3 = (byte) 0x10;
final byte SECTION_4 = (byte) 0x1F;
// 192.168.x.x/16
final byte SECTION_5 = (byte) 0xC0;
final byte SECTION_6 = (byte) 0xA8;
switch (b0) {
case SECTION_1:
return true;
case SECTION_2:
if (b1 >= SECTION_3 && b1 <= SECTION_4) {
return true;
}
case SECTION_5:
switch (b1) {
case SECTION_6:
return true;
}
default:
return false;
}
}
/**
* 将IPv4地址转换成字节
*
* @param text IPv4地址
* @return byte 字节
*/
public static byte[] textToNumericFormatV4(String text) {
if (text.length() == 0) {
return null;
}
byte[] bytes = new byte[4];
String[] elements = text.split("\\.", -1);
try {
long l;
int i;
switch (elements.length) {
case 1:
l = Long.parseLong(elements[0]);
if ((l < 0L) || (l > 4294967295L)) {
return null;
}
bytes[0] = (byte) (int) (l >> 24 & 0xFF);
bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 2:
l = Integer.parseInt(elements[0]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[0] = (byte) (int) (l & 0xFF);
l = Integer.parseInt(elements[1]);
if ((l < 0L) || (l > 16777215L)) {
return null;
}
bytes[1] = (byte) (int) (l >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 3:
for (i = 0; i < 2; ++i) {
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
l = Integer.parseInt(elements[2]);
if ((l < 0L) || (l > 65535L)) {
return null;
}
bytes[2] = (byte) (int) (l >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 4:
for (i = 0; i < 4; ++i) {
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
break;
default:
return null;
}
} catch (NumberFormatException e) {
return null;
}
return bytes;
}
public static String getHostIp() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
}
return "127.0.0.1";
}
public static String getHostName() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
}
return "未知";
}
}

View File

@@ -0,0 +1,34 @@
package cn.fateverse.common.core.utils;
import cn.fateverse.common.core.exception.CustomException;
/**
* Long工具类
*
* @author Clay
* @date 2022/11/6
*/
public class LongUtils {
public static boolean isNull(Long num){
return null == num || 0L == num;
}
public static boolean isNotNull(Long num){
return !isNull(num);
}
public static void checkId(Long pk){
checkId(pk,"缺少必要参数!");
}
public static void checkId(Long pk, String message){
if (isNull(pk)) {
throw new CustomException(message);
}
}
}

View File

@@ -0,0 +1,16 @@
package cn.fateverse.common.core.utils;
import cn.fateverse.common.core.enums.MenuEnum;
/**
* @author Clay
* @date 2022/11/9
*/
public class MenuTypeUtils {
public static boolean checkMenuTypeLegal(String menuType){
return MenuEnum.MENU.getInfo().equals(menuType) ||
MenuEnum.DIRECTORY.getInfo().equals(menuType)||
MenuEnum.BUTTON.getInfo().equals(menuType);
}
}

View File

@@ -0,0 +1,59 @@
package cn.fateverse.common.core.utils;
import cn.fateverse.common.core.exception.CustomException;
import java.util.List;
/**
* @author Clay
* @date 2022/12/18
*/
public class ObjectUtils extends org.springframework.util.ObjectUtils {
/**
* 检查主键
* @param pk 主键
*/
public static void checkPk(Object pk) {
checkPk(pk, "缺少必要参数!");
}
/**
* 检查主键
* @param pk 主键
* @param message 错误提示消息
*/
public static void checkPk(Object pk, String message) {
if (pk instanceof Long) {
LongUtils.checkId((Long) pk, message);
} else if (pk instanceof String) {
if (isEmpty(pk)) {
throw new CustomException(message);
}
} else {
if (null == pk) {
throw new CustomException(message);
}
}
}
/**
* 检查主键list
* @param pkList 主键list
*/
public static void checkPkList(List<?> pkList) {
checkPkList(pkList,"缺少必要参数!");
}
/**
* 检查主键list
* @param pkList 主键list
* @param message 错误提示消息
*/
public static void checkPkList(List<?> pkList, String message) {
if (isEmpty(pkList)){
throw new CustomException(message);
}
}
}

View File

@@ -0,0 +1,122 @@
package cn.fateverse.common.core.utils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
/**
* @author Clay
* @date 2023-05-10
*/
public class ReflectUserUtils {
/**
* 从loginUser中获取到用户信息
*
* @param loginUser 登录后的用户
* @return 用户的字段信息
*/
private static Field getUserField(Object loginUser) {
Class<?> userClass = loginUser.getClass();
try {
return userClass.getDeclaredField("user");
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
/**
* 获取到token 信息
*
* @param loginUser 登录后的用户
* @return token
*/
public static String getToken(Object loginUser) {
Class<?> loginUserClass = loginUser.getClass();
Field token;
try {
token = loginUserClass.getDeclaredField("token");
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
return getValue(loginUser, token).toString();
}
/**
* 获取用户信息
*
* @param loginUser 登录后的用户
* @return 用户信息
*/
public static JSONObject getUser(Object loginUser) {
Field userField = getUserField(loginUser);
Object user = getValue(loginUser, userField);
return (JSONObject) JSON.toJSON(user);
}
/**
* 获取到用户Id
*
* @param loginUser 登录后的用户
* @return 用户id
*/
public static String getUserId(Object loginUser) {
return getFieldValue(loginUser, "userId");
}
/**
* 获取到用户名
*
* @param loginUser 登录后的用户
* @return 用户名
*/
public static String getUsername(Object loginUser) {
return getFieldValue(loginUser, "userName");
}
/**
* 获取到用户别名
*
* @param loginUser 登录后的用户
* @return 用户别名
*/
public static String getNickname(Object loginUser) {
return getFieldValue(loginUser, "nickName");
}
/**
* 获取到值
*
* @param user 登录后的用户
* @param field 字段
* @return 值
*/
private static Object getValue(Object user, Field field) {
field.setAccessible(true);
return ReflectionUtils.getField(field, user);
}
/**
* 通过字段名获取到值
*
* @param loginUser 登录后的用户
* @param fieldName 字段名
* @return 值
*/
private static String getFieldValue(Object loginUser, String fieldName) {
Field userField = getUserField(loginUser);
Class<?> userClass = userField.getType().getSuperclass();
Object user = getValue(loginUser, userField);
Field field = null;
try {
field = userClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
return getValue(user, field).toString();
}
}

View File

@@ -0,0 +1,80 @@
package cn.fateverse.common.core.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Lazy;
/**
* Spring 事件发布工具类
* @author Clay
* @date 2022/11/1
*/
@Slf4j
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
private static ApplicationContext applicationContext = null;
/**
* 从applicationContext中获取到Bean,并转换成为requiredType对应的类型
*/
public static <T> T getBean(Class<T> requiredType){
return applicationContext.getBean(requiredType);
}
/**
* 从applicationContext中获取Bean,并自动转成对应接受的类型
*/
public static <T> T getBean(String name){
return (T) applicationContext.getBean(name);
}
/**
* 发布事件,实现异步执行功能
* @param event
*/
public static void publishEvent(ApplicationEvent event){
if (applicationContext == null){
return;
}
applicationContext.publishEvent(event);
}
/**
*
* @throws Exception
*/
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
/**
* 清除SpringContextHolder中的applicationContext
*/
public static void clearHolder(){
//如果是debug环境下,打印清除ApplicationContext的日志
if (log.isDebugEnabled()){
log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
}
applicationContext = null;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextHolder.applicationContext = applicationContext;
}
@Override
public void destroy() throws Exception {
SpringContextHolder.clearHolder();
}
}

View File

@@ -0,0 +1,15 @@
package cn.fateverse.common.core.utils;
import cn.fateverse.common.core.enums.StateEnum;
/**
* @author Clay
* @date 2022/11/6
*/
public class StateUtils {
public static boolean checkStateLegal(String state){
return StateEnum.NORMAL.getCode().equals(state) ||
StateEnum.DISABLE.getCode().equals(state);
}
}

View File

@@ -0,0 +1,80 @@
package cn.fateverse.common.core.utils;
import cn.fateverse.common.core.entity.PageInfo;
import cn.hutool.core.convert.Convert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* 表格数据处理
*
* @author Clay
* @date 2022/10/30
*/
public class TableSupport {
/**
* 当前记录起始索引
*/
public static final String PAGE_NUM = "pageNum";
/**
* 每页显示记录数
*/
public static final String PAGE_SIZE = "pageSize";
/**
* 排序列
*/
public static final String ORDER_BY_COLUMN = "orderByColumn";
/**
* 排序的方向 "desc" 或者 "asc".
*/
public static final String IS_ASC = "isAsc";
/**
* 分页参数合理化
*/
public static final String REASONABLE = "reasonable";
/**
* 封装分页对象
*/
public static PageInfo getPageInfo() {
PageInfo pageInfo = new PageInfo();
pageInfo.setPageNum(Convert.toInt(getParameter(PAGE_NUM), 1));
pageInfo.setPageSize(Convert.toInt(getParameter(PAGE_SIZE), 10));
pageInfo.setOrderByColumn(getParameter(ORDER_BY_COLUMN));
pageInfo.setIsAsc(getParameter(IS_ASC));
pageInfo.setReasonable(getParameterToBool(REASONABLE));
return pageInfo;
}
public static PageInfo buildPageRequest() {
return getPageInfo();
}
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name) {
return Convert.toBool(getRequest().getParameter(name));
}
/**
* 获取String参数
*/
public static String getParameter(String name) {
return Convert.toStr(getRequest().getParameter(name));
}
public static HttpServletRequest getRequest() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
return attributes.getRequest();
}
}

View File

@@ -0,0 +1,56 @@
package cn.fateverse.common.core.utils.convert;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* @author Clay
* @date 2022/11/16
*/
public class ObjectConfig {
private boolean copy;
private Map<String,String> mapper;
private Set<String> exclude;
public ObjectConfig() {
mapper = new LinkedHashMap<>();
exclude = new LinkedHashSet<>();
copy = true;
}
public void setMapper(String targetKey, String sourceKey){
mapper.put(targetKey,sourceKey);
}
public void setExclude(String excludeKey){
exclude.add(excludeKey);
}
public Map<String,String> getMapper(){
return mapper;
}
public Set<String> getExclude() {
return exclude;
}
public void setOption(String value,String label){
this.copy = false;
mapper.put("label",label);
mapper.put("value",value);
}
public boolean isCopy() {
return copy;
}
public void setCopy(boolean copy) {
this.copy = copy;
}
}

View File

@@ -0,0 +1,112 @@
package cn.fateverse.common.core.utils.convert;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* @author Clay
* @date 2022/11/16
* 对象之间的转换
*/
public class ObjectConvertUtil {
private static TreeConfig treeConfig;
private static Map<String, Field> cacheTargetField;
private static Map<String,Field> cacheSourceField;
/**
* 目标class
*/
private static Class<?> targetClass;
private static Class<?> sourceClass;
/**
*
* @param list
* @param target
* @param config
* @return
* @param <T>
*/
@SuppressWarnings("unchecked")
public static <T> List<T> build(List<?> list, Class<T> target, Consumer<TreeConfig> config) {
if (list.isEmpty()){
return new ArrayList<>();
}
//将目标class对象设置为全局对象
targetClass = target;
sourceClass = list.get(0).getClass();
//初始化config
treeConfig = new TreeConfig();
//将目标class对象设置为全局对象
//提供给实现类对config进行修改
config.accept(treeConfig);
List<Object> collect = list.stream().map(ObjectConvertUtil::conversion).collect(Collectors.toList());
return (List<T>) collect;
}
@SuppressWarnings("unchecked")
private static <T> T conversion(Object object) {
try {
Object targetObject = targetClass.newInstance();
//相同字段名称直接赋值
if (treeConfig.isCopy()) {
BeanUtils.copyProperties(object, targetObject);
}
//不同字段名进行赋值
for (Map.Entry<String, String> entry : treeConfig.getMapper().entrySet()) {
Object value = getSourceValue(object,entry.getValue());
setTargetValue(targetObject,entry.getKey(),value);
}
for (String key : treeConfig.getExclude()) {
setTargetValue(targetObject,key,null);
}
//返回结果
return (T) targetObject;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static Object getSourceValue(Object source,String sourceFiled){
Field field = cacheSourceField.get(sourceFiled);
if (null == field){
try {
field = sourceClass.getDeclaredField(sourceFiled);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
cacheSourceField.put(sourceFiled,field);
}
field.setAccessible(true);
return ReflectionUtils.getField(field,source);
}
private static void setTargetValue(Object target,String targetFiled,Object value){
Field field = cacheTargetField.get(targetFiled);
if (null == field){
try {
field = targetClass.getDeclaredField(targetFiled);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
cacheTargetField.put(targetFiled,field);
}
field.setAccessible(true);
ReflectionUtils.setField(field,target,value);
}
}

View File

@@ -0,0 +1,126 @@
package cn.fateverse.common.core.utils.convert;
import cn.hutool.core.util.StrUtil;
import java.util.*;
/**
* @author Clay
* @date 2022/11/16
* TreeConfig的配置文件
*/
public class TreeConfig {
private boolean copy;
private final Map<String, String> mapper;
private final Set<String> exclude;
private String idField;
private String parentField;
private String childrenField;
private Boolean isStore = false;
private String storeField;
public TreeConfig() {
mapper = new LinkedHashMap<>();
exclude = new LinkedHashSet<>();
copy = true;
this.idField = "id";
this.parentField = "parentId";
this.childrenField = "children";
}
public void setParentField(String parentField) {
if (StrUtil.isEmpty(parentField)) {
return;
}
this.parentField = parentField;
}
public Boolean getStore() {
return isStore;
}
public String getStoreField() {
return storeField;
}
public String getParentField() {
return parentField;
}
public String getIdField() {
return idField;
}
public void setIdField(String idField) {
if (StrUtil.isEmpty(idField)) {
return;
}
this.idField = idField;
}
public void setSortOrder(Boolean isStore,String storeField) {
this.isStore = isStore;
this.storeField = storeField;
}
public String getChildrenField() {
return childrenField;
}
public void setChildrenField(String childrenField) {
if (StrUtil.isEmpty(childrenField)) {
return;
}
this.childrenField = childrenField;
}
public void setMapper(String targetKey, String sourceKey) {
mapper.put(targetKey, sourceKey);
}
public void setExclude(String excludeKey) {
exclude.add(excludeKey);
}
public Map<String, String> getMapper() {
return mapper;
}
public Set<String> getExclude() {
return exclude;
}
public void setOption(String valueField, String labelField) {
this.copy = false;
mapper.put("value", valueField);
mapper.put("label", labelField);
}
public boolean isCopy() {
return copy;
}
public void setCopy(boolean copy) {
this.copy = copy;
}
/**
* 空实现
*/
//@Override
//public void build(TreeConfig treeConfig) {
//}
}

View File

@@ -0,0 +1,185 @@
package cn.fateverse.common.core.utils.convert;
import cn.hutool.core.convert.Convert;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* @author Clay
* @date 2022/11/16
* 树形结构转换递归方式
*/
@SuppressWarnings("unchecked")
public class TreeUtil {
/**
* 配置信息
*/
private static TreeConfig treeConfig;
private static Map<String, Field> cacheTargetField;
private static Map<String, Field> cacheSourceField;
/**
* 目标class
*/
private static Class<?> targetClass;
private static Class<?> sourceClass;
/**
* 构建tree结构
*
* @param list 需要转换的list
* @param target 目标class对象
* @param config 配置项
* @param <T> 目标对象类型
* @return
*/
public static <T> List<T> build(List<?> list, Class<T> target, Consumer<TreeConfig> config) {
if (list.isEmpty()) {
return new ArrayList<>();
}
//将目标class对象设置为全局对象
targetClass = target;
sourceClass = list.get(0).getClass();
//初始化config
treeConfig = new TreeConfig();
//初始化字段缓存
cacheTargetField = new HashMap<>();
cacheSourceField = new HashMap<>();
//提供给实现类对config进行修改
config.accept(treeConfig);
//获取到最小的
Object min = list.stream().min(Comparator.comparing(object -> getParentId(object).toString())).get();
//获取到最小的父级id
Object minPid = getParentId(min);
//将数据通过他们的各自的父id进行分组
Map<Object, List<Object>> listMap = list.stream().collect(Collectors.groupingBy(TreeUtil::getParentId));
//最终开始进行tree的构建
return getChildren(listMap, minPid);
}
/**
* 获取到子节点
*
* @param listMap
* @param parentId
* @param <T>
* @return
*/
private static <T> List<T> getChildren(Map<Object, List<Object>> listMap, Object parentId) {
//获取到缓存中的list
List<?> objects = listMap.get(parentId);
if (chickList(objects)) {
return null;
}
if (treeConfig.getStore()) {
objects = objects.stream().sorted(Comparator.comparing(item ->
Convert.toInt(getSourceValue(item, treeConfig.getStoreField()))
)).collect(Collectors.toList());
}
listMap.remove(parentId);
//遍历数组,并将对象一一的转换
List<Object> collect = objects.stream().map(object ->
conversion(object, listMap)).collect(Collectors.toList());
return (List<T>) collect;
}
/**
* 对象直接的字段进行转换
*
* @param object
* @param listMap
* @param <T>
* @return
*/
private static <T> T conversion(Object object, Map<Object, List<Object>> listMap) {
try {
Object targetObject = targetClass.newInstance();
//相同字段名称直接赋值
if (treeConfig.isCopy()) {
BeanUtils.copyProperties(object, targetObject);
}
//不同字段名进行赋值
for (Map.Entry<String, String> entry : treeConfig.getMapper().entrySet()) {
Object value = getSourceValue(object, entry.getValue());
setTargetValue(targetObject, entry.getKey(), value);
}
//设置子节点
Object id = getSourceValue(object, treeConfig.getIdField());
List<Object> children = getChildren(listMap, id);
if (!chickList(children)) {
setTargetValue(targetObject, treeConfig.getChildrenField(), children);
}
//设置完毕后,将需要排除的字段进行置空
for (String key : treeConfig.getExclude()) {
setTargetValue(targetObject, key, null);
}
//返回结果
return (T) targetObject;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static Object getSourceValue(Object source, String sourceFiled) {
Field field = cacheSourceField.get(sourceFiled);
if (null == field) {
try {
field = sourceClass.getDeclaredField(sourceFiled);
field.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
cacheSourceField.put(sourceFiled, field);
}
return ReflectionUtils.getField(field, source);
}
private static void setTargetValue(Object target, String targetFiled, Object value) {
Field field = cacheTargetField.get(targetFiled);
if (null == field) {
try {
field = targetClass.getDeclaredField(targetFiled);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
field.setAccessible(true);
cacheTargetField.put(targetFiled, field);
}
ReflectionUtils.setField(field, target, value);
}
/**
* 检查list是否为空
*
* @param objects
* @return
*/
private static boolean chickList(List<?> objects) {
return null == objects || objects.isEmpty();
}
/**
* 获取到父级id
*
* @param object
* @return
*/
private static Object getParentId(Object object) {
try {
return getSourceValue(object, treeConfig.getParentField());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,56 @@
package cn.fateverse.common.core.utils.sql;
import cn.fateverse.common.core.exception.CustomException;
import cn.hutool.core.util.StrUtil;
import org.apache.commons.lang3.StringUtils;
/**
* sql操作工具类
*
* @author Clay
* @date 2022/10/30
*/
public class SqlUtil {
/**
* 定义常用的 sql关键字
*/
public static String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ";
/**
* 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
*/
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
/**
* 检查字符,防止注入绕过
*/
public static String escapeOrderBySql(String value) {
if (!StrUtil.isEmpty(value) && !isValidOrderBySql(value)) {
throw new CustomException("参数不符合规范,不能进行查询");
}
return value;
}
/**
* 验证 order by 语法是否符合规范
*/
public static boolean isValidOrderBySql(String value) {
return value.matches(SQL_PATTERN);
}
/**
* SQL关键字检查
*/
public static void filterKeyword(String value) {
if (StrUtil.isEmpty(value)) {
return;
}
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
for (String sqlKeyword : sqlKeywords) {
if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) {
throw new CustomException("参数存在SQL注入风险");
}
}
}
}

View File

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

View File

@@ -0,0 +1 @@
cn.fateverse.common.core.utils.SpringContextHolder