注解代码
package com.ds.admin.v2.common.annotation;
import com.ds.admin.v2.common.enums.Module;
import com.ds.common.enums.BusinessType;
import com.ds.common.utils.uuid.UUID;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义数据变化通知
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MessageNotice {
/**
* 模块
* @see Module#name()
*/
public Module module() default Module.OTHER;
/**
* 功能
* @see BusinessType#name()
*/
public BusinessType businessType() default BusinessType.OTHER;
/**
* uuid
*/
public String uuid() default "";
}
枚举
package com.ds.admin.v2.common.enums;
/**
* 标准各模块定义
*/
public enum Module {
ELEMENT("数据元"),
DIC("值域"),
SBR("主索引"),
STANDARD_MODEL("标化模型"),
BUSINESS_MODEL("业务模型"),
MAPPING("链路映射"),
OTHER("未知");
Module( String info) {
this.info = info;
}
private String info;
public String getInfo() {
return info;
}
}
package com.ds.common.enums;
/**
* 业务操作类型
*
* @author lr-app
*/
public enum BusinessType
{
/**
* 其它
*/
OTHER,
/**
* 新增
*/
INSERT,
/**
* 修改
*/
UPDATE,
/**
* 删除
*/
DELETE,
/**
* 授权
*/
GRANT,
/**
* 导出
*/
EXPORT,
/**
* 导入
*/
IMPORT,
/**
* 强退
*/
FORCE,
/**
* 生成代码
*/
GENCODE,
/**
* 清空数据
*/
CLEAN,
}
切面类
package com.ds.admin.v2.common.aspectj;
import com.ds.admin.v2.common.annotation.MessageNotice;
import com.ds.admin.v2.common.domain.dto.MessageNoticeDto;
import com.ds.admin.v2.utils.MessageNoticeUtil;
import com.ds.common.utils.StringUtils;
import com.ds.common.utils.uuid.IdUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Optional;
/**
* 数据标准改动通知
*/
@Aspect
@Component
@Slf4j
public class MessageNoticeAspect {
@Resource
private KafkaTemplate<String, String> kafkaTemplate;
@Pointcut("@annotation(com.ds.admin.v2.common.annotation.MessageNotice)")
public void noticePointCut() {
log.info("執行發送通知方法");
}
// @Before("noticePointCut()")
// public void doBeforeReturning(JoinPoint joinPoint)
// {
//
// MessageNotice messageNotice = getAnnotationLog(joinPoint);
// System.out.println(messageNotice.module().getInfo());
// }
@Before("execution(public * com.ds.admin.v2.valuedict.service.impl.DataValueColumnServiceImpl.*(..))")
public void doBeforeReturning(JoinPoint joinPoint)
{
MessageNotice messageNotice = getAnnotationLog(joinPoint);
System.out.println(messageNotice.module().getInfo());
}
/**
* 出现异常也执行
*
* @param joinPoint 切点
*/
@After("noticePointCut()")
public void doAfter(JoinPoint joinPoint) {
MessageNotice messageNotice = getAnnotationLog(joinPoint);
System.out.println(messageNotice.module().name());
}
/**
* 处理完请求后执行
* 出现异常不执行
*
* @param joinPoint 切点
*/
// @AfterReturning(pointcut = "noticePointCut()")
// public void doAfterReturning(JoinPoint joinPoint) {
// handleLog(joinPoint);
// }
protected void handleLog(final JoinPoint joinPoint) {
MessageNotice messageNotice = getAnnotationLog(joinPoint);
Optional.ofNullable(messageNotice).ifPresent(f -> send(messageNotice));
}
/**
* 环绕通知:灵活自由的在目标方法中切入代码
*/
@Around("noticePointCut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取目标方法的名称
String methodName = joinPoint.getSignature().getName();
// 获取方法传入参数
Object[] params = joinPoint.getArgs();
// MessageNotice lingyejun = getDeclaredAnnotation(joinPoint);
MessageNotice lingyejun = getAnnotationLog(joinPoint);
System.out.println("==@Around== lingyejun blog logger --》 method name " + methodName + " args " + params[0]);
// 执行源方法
joinPoint.proceed();
// 模拟进行验证
if (params != null && params.length > 0 && params[0].equals("Blog Home")) {
System.out.println("==@Around== lingyejun blog logger --》 " + lingyejun.module() + " auth success");
} else {
System.out.println("==@Around== lingyejun blog logger --》 " + lingyejun.module() + " auth failed");
}
}
/**
* 获取方法中声明的注解
*
* @param joinPoint
* @return
* @throws NoSuchMethodException
*/
public MessageNotice getDeclaredAnnotation(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
// 获取方法名
String methodName = joinPoint.getSignature().getName();
// 反射获取目标类
Class<?> targetClass = joinPoint.getTarget().getClass();
// 拿到方法对应的参数类型
Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
// 根据类、方法、参数类型(重载)获取到方法的具体信息
Method objMethod = targetClass.getMethod(methodName, parameterTypes);
// 拿到方法定义的注解信息
MessageNotice annotation = objMethod.getDeclaredAnnotation(MessageNotice.class);
// 返回
return annotation;
}
/**
* 是否存在注解,如果存在就获取
*/
private MessageNotice getAnnotationLog(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
return method.getAnnotation(MessageNotice.class);
}
return null;
}
/**
* 消息发送
*/
private void send(MessageNotice messageNotice) {
MessageNoticeUtil.getMessage(messageNotice.uuid())
.forEach(f -> {
String topic = StringUtils.isNotBlank(f.getTopic()) ? f.getTopic() : kafkaTemplate.getDefaultTopic();
kafkaTemplate.send(topic,
MessageNoticeDto.builder()
.messageId(IdUtils.fastSimpleUUID())
.module(messageNotice.module().name().toLowerCase())
.businessType(messageNotice.businessType().name().toLowerCase())
.object(f)
.build().toString());
});
MessageNoticeUtil.clear();
}
}
注解使用在方法上
package com.ds.admin.v2.valuedict.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ds.admin.v2.common.annotation.MessageNotice;
import com.ds.admin.v2.common.enums.Module;
import com.ds.admin.v2.sbr.domian.vo.SbrQueryModelColumnAndSort;
import com.ds.admin.v2.sbr.enums.DataValueExportEnums;
import com.ds.admin.v2.utils.MessageNoticeUtil;
import com.ds.admin.v2.utils.MyPageUtil;
import com.ds.admin.v2.valuedict.domain.vo.DictColumnInsertReqVo;
import com.ds.admin.v2.valuedict.domain.vo.DictColumnVo;
import com.ds.admin.v2.valuedict.enums.CodeCatalog;
import com.ds.admin.v2.valuedict.model.DataValue;
import com.ds.admin.v2.valuedict.model.DataValueColumn;
import com.ds.admin.v2.valuedict.mapper.DataValueColumnMapper;
import com.ds.admin.v2.valuedict.service.DataValueColumnService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ds.admin.v2.valuedict.service.DataValueService;
import com.ds.common.enums.BusinessType;
import com.ds.common.exception.CustomException;
import com.ds.common.utils.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 值域字段信息 服务实现类
* </p>
*
* @author standard
* @since 2022-10-12
*/
@Service
public class DataValueColumnServiceImpl extends ServiceImpl<DataValueColumnMapper, DataValueColumn> implements DataValueColumnService {
@Resource
private DataValueService dataValueService;
@Override
public List<DictColumnVo> getColumName(Integer dataValueId) {
LambdaQueryWrapper<DataValueColumn> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DataValueColumn::getDataValueId, dataValueId).orderByAsc(DataValueColumn::getSeqNo);
List<DataValueColumn> dataValueColumns = this.list(queryWrapper);
//是否展示
DataValue dataValue = dataValueService.getById(dataValueId);
String field = DataValueExportEnums.getField(dataValue.getCodeCatalogId());
List<SbrQueryModelColumnAndSort> list = JSON.parseArray(field, SbrQueryModelColumnAndSort.class);
List<DictColumnVo> dictColumnVos = dataValueColumns.stream().map(dvc -> {
DictColumnVo dcv = new DictColumnVo();
BeanUtils.copyProperties(dvc, dcv);
dcv.setShowFlag(false);
for(SbrQueryModelColumnAndSort sort : list){
if (sort.getNameEn().equals(dcv.getNameEn())) {
dcv.setShowFlag(true);
dcv.setNameCn(sort.getNameCn());
if(StringUtils.isNotBlank(sort.getNameEn())){
dcv.setNameEn(sort.getNameEn());
}
}
}
dcv.setColumnId(dvc.getId());
return dcv;
}).collect(Collectors.toList());
return dictColumnVos;
}
@Override
public Page<DictColumnVo> getColumNamePages(Page<DictColumnVo> page, Integer dataValueId) {
List<DictColumnVo> dictColumnVos = this.getColumName(dataValueId);
return MyPageUtil.getMyPage(page, dictColumnVos);
}
@Override
@MessageNotice(module = Module.DIC,businessType = BusinessType.INSERT)
public String addColumnName(DictColumnInsertReqVo dictColumnInsertReqVo) {
DataValue dataValue = dataValueService.getById(dictColumnInsertReqVo.getDataValueId());
// if(dataValue.getCodeCatalogId().equals(CodeCatalog.SINGELVALUECODECATALOG.getId())) throw new CustomException("单值表字段不能修改");
// DataValueColumn dataValueColumn = new DataValueColumn();
// BeanUtils.copyProperties(dictColumnInsertReqVo,dataValueColumn);
// this.save(dataValueColumn);
// MessageNoticeUtil.putMessage(new Object(){}.getClass().getEnclosingMethod(),dataValueColumn);
return "sss";
}
@Override
@MessageNotice(module = Module.DIC,businessType = BusinessType.UPDATE)
public String updateColumnName(DictColumnInsertReqVo dictColumnInsertReqVo) {
DataValue dataValue = dataValueService.getById(dictColumnInsertReqVo.getDataValueId());
// if(dataValue.getCodeCatalogId().equals(CodeCatalog.SINGELVALUECODECATALOG.getId())) throw new CustomException("单值表字段不能修改");
// DataValueColumn dataValueColumn = this.getById(dictColumnInsertReqVo.getId());
// if(dataValueColumn == null) throw new CustomException("值域字段不存在");
// BeanUtils.copyProperties(dictColumnInsertReqVo,dataValueColumn);
// this.updateById(dataValueColumn);
// MessageNoticeUtil.putMessage(new Object(){}.getClass().getEnclosingMethod(),dataValueColumn);
return "sss";
}
@Override
@MessageNotice(module = Module.DIC,businessType = BusinessType.DELETE)
public void deleteColumnName(List<Integer> columnIds) {
List<DataValueColumn> dataValueColumns = this.listByIds(columnIds);
if(StringUtils.isEmpty(dataValueColumns)) throw new CustomException("值域字段不存在");
this.removeByIds(columnIds);
MessageNoticeUtil.putMessage(new Object(){}.getClass().getEnclosingMethod(),dataValueColumns.toArray());
}
}
统一日志处理
package com.ds.admin.v2.common.aspectj;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.ds.admin.v2.common.annotation.MessageNotice;
import com.ds.admin.v2.common.domain.dto.MessageNoticeDto;
import com.ds.admin.v2.utils.MessageNoticeUtil;
import com.ds.common.utils.StringUtils;
import com.ds.common.utils.uuid.IdUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* 统一日志处理切面
* Created by 石磊
*/
@Aspect
@Component
@Order(1)
public class WebLogAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class);
@Pointcut("execution(public * com.ds.admin.v2.valuedict.controller.*.*(..))")
public void webLog() {
}
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
}
@AfterReturning(value = "webLog()", returning = "ret")
public void doAfterReturning(Object ret) throws Throwable {
}
@Around("webLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
//获取当前请求对象
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//记录请求信息(通过Logstash传入Elasticsearch)
WebLog webLog = new WebLog();
Object result = joinPoint.proceed();
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method.isAnnotationPresent(ApiOperation.class)) {
ApiOperation log = method.getAnnotation(ApiOperation.class);
webLog.setDescription(log.value());
}
long endTime = System.currentTimeMillis();
String urlStr = request.getRequestURL().toString();
webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath()));
webLog.setIp(request.getRemoteUser());
Map<String,Object> logMap = new HashMap<>();
logMap.put("spendTime",webLog.getSpendTime());
logMap.put("description",webLog.getDescription());
LOGGER.info("{}", JSONUtil.parse(webLog));
return result;
}
}
package com.ds.admin.v2.common.aspectj;
import lombok.Data;
/**
* Controller层的日志封装类
* Created by macro on 2018/4/26.
*/
@Data
public class WebLog {
private String description;
private String username;
private Long startTime;
private Integer spendTime;
private String basePath;
private String uri;
private String url;
private String method;
private String ip;
private Object parameter;
private Object result;
//省略了getter,setter方法
}