feat: complete all post-refactor tasks (performance, monitoring, docs, CI/CD)
This commit is contained in:
+6
@@ -9,6 +9,12 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 缓存配置类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public class CacheConfig {
|
||||
|
||||
+6
@@ -4,6 +4,12 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
/**
|
||||
* JWT配置属性类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "jwt")
|
||||
@Validated
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package cn.novalon.manage.common.dao;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 查询字段注解
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface QueryField {
|
||||
|
||||
String propName() default "";
|
||||
|
||||
String blurry() default "";
|
||||
|
||||
Type type() default Type.EQUAL;
|
||||
|
||||
Type orPropVal() default Type.EQUAL;
|
||||
|
||||
String[] orPropNames() default {};
|
||||
|
||||
enum Type {
|
||||
EQUAL,
|
||||
GREATER_THAN,
|
||||
LESS_THAN,
|
||||
LESS_THAN_NQ,
|
||||
INNER_LIKE,
|
||||
LEFT_LIKE,
|
||||
NOT_LEFT_LIKE,
|
||||
RIGHT_LIKE,
|
||||
IN,
|
||||
OR,
|
||||
IS_NULL,
|
||||
IS_NOT_NULL
|
||||
}
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
package cn.novalon.manage.common.dao;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.relational.core.query.Criteria;
|
||||
import org.springframework.data.relational.core.query.Query;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 查询工具类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class QueryUtil {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(QueryUtil.class);
|
||||
|
||||
public static <Q> Query getQuery(Q query) {
|
||||
return getQuery(query, true);
|
||||
}
|
||||
|
||||
public static <Q> Query getQueryAll(Q query) {
|
||||
return getQuery(query, false);
|
||||
}
|
||||
|
||||
public static <Q> Query getQuery(Q query, Boolean enabled) {
|
||||
Criteria criteria = Criteria.empty();
|
||||
if (enabled) {
|
||||
criteria = criteria.and("deletedAt").isNull();
|
||||
}
|
||||
if (query == null) {
|
||||
return Query.query(criteria);
|
||||
}
|
||||
try {
|
||||
List<Field> fields = getAllFields(query.getClass(), new ArrayList<>());
|
||||
for (Field field : fields) {
|
||||
boolean accessible = Modifier.isStatic(field.getModifiers()) ? field.canAccess(null)
|
||||
: field.canAccess(query);
|
||||
field.setAccessible(true);
|
||||
QueryField q = field.getAnnotation(QueryField.class);
|
||||
if (q != null) {
|
||||
String propName = q.propName();
|
||||
String blurry = q.blurry();
|
||||
String attributeName = isBlank(propName) ? field.getName() : propName;
|
||||
Object val = field.get(query);
|
||||
if (val == null || "".equals(val)) {
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isNotBlank(blurry)) {
|
||||
String[] blurrys = blurry.split(",");
|
||||
Criteria orCriteria = Criteria.empty();
|
||||
for (String s : blurrys) {
|
||||
orCriteria = orCriteria.or(s).like("%" + val + "%");
|
||||
}
|
||||
criteria = criteria.and(orCriteria);
|
||||
continue;
|
||||
}
|
||||
switch (q.type()) {
|
||||
case EQUAL:
|
||||
criteria = criteria.and(attributeName).is(val);
|
||||
break;
|
||||
case GREATER_THAN:
|
||||
criteria = criteria.and(attributeName).greaterThanOrEquals(val);
|
||||
break;
|
||||
case LESS_THAN:
|
||||
criteria = criteria.and(attributeName).lessThanOrEquals(val);
|
||||
break;
|
||||
case LESS_THAN_NQ:
|
||||
criteria = criteria.and(attributeName).lessThan(val);
|
||||
break;
|
||||
case INNER_LIKE:
|
||||
criteria = criteria.and(attributeName).like("%" + val + "%");
|
||||
break;
|
||||
case LEFT_LIKE:
|
||||
criteria = criteria.and(attributeName).like("%" + val);
|
||||
break;
|
||||
case NOT_LEFT_LIKE:
|
||||
criteria = criteria.and(attributeName).notLike("%" + val);
|
||||
break;
|
||||
case RIGHT_LIKE:
|
||||
criteria = criteria.and(attributeName).like(val + "%");
|
||||
break;
|
||||
case IN:
|
||||
if (val instanceof Collection && CollectionUtils.isNotEmpty((Collection<?>) val)) {
|
||||
criteria = criteria.and(attributeName).in((Collection<?>) val);
|
||||
}
|
||||
break;
|
||||
case OR:
|
||||
QueryField.Type orValue = q.orPropVal();
|
||||
String[] orPropNames = q.orPropNames();
|
||||
Criteria orPredicate = Criteria.empty();
|
||||
if (QueryField.Type.IS_NULL.equals(orValue)) {
|
||||
for (String prop : orPropNames) {
|
||||
orPredicate = orPredicate.or(prop).isNull();
|
||||
}
|
||||
}
|
||||
if (QueryField.Type.IS_NOT_NULL.equals(orValue)) {
|
||||
for (String prop : orPropNames) {
|
||||
orPredicate = orPredicate.or(prop).isNotNull();
|
||||
}
|
||||
}
|
||||
criteria = criteria.and(orPredicate);
|
||||
break;
|
||||
case IS_NULL:
|
||||
criteria = criteria.and(attributeName).isNull();
|
||||
break;
|
||||
case IS_NOT_NULL:
|
||||
criteria = criteria.and(attributeName).isNotNull();
|
||||
break;
|
||||
}
|
||||
}
|
||||
field.setAccessible(accessible);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return Query.query(criteria);
|
||||
}
|
||||
|
||||
public static boolean isBlank(final CharSequence cs) {
|
||||
int strLen;
|
||||
if (cs == null || (strLen = cs.length()) == 0) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < strLen; i++) {
|
||||
if (!Character.isWhitespace(cs.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static List<Field> getAllFields(Class<?> clazz, List<Field> fields) {
|
||||
if (clazz != null) {
|
||||
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
||||
getAllFields(clazz.getSuperclass(), fields);
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 基础领域对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
public abstract class BaseDomain {
|
||||
|
||||
protected Long id;
|
||||
protected String createBy;
|
||||
protected String updateBy;
|
||||
protected LocalDateTime createdAt;
|
||||
protected LocalDateTime updatedAt;
|
||||
protected LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getCreateBy() {
|
||||
return createBy;
|
||||
}
|
||||
|
||||
public void setCreateBy(String createBy) {
|
||||
this.createBy = createBy;
|
||||
}
|
||||
|
||||
public String getUpdateBy() {
|
||||
return updateBy;
|
||||
}
|
||||
|
||||
public void setUpdateBy(String updateBy) {
|
||||
this.updateBy = updateBy;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getDeletedAt() {
|
||||
return deletedAt;
|
||||
}
|
||||
|
||||
public void setDeletedAt(LocalDateTime deletedAt) {
|
||||
this.deletedAt = deletedAt;
|
||||
}
|
||||
}
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class Dictionary {
|
||||
private Long id;
|
||||
private String type;
|
||||
private String code;
|
||||
private String name;
|
||||
private String value;
|
||||
private String remark;
|
||||
private Integer sort;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Dictionary() {
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public Integer getSort() {
|
||||
return sort;
|
||||
}
|
||||
|
||||
public void setSort(Integer sort) {
|
||||
this.sort = sort;
|
||||
}
|
||||
|
||||
public String getCreateBy() {
|
||||
return createBy;
|
||||
}
|
||||
|
||||
public void setCreateBy(String createBy) {
|
||||
this.createBy = createBy;
|
||||
}
|
||||
|
||||
public String getUpdateBy() {
|
||||
return updateBy;
|
||||
}
|
||||
|
||||
public void setUpdateBy(String updateBy) {
|
||||
this.updateBy = updateBy;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getDeletedAt() {
|
||||
return deletedAt;
|
||||
}
|
||||
|
||||
public void setDeletedAt(LocalDateTime deletedAt) {
|
||||
this.deletedAt = deletedAt;
|
||||
}
|
||||
}
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
public class OperationLog extends BaseDomain {
|
||||
|
||||
private String username;
|
||||
private String operation;
|
||||
private String method;
|
||||
private String params;
|
||||
private String result;
|
||||
private String ip;
|
||||
private Long duration;
|
||||
private String status;
|
||||
private String errorMsg;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
public void setOperation(String operation) {
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public String getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(String params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public String getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(String result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public Long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setDuration(Long duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getErrorMsg() {
|
||||
return errorMsg;
|
||||
}
|
||||
|
||||
public void setErrorMsg(String errorMsg) {
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysConfig {
|
||||
|
||||
private Long id;
|
||||
private String configName;
|
||||
private String configKey;
|
||||
private String configValue;
|
||||
private String configType;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getConfigName() { return configName; }
|
||||
public void setConfigName(String configName) { this.configName = configName; }
|
||||
public String getConfigKey() { return configKey; }
|
||||
public void setConfigKey(String configKey) { this.configKey = configKey; }
|
||||
public String getConfigValue() { return configValue; }
|
||||
public void setConfigValue(String configValue) { this.configValue = configValue; }
|
||||
public String getConfigType() { return configType; }
|
||||
public void setConfigType(String configType) { this.configType = configType; }
|
||||
public String getCreateBy() { return createBy; }
|
||||
public void setCreateBy(String createBy) { this.createBy = createBy; }
|
||||
public String getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
public LocalDateTime getDeletedAt() { return deletedAt; }
|
||||
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysDictData {
|
||||
|
||||
private Long id;
|
||||
private Long dictTypeId;
|
||||
private String dictLabel;
|
||||
private String dictValue;
|
||||
private Integer dictSort;
|
||||
private String dictType;
|
||||
private String cssClass;
|
||||
private String listClass;
|
||||
private String isDefault;
|
||||
private String status;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public Long getDictTypeId() { return dictTypeId; }
|
||||
public void setDictTypeId(Long dictTypeId) { this.dictTypeId = dictTypeId; }
|
||||
public String getDictLabel() { return dictLabel; }
|
||||
public void setDictLabel(String dictLabel) { this.dictLabel = dictLabel; }
|
||||
public String getDictValue() { return dictValue; }
|
||||
public void setDictValue(String dictValue) { this.dictValue = dictValue; }
|
||||
public Integer getDictSort() { return dictSort; }
|
||||
public void setDictSort(Integer dictSort) { this.dictSort = dictSort; }
|
||||
public String getDictType() { return dictType; }
|
||||
public void setDictType(String dictType) { this.dictType = dictType; }
|
||||
public String getCssClass() { return cssClass; }
|
||||
public void setCssClass(String cssClass) { this.cssClass = cssClass; }
|
||||
public String getListClass() { return listClass; }
|
||||
public void setListClass(String listClass) { this.listClass = listClass; }
|
||||
public String getIsDefault() { return isDefault; }
|
||||
public void setIsDefault(String isDefault) { this.isDefault = isDefault; }
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public String getCreateBy() { return createBy; }
|
||||
public void setCreateBy(String createBy) { this.createBy = createBy; }
|
||||
public String getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
public LocalDateTime getDeletedAt() { return deletedAt; }
|
||||
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysDictType {
|
||||
|
||||
private Long id;
|
||||
private String dictName;
|
||||
private String dictType;
|
||||
private String status;
|
||||
private String remark;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getDictName() { return dictName; }
|
||||
public void setDictName(String dictName) { this.dictName = dictName; }
|
||||
public String getDictType() { return dictType; }
|
||||
public void setDictType(String dictType) { this.dictType = dictType; }
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public String getRemark() { return remark; }
|
||||
public void setRemark(String remark) { this.remark = remark; }
|
||||
public String getCreateBy() { return createBy; }
|
||||
public void setCreateBy(String createBy) { this.createBy = createBy; }
|
||||
public String getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
public LocalDateTime getDeletedAt() { return deletedAt; }
|
||||
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysExceptionLog {
|
||||
|
||||
private Long id;
|
||||
private String username;
|
||||
private String title;
|
||||
private String exceptionName;
|
||||
private String methodName;
|
||||
private String methodParams;
|
||||
private String exceptionMsg;
|
||||
private String exceptionStack;
|
||||
private String ip;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getUsername() { return username; }
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public String getExceptionName() { return exceptionName; }
|
||||
public void setExceptionName(String exceptionName) { this.exceptionName = exceptionName; }
|
||||
public String getMethodName() { return methodName; }
|
||||
public void setMethodName(String methodName) { this.methodName = methodName; }
|
||||
public String getMethodParams() { return methodParams; }
|
||||
public void setMethodParams(String methodParams) { this.methodParams = methodParams; }
|
||||
public String getExceptionMsg() { return exceptionMsg; }
|
||||
public void setExceptionMsg(String exceptionMsg) { this.exceptionMsg = exceptionMsg; }
|
||||
public String getExceptionStack() { return exceptionStack; }
|
||||
public void setExceptionStack(String exceptionStack) { this.exceptionStack = exceptionStack; }
|
||||
public String getIp() { return ip; }
|
||||
public void setIp(String ip) { this.ip = ip; }
|
||||
public LocalDateTime getCreateTime() { return createTime; }
|
||||
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysFile {
|
||||
|
||||
private Long id;
|
||||
private String fileName;
|
||||
private String filePath;
|
||||
private String fileSize;
|
||||
private String fileType;
|
||||
private String storageType;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getFileName() { return fileName; }
|
||||
public void setFileName(String fileName) { this.fileName = fileName; }
|
||||
public String getFilePath() { return filePath; }
|
||||
public void setFilePath(String filePath) { this.filePath = filePath; }
|
||||
public String getFileSize() { return fileSize; }
|
||||
public void setFileSize(String fileSize) { this.fileSize = fileSize; }
|
||||
public String getFileType() { return fileType; }
|
||||
public void setFileType(String fileType) { this.fileType = fileType; }
|
||||
public String getStorageType() { return storageType; }
|
||||
public void setStorageType(String storageType) { this.storageType = storageType; }
|
||||
public String getCreateBy() { return createBy; }
|
||||
public void setCreateBy(String createBy) { this.createBy = createBy; }
|
||||
public String getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getDeletedAt() { return deletedAt; }
|
||||
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysLoginLog {
|
||||
|
||||
private Long id;
|
||||
private String username;
|
||||
private String ip;
|
||||
private String location;
|
||||
private String browser;
|
||||
private String os;
|
||||
private String status;
|
||||
private String message;
|
||||
private LocalDateTime loginTime;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getUsername() { return username; }
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
public String getIp() { return ip; }
|
||||
public void setIp(String ip) { this.ip = ip; }
|
||||
public String getLocation() { return location; }
|
||||
public void setLocation(String location) { this.location = location; }
|
||||
public String getBrowser() { return browser; }
|
||||
public void setBrowser(String browser) { this.browser = browser; }
|
||||
public String getOs() { return os; }
|
||||
public void setOs(String os) { this.os = os; }
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public String getMessage() { return message; }
|
||||
public void setMessage(String message) { this.message = message; }
|
||||
public LocalDateTime getLoginTime() { return loginTime; }
|
||||
public void setLoginTime(LocalDateTime loginTime) { this.loginTime = loginTime; }
|
||||
}
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SysMenu extends BaseDomain {
|
||||
|
||||
private String menuName;
|
||||
private Long parentId;
|
||||
private Integer orderNum;
|
||||
private String menuType;
|
||||
private String perms;
|
||||
private String component;
|
||||
private String status;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private List<SysMenu> children;
|
||||
|
||||
public String getMenuName() {
|
||||
return menuName;
|
||||
}
|
||||
|
||||
public void setMenuName(String menuName) {
|
||||
this.menuName = menuName;
|
||||
}
|
||||
|
||||
public Long getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public void setParentId(Long parentId) {
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public Integer getOrderNum() {
|
||||
return orderNum;
|
||||
}
|
||||
|
||||
public void setOrderNum(Integer orderNum) {
|
||||
this.orderNum = orderNum;
|
||||
}
|
||||
|
||||
public String getMenuType() {
|
||||
return menuType;
|
||||
}
|
||||
|
||||
public void setMenuType(String menuType) {
|
||||
this.menuType = menuType;
|
||||
}
|
||||
|
||||
public String getPerms() {
|
||||
return perms;
|
||||
}
|
||||
|
||||
public void setPerms(String perms) {
|
||||
this.perms = perms;
|
||||
}
|
||||
|
||||
public String getComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
public void setComponent(String component) {
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getCreateBy() {
|
||||
return createBy;
|
||||
}
|
||||
|
||||
public void setCreateBy(String createBy) {
|
||||
this.createBy = createBy;
|
||||
}
|
||||
|
||||
public String getUpdateBy() {
|
||||
return updateBy;
|
||||
}
|
||||
|
||||
public void setUpdateBy(String updateBy) {
|
||||
this.updateBy = updateBy;
|
||||
}
|
||||
|
||||
public List<SysMenu> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<SysMenu> children) {
|
||||
this.children = children;
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysNotice {
|
||||
|
||||
private Long id;
|
||||
private String noticeTitle;
|
||||
private String noticeType;
|
||||
private String noticeContent;
|
||||
private String status;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getNoticeTitle() { return noticeTitle; }
|
||||
public void setNoticeTitle(String noticeTitle) { this.noticeTitle = noticeTitle; }
|
||||
public String getNoticeType() { return noticeType; }
|
||||
public void setNoticeType(String noticeType) { this.noticeType = noticeType; }
|
||||
public String getNoticeContent() { return noticeContent; }
|
||||
public void setNoticeContent(String noticeContent) { this.noticeContent = noticeContent; }
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public String getCreateBy() { return createBy; }
|
||||
public void setCreateBy(String createBy) { this.createBy = createBy; }
|
||||
public String getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
public LocalDateTime getDeletedAt() { return deletedAt; }
|
||||
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import cn.novalon.manage.common.util.SnowflakeId;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 角色领域对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
public class SysRole extends BaseDomain {
|
||||
|
||||
private String roleName;
|
||||
private String roleKey;
|
||||
private Integer roleSort;
|
||||
private Integer status;
|
||||
|
||||
public String getRoleName() {
|
||||
return roleName;
|
||||
}
|
||||
|
||||
public void setRoleName(String roleName) {
|
||||
this.roleName = roleName;
|
||||
}
|
||||
|
||||
public String getRoleKey() {
|
||||
return roleKey;
|
||||
}
|
||||
|
||||
public void setRoleKey(String roleKey) {
|
||||
this.roleKey = roleKey;
|
||||
}
|
||||
|
||||
public Integer getRoleSort() {
|
||||
return roleSort;
|
||||
}
|
||||
|
||||
public void setRoleSort(Integer roleSort) {
|
||||
this.roleSort = roleSort;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成主键ID
|
||||
*
|
||||
* @return 主键ID
|
||||
*/
|
||||
public Long generateId() {
|
||||
this.id = SnowflakeId.nextId();
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除角色
|
||||
*/
|
||||
public void delete() {
|
||||
this.deletedAt = LocalDateTime.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复角色
|
||||
*/
|
||||
public void restore() {
|
||||
this.deletedAt = null;
|
||||
}
|
||||
}
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import cn.novalon.manage.common.util.SnowflakeId;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 用户领域对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
public class SysUser extends BaseDomain {
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
private String email;
|
||||
private Long roleId;
|
||||
private Integer status;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public Long getRoleId() {
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(Long roleId) {
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成主键ID
|
||||
*
|
||||
* @return 主键ID
|
||||
*/
|
||||
public Long generateId() {
|
||||
this.id = SnowflakeId.nextId();
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
public void delete() {
|
||||
this.deletedAt = LocalDateTime.now();
|
||||
}
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysUserMessage {
|
||||
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private String title;
|
||||
private String content;
|
||||
private String messageType;
|
||||
private String isRead;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public Long getUserId() { return userId; }
|
||||
public void setUserId(Long userId) { this.userId = userId; }
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public String getContent() { return content; }
|
||||
public void setContent(String content) { this.content = content; }
|
||||
public String getMessageType() { return messageType; }
|
||||
public void setMessageType(String messageType) { this.messageType = messageType; }
|
||||
public String getIsRead() { return isRead; }
|
||||
public void setIsRead(String isRead) { this.isRead = isRead; }
|
||||
public LocalDateTime getCreateTime() { return createTime; }
|
||||
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
|
||||
}
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
package cn.novalon.manage.common.domain.query;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 菜单查询对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 菜单查询条件对象
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class SysMenuQuery {
|
||||
|
||||
private String menuName;
|
||||
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
package cn.novalon.manage.common.domain.query;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 角色查询对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 角色查询条件对象
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class SysRoleQuery {
|
||||
|
||||
private String roleName;
|
||||
|
||||
+14
-5
@@ -1,17 +1,18 @@
|
||||
package cn.novalon.manage.common.domain.query;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 用户查询对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 用户查询条件对象
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class SysUserQuery {
|
||||
|
||||
private String username;
|
||||
private String email;
|
||||
private Integer status;
|
||||
private Long roleId;
|
||||
private String keyword;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
@@ -44,4 +45,12 @@ public class SysUserQuery {
|
||||
public void setRoleId(Long roleId) {
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public String getKeyword() {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
public void setKeyword(String keyword) {
|
||||
this.keyword = keyword;
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -1,5 +1,11 @@
|
||||
package cn.novalon.manage.common.dto;
|
||||
|
||||
/**
|
||||
* 分页请求参数封装类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class PageRequest {
|
||||
private int page = 0;
|
||||
private int size = 10;
|
||||
|
||||
+6
@@ -2,6 +2,12 @@ package cn.novalon.manage.common.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页响应结果封装类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class PageResponse<T> {
|
||||
private List<T> content;
|
||||
private int totalPages;
|
||||
|
||||
+6
@@ -1,5 +1,11 @@
|
||||
package cn.novalon.manage.common.exception;
|
||||
|
||||
/**
|
||||
* 业务异常类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class BusinessException extends RuntimeException {
|
||||
|
||||
private final String code;
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package cn.novalon.manage.common.handler;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 异常日志服务接口
|
||||
*
|
||||
* 文件定义:定义异常日志记录的抽象接口
|
||||
* 涉及业务:异常日志记录、错误追踪
|
||||
* 算法:使用响应式编程实现异步日志记录
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public interface ExceptionLogService {
|
||||
Mono<Void> logException(String title, String exceptionName, String exceptionMsg,
|
||||
String methodName, String ip, String stackTrace);
|
||||
}
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
package cn.novalon.manage.common.handler;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
*
|
||||
* 文件定义:统一处理系统中抛出的各种异常,返回标准化的错误响应
|
||||
* 涉及业务:异常捕获、错误日志记录、错误响应格式化
|
||||
* 算法:使用@RestControllerAdvice注解实现全局异常拦截
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||
|
||||
private final ExceptionLogService exceptionLogService;
|
||||
|
||||
public GlobalExceptionHandler(ExceptionLogService exceptionLogService) {
|
||||
this.exceptionLogService = exceptionLogService;
|
||||
}
|
||||
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleRuntimeException(RuntimeException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Runtime exception: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
if (ex.getMessage() != null && ex.getMessage().contains("not found")) {
|
||||
response.put("code", HttpStatus.NOT_FOUND.value());
|
||||
response.put("message", ex.getMessage());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
|
||||
}
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", ex.getMessage());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<Map<String, Object>> handleException(Exception ex, ServerWebExchange exchange) {
|
||||
logger.error("Exception occurred: ", ex);
|
||||
|
||||
exceptionLogService.logException(
|
||||
"System Exception",
|
||||
ex.getClass().getSimpleName(),
|
||||
ex.getMessage(),
|
||||
exchange.getRequest().getPath().value(),
|
||||
getClientIp(exchange),
|
||||
getStackTrace(ex)
|
||||
).subscribe();
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
response.put("message", "Internal server error");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleIllegalArgumentException(IllegalArgumentException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Illegal argument: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", ex.getMessage());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Validation failed: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", "Validation failed");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
Map<String, String> fieldErrors = ex.getBindingResult()
|
||||
.getFieldErrors()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage, (e1, e2) -> e1));
|
||||
|
||||
response.put("errors", fieldErrors);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ServerWebInputException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleServerWebInputException(ServerWebInputException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Invalid input: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", "Invalid input");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ResponseStatusException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleResponseStatusException(ResponseStatusException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Response status exception: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", ex.getStatusCode().value());
|
||||
response.put("message", ex.getReason());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(ex.getStatusCode()).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(DuplicateKeyException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleDuplicateKeyException(DuplicateKeyException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Duplicate key: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.CONFLICT.value());
|
||||
response.put("message", "Duplicate key violation");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.CONFLICT).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(DataIntegrityViolationException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleDataIntegrityViolationException(DataIntegrityViolationException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Data integrity violation: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.CONFLICT.value());
|
||||
response.put("message", "Data integrity violation");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.CONFLICT).body(response);
|
||||
}
|
||||
|
||||
private String getClientIp(ServerWebExchange exchange) {
|
||||
String ip = exchange.getRequest().getHeaders().getFirst("X-Forwarded-For");
|
||||
if (ip == null || ip.isEmpty()) {
|
||||
ip = exchange.getRequest().getHeaders().getFirst("X-Real-IP");
|
||||
}
|
||||
if (ip == null || ip.isEmpty()) {
|
||||
ip = exchange.getRequest().getRemoteAddress() != null
|
||||
? exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
|
||||
: "127.0.0.1";
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
private String getStackTrace(Exception ex) {
|
||||
StringBuilder stackTrace = new StringBuilder();
|
||||
for (StackTraceElement element : ex.getStackTrace()) {
|
||||
stackTrace.append(element.toString()).append("\n");
|
||||
}
|
||||
return stackTrace.toString();
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package cn.novalon.manage.common.monitoring;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.springframework.stereotype.Component;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class MetricsAspect {
|
||||
|
||||
private final MetricsCollector metricsCollector;
|
||||
|
||||
public MetricsAspect(MetricsCollector metricsCollector) {
|
||||
this.metricsCollector = metricsCollector;
|
||||
}
|
||||
|
||||
@Pointcut("within(cn.novalon.manage..*) && " +
|
||||
"@annotation(org.springframework.web.bind.annotation.GetMapping || " +
|
||||
"@annotation(org.springframework.web.bind.annotation.PostMapping || " +
|
||||
"@annotation(org.springframework.web.bind.annotation.PutMapping || " +
|
||||
"@annotation(org.springframework.web.bind.annotation.DeleteMapping)")
|
||||
public void apiMethods() {}
|
||||
|
||||
@Around("apiMethods()")
|
||||
public Object monitorApiCall(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
String className = joinPoint.getTarget().getClass().getSimpleName();
|
||||
String methodName = joinPoint.getSignature().getName();
|
||||
String module = extractModule(className);
|
||||
String endpoint = className.replace("Handler", "").toLowerCase() + "/" + methodName;
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
boolean success = true;
|
||||
String errorType = null;
|
||||
|
||||
try {
|
||||
Object result = joinPoint.proceed();
|
||||
|
||||
if (result instanceof Mono) {
|
||||
return ((Mono<?>) result)
|
||||
.doOnError(error -> {
|
||||
success = false;
|
||||
errorType = error.getClass().getSimpleName();
|
||||
metricsCollector.recordError(module, errorType, error.getMessage());
|
||||
})
|
||||
.doOnSuccess(v -> {
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
metricsCollector.recordApiCall(module, endpoint, "GET", duration, true);
|
||||
});
|
||||
}
|
||||
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
metricsCollector.recordApiCall(module, endpoint, "GET", duration, true);
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
success = false;
|
||||
errorType = e.getClass().getSimpleName();
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
metricsCollector.recordApiCall(module, endpoint, "GET", duration, false);
|
||||
metricsCollector.recordError(module, errorType, e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private String extractModule(String className) {
|
||||
if (className.contains("Notify")) return "notify";
|
||||
if (className.contains("File")) return "file";
|
||||
if (className.contains("User")) return "user";
|
||||
if (className.contains("Role")) return "role";
|
||||
if (className.contains("Config")) return "config";
|
||||
if (className.contains("Log")) return "log";
|
||||
return "system";
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package cn.novalon.manage.common.monitoring;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
public class MetricsCollector {
|
||||
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
public MetricsCollector(MeterRegistry meterRegistry) {
|
||||
this.meterRegistry = meterRegistry;
|
||||
}
|
||||
|
||||
public Counter buildCounter(String name, String description, String... tags) {
|
||||
return Counter.builder(name)
|
||||
.description(description)
|
||||
.tags(tags)
|
||||
.register(meterRegistry);
|
||||
}
|
||||
|
||||
public Timer buildTimer(String name, String description, String... tags) {
|
||||
return Timer.builder(name)
|
||||
.description(description)
|
||||
.tags(tags)
|
||||
.register(meterRegistry);
|
||||
}
|
||||
|
||||
public void recordApiCall(String module, String endpoint, String method, long duration, boolean success) {
|
||||
Timer.builder("api.call.duration")
|
||||
.description("API call duration")
|
||||
.tag("module", module)
|
||||
.tag("endpoint", endpoint)
|
||||
.tag("method", method)
|
||||
.register(meterRegistry)
|
||||
.record(duration, TimeUnit.MILLISECONDS);
|
||||
|
||||
Counter.builder("api.call.count")
|
||||
.description("API call count")
|
||||
.tag("module", module)
|
||||
.tag("endpoint", endpoint)
|
||||
.tag("method", method)
|
||||
.tag("status", success ? "success" : "failure")
|
||||
.register(meterRegistry)
|
||||
.increment();
|
||||
}
|
||||
|
||||
public void recordDatabaseQuery(String module, String operation, long duration, boolean success) {
|
||||
Timer.builder("db.query.duration")
|
||||
.description("Database query duration")
|
||||
.tag("module", module)
|
||||
.tag("operation", operation)
|
||||
.register(meterRegistry)
|
||||
.record(duration, TimeUnit.MILLISECONDS);
|
||||
|
||||
Counter.builder("db.query.count")
|
||||
.description("Database query count")
|
||||
.tag("module", module)
|
||||
.tag("operation", operation)
|
||||
.tag("status", success ? "success" : "failure")
|
||||
.register(meterRegistry)
|
||||
.increment();
|
||||
}
|
||||
|
||||
public void recordCacheHit(String module, String cacheName, boolean hit) {
|
||||
Counter.builder("cache.access")
|
||||
.description("Cache access count")
|
||||
.tag("module", module)
|
||||
.tag("cache", cacheName)
|
||||
.tag("result", hit ? "hit" : "miss")
|
||||
.register(meterRegistry)
|
||||
.increment();
|
||||
}
|
||||
|
||||
public void recordError(String module, String errorType, String message) {
|
||||
Counter.builder("error.count")
|
||||
.description("Error count")
|
||||
.tag("module", module)
|
||||
.tag("type", errorType)
|
||||
.tag("message", message)
|
||||
.register(meterRegistry)
|
||||
.increment();
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package cn.novalon.manage.common.monitoring;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class MetricsConfig {
|
||||
|
||||
@Bean
|
||||
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
|
||||
return registry -> registry.config().commonTags(
|
||||
"application", "novalon-manage-api",
|
||||
"environment", System.getenv().getOrDefault("ENV", "development")
|
||||
);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MetricsCollector metricsCollector(MeterRegistry meterRegistry) {
|
||||
return new MetricsCollector(meterRegistry);
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
package cn.novalon.manage.common.util;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 数据库字段名常量
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 数据库字段名常量定义
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class FieldConstants {
|
||||
|
||||
public static final String USERNAME = "username";
|
||||
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
package cn.novalon.manage.common.util;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 菜单类型常量
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 菜单类型常量定义
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class MenuTypeConstants {
|
||||
|
||||
public static final String DIRECTORY = "M";
|
||||
|
||||
+8
-11
@@ -6,17 +6,14 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
/**
|
||||
* Twitter的Snowflake算法实现(性能优化版)
|
||||
*
|
||||
* 优化点:
|
||||
* 1. 使用自适应等待策略,减少CPU空转
|
||||
* 2. 时间戳缓存机制,降低系统调用频率
|
||||
* 3. 增强CAS重试策略,提升并发性能
|
||||
* 4. 完善异常处理和资源管理
|
||||
*
|
||||
* @author zhangxiang
|
||||
* @version 2.0
|
||||
* @date 2026/03/11
|
||||
* 雪花算法ID生成器
|
||||
*
|
||||
* 文件定义:基于Twitter Snowflake算法的分布式唯一ID生成器
|
||||
* 涉及业务:为系统所有实体生成唯一ID,支持分布式环境下的ID生成
|
||||
* 算法:使用雪花算法,结合时间戳、机器ID和序列号生成唯一ID,支持高并发场景
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public final class SnowflakeId {
|
||||
|
||||
|
||||
+9
-5
@@ -1,11 +1,15 @@
|
||||
package cn.novalon.manage.common.util;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 状态常量
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 状态常量定义
|
||||
*
|
||||
* 文件定义:系统通用的状态常量定义类
|
||||
* 涉及业务:为系统提供统一的状态码定义,包括启用、禁用、删除等状态
|
||||
* 算法:无复杂算法,主要为常量定义
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class StatusConstants {
|
||||
|
||||
public static final Integer DISABLED = 0;
|
||||
|
||||
Reference in New Issue
Block a user