Java自定义注解

自定义注解

1. 自定义一个注解类

/**
 * bpm应用业务实例日志注解
 *
 * @author 梁伟浩
 * @since 2023-08-14
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BpmInstanceLog {

	/**
	 * 日志描述
	 *
	 * @return {String}
	 */
	@AliasFor("name")
	String value() default "";

	/**
	 * 日志描述
	 *
	 * @return {String}
	 */
	@AliasFor("value")
	String name() default "";

	/**
	 * 模块分组
	 *
	 * @return {String}
	 */
	String group() default "";

	/**
	 * 操作类型
	 *
	 * @return {OpType}
	 */
	OpType opType() default OpType.QUERY;

	/**
	 * 日志描述
	 *
	 * @return {String}
	 */
	String description() default "";

	/**
	 * 日志Id名称
	 *
	 * @return {String}
	 */
	String dataIdName() default "";

	/**
	 * 业务实例标识
	 *
	 * @return {String}
	 */
	String instId() default "";

	/**
	 * 工作流过程key
	 *
	 * @return {String}
	 */
	String key() default "";

}

2. 编写切面类,获取对应参数

/**
 * bpm instance log注解切面
 *
 * @author 梁伟浩
 */
@Aspect
@Component
public class BpmInstanceLogAnnotationAspect {


    @Around("@annotation(bpmInstanceLog)")
    public Object around(ProceedingJoinPoint point, BpmInstanceLog bpmInstanceLog) throws Throwable {
        HttpServletRequest request = WebUtil.getRequest();
        //发布事件
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("logGroup", bpmInstanceLog.group());
        dataMap.put("logName", StringUtils.isBlank(bpmInstanceLog.name()) ? bpmInstanceLog.value() : bpmInstanceLog.name());
        dataMap.put("opType", bpmInstanceLog.opType().name());
        dataMap.put("description", bpmInstanceLog.description());
        dataMap.put("path", Objects.requireNonNull(request).getRequestURI());
        dataMap.put("opUserIp", ServletUtil.getClientIP(request));
        //从请求中获取标识
        String dataIdName = bpmInstanceLog.dataIdName();
        String dataId = this.getDataId(point, dataIdName).toString();
        if (StringUtils.isNotBlank(dataIdName)) {
            dataMap.put("dataId", dataId);
        }
        String key = bpmInstanceLog.key();
        if (StringUtils.isNotBlank(key)) {
            dataMap.put("key", this.getDataKeyAndInstId(point, key));
        }
        String instId = bpmInstanceLog.instId();
        if (StringUtils.isNotBlank(instId)) {
            Object dataInstId = this.getDataKeyAndInstId(point, instId);
            if (ObjectUtil.isNull(dataInstId)){
                dataInstId = this.getDataId(point, instId);
                 if (ObjectUtil.isNull(dataInstId)){
                     dataInstId = dataId;
                 }
            }
            dataMap.put("instId", dataInstId);
        }
        SpringUtil.publishEvent(new BpmInstanceLogEvent(dataMap));
        return point.proceed();
    }


    /**
     * 获取数据instId,key
     *
     * @param point    ProceedingJoinPoint
     * @param dataName 数据名称
     * @return instId, key
     */
    private Object getDataKeyAndInstId(ProceedingJoinPoint point, String dataName) throws Exception{
        Object[] args = point.getArgs();
        if (args.length == 1) {
            Object value = args[0];
            //转map
            Map<String, Object> argsMap = this.obj2Map(value);
            if (argsMap.containsKey(dataName)) {
                return argsMap.get(dataName);
            }
        }
        return null;
    }

    public Map<String,Object> obj2Map(Object obj) throws Exception{
        Map<String,Object> map=new HashMap<>();
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            String key = property.getName();
            if (key.compareToIgnoreCase("class") == 0) {
                continue;
            }
            Method getter = property.getReadMethod();
            Object value = getter!=null ? getter.invoke(obj) : null;
            map.put(key, value);
        }
        return map;
    }

    /**
     * 获取数据 dataId
     *
     * @param point      ProceedingJoinPoint
     * @param dataIdName 数据id名称
     * @return dataId
     */
    private Object getDataId(ProceedingJoinPoint point, String dataIdName) {
        Object[] args = point.getArgs();
        //比较参数名称,如果是一样则获取该参数值
        String[] names = ((CodeSignature) point.getSignature()).getParameterNames();
        for (int i = 0; i < names.length; i++) {
            if (dataIdName.equals(names[i])) {
                Object dataId = args[i];
                if (dataId != null && isPrimitiveWrapper(dataId.getClass())) {
                    return dataId;
                }
                return null;
            }
        }
        //从对象里获取数据id
        for (Object arg : args) {
            Class clazz = arg.getClass();
            if (!isPrimitiveWrapper(clazz)) {
                if (arg instanceof Map) {
                    Map map = (Map) arg;
                    return map.get(dataIdName);
                } else {
                    try {
                        Field field = clazz.getDeclaredField(dataIdName);
                        field.setAccessible(true);
                        return field.get(arg);
                    } catch (Exception e) {
                    }
                }
            }
        }
        return null;
    }


    /**
     * 是否包装类
     *
     * @param calzz
     * @return
     */
    private boolean isPrimitiveWrapper(Class<?> calzz) {
        return String.class.equals(calzz) || ClassUtil.isPrimitiveWrapper(calzz);
    }

}

3. 编写日监听事件

/**
 * bpm instance 业务实例日志日志事件
 *
 * @author 梁伟浩
 */
public class BpmInstanceLogEvent extends ApplicationEvent {

	public BpmInstanceLogEvent(Map<String, Object> source) {
		super(source);
	}

}

4. 实现监听

/**
 * bpm instance 业务实例日志监听器
 *
 * @author 梁伟浩
 */
@Configuration
public class BpmInstanceLogListener {

    @Resource
    private Environment environment;
    @Resource
    private LogInstanceMapper logInstanceMapper;

    @Async
    @Order
    @Transactional(rollbackFor = Exception.class)
    @EventListener(BpmInstanceLogEvent.class)
    public void saveLog(BpmInstanceLogEvent event) {
        Map<String, Object> source = (Map<String, Object>) event.getSource();
        LogInstance logInstance = BeanUtil.toBean(source, LogInstance.class);
        logInstance.setLogId(String.valueOf(IdUtil.getId()));
        logInstance.setOpUser(String.valueOf(AuthUtil.getUserId()));
        logInstance.setOpDate(DateUtil.date().toTimestamp());
        logInstance.setAppName(environment.getProperty("spring.application.name"));
        logInstanceMapper.insert(logInstance);
    }
}

5. 使用自定义注解@BpmInstanceLog

 @PostMapping("/saveFormData")
 @ApiOperation(value = "表单数据保存", notes = "表单数据保存")
 @ApiOperationSupport(order = 13)
 @BpmInstanceLog(name = "编辑表单", group = MODULE_SOLUTION, dataIdName = "dataId", instId = "instId", key = "key" ,opType = OpType.UPDATE)
    public R<SaveFormDataResponse> saveFormData(@RequestBody BusinessSaveFormRequest formRequest) throws Exception {}

你可能感兴趣的:(java)