Springboot利用AOP切入注解翻译系统数据库字典、用户、组织名称

场景:

由于服务和业务拆分,在VUE前端有自定的标签:字典标签、用户标签、组织标签,通过先缓存加载所有数据后用自定义标签处理上述业务,但在做AndroidIOS前端对接时,考虑到本地缓存因素,影响获取的数据可能不实时,而频繁调用接口,操作对接很麻烦,所以决定开发一套注解在后端进行翻译

思路:

1、新增修改删除 数据库字典、用户、组织表的接口进行清除redis缓存数据

2、在需要的方法上添加自定义注解–>redis数据获取数据–>不同key切换数据 –>翻译

3、redis无数据–>查询数据–>加入缓存数据以map类型(key -value)存入

实现步骤:

  • 定义数据类型枚举类 FieldTypeEnum
public enum FieldTypeEnum {
    	/**
    	 * 系统全局数据库字典缓存
    	 */
    	SYS_DICT("1"),
    	/**
    	 * 系统全局用户库缓存
    	 */
    	SYS_USER("2"),
    	/**
    	 * 系统全局组织架构缓存
    	 */
    	SYS_ORG("3");

    	private final String key;

    	FieldTypeEnum(String key) {
    		this.key = key;
    	}

    	public String getKey() {
    		return key;
    	}
    	/**
    	 * 根据key动态获取对象
    	 * 
    	 * @param key
    	 * @return
    	 */
    	public static FieldTypeEnum getByKey(String key) {
    		for (FieldTypeEnum type : FieldTypeEnum.values()) {
    			if (String.valueOf(type.getKey()).equals(key)) {
    				return type;
    			}
    		}
    		return null;
    	}

    }复制代码
  • 定义数据类型枚举类 RedisKeyEnum
public enum RedisKeyEnum {
    	/**
    	 * 系统全局数据库字典缓存
    	 */
    	SYS_DICT("redis_sys_dict_application"),
    	/**
    	 * 系统全局用户库缓存
    	 */
    	SYS_USER("redis_sys_user_application"),
    	/**
    	 * 系统全局组织架构缓存
    	 */
    	SYS_ORG("redis_sys_org_application");

    	private String value;

    	RedisKeyEnum(String value) {
    		this.value = value;
    	}

    	public String getValue() {
    		return value;
    	}

    }复制代码
  • 定义单个系统字段注解 SysField
@Target(value={ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysField {
	/**
     * 需要被翻译的归属类型
     * @return
     */
	FieldTypeEnum type();
	/**
     * 指定需要被翻译的字段
     * @return
     */
    String value();
    /**
     * 指定翻译后的字段名 实体类必须定义此字段和getter.setter
     * @return 
     */
    String target();
    /**
     * 字典编码
     * @return
     */
    String dictGroupCode() default "code";
}
复制代码
  • 定义方法上翻译的注解 TranslationSysFiled
/**
 * * 系统翻译,
 * *注意:使用在需要将返回值翻译的方法上
 * 将数据以key -value存入redis
 *  根据系统系统将key翻译成需要的value
 *  如果是数据库字典另外需要指定编码
 * @author Administrator
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.METHOD})
@Documented
public @interface TranslationSysFiled {
	
	SysField[] value();
}复制代码
  • 定义Aspect  切面 TranslationSysFiledAspect
@Aspect
@Component
public class TranslationSysFiledAspect {
	
	@Autowired
	private JedisUtil jedisUtil;
	@Autowired
	private SysUserService sysUserService;
	@Autowired
	private SysOrgService sysOrgService;
	@Autowired
	private SysDictService sysDictService;
	
	@Around("@annotation(translationSysFiled)")
	public Object Translation(ProceedingJoinPoint pjp, TranslationSysFiled translationSysFiled)  throws Throwable{
		Object result = this.doTranslation(pjp,translationSysFiled);
		return result;
	}

	private Object doTranslation(ProceedingJoinPoint pjp, TranslationSysFiled translationSysFiled) throws Throwable {
		Object result = pjp.proceed();
		Class returnType = ((MethodSignature) pjp.getSignature()).getReturnType();
		// 取出要翻译的值
		String returnJsonResult = JSON.toJSONString(result, SerializerFeature.WriteMapNullValue);
		SysField[] sysFields = translationSysFiled.value();
		for (SysField sysField : sysFields) {
			//获取注解上参数
			FieldTypeEnum type = sysField.type();
			String value = sysField.value();
			String target = sysField.target();
			String dictGroupCode = sysField.dictGroupCode();
			
			//根据不同类型  变换 infoMap 值
			Map<String, String> infoMap = this.changeInfoMap(type,dictGroupCode);
			
			Pattern pattern = Pattern.compile("/"" + value + ".*?,");
			Matcher matcher = pattern.matcher(returnJsonResult);
			StringBuffer sb = new StringBuffer();
			while (matcher.find()) {
				Pattern valuePattern = Pattern.compile(":/"(.*?)/",");
				Matcher valueMatcher = valuePattern.matcher(matcher.group().toString());
				if (valueMatcher.find()) {
					// 翻译
					String targetName = infoMap.get(valueMatcher.group(1));
					String s = matcher.group() + "/"" + target + "/":/"" + targetName + "/",";
					matcher.appendReplacement(sb, s);
				} else {
					String s = matcher.group() + "/"" + target + "/":/"/",";
					matcher.appendReplacement(sb, s);
				}
			}
			matcher.appendTail(sb);
			String repaceStr = ",/"" + target + "/":null";
			String repaceStr2 = ",/"" + target + "/":/"/"";
			returnJsonResult = sb.toString().replaceAll(repaceStr, "").replaceAll(repaceStr2, "");
			
		}
		result = AspectUtils.getJsonToResultObject(returnJsonResult, returnType);
		return result;
	}

	private Map<String, String> changeInfoMap(FieldTypeEnum type, String dictGroupCode) {
		Map<String, String> infoMap = new HashMap<String, String>();
		// 从redis获取缓存进行过滤 
		switch (type) { //	FieldTypeEnum.getByKey(type)
		case SYS_DICT: // 数据库字典  FieldTypeEnum.SYS_DICT.getKey()
			infoMap = this.sysDictInfoMap(dictGroupCode);
			break;
		case SYS_USER: // 系统用户 FieldTypeEnum.SYS_USER.getKey()
			infoMap = this.sysUserInfoMap();
			break;
		case SYS_ORG: // 系统组织 FieldTypeEnum.SYS_ORG.getKey()
			infoMap = this.sysOrgInfoMap();
			break;
		default:
			break;
		}
		return infoMap;
	}
	/**
	 * 系统组织 业务数据
	 * @return
	 */
	private Map<String, String> sysOrgInfoMap() {
		//1、从redis获取map
		Map<String, String> infoMap = jedisUtil.getMap(RedisKeyEnum.SYS_ORG.getValue());
		if(ObjectUtils.isEmpty(infoMap)) {
			//2、1没有进行查询
			infoMap = new HashMap<String, String>();
			SysOrgParam params = new SysOrgParam();
			List <SysOrgEntity> orgInfos = sysOrgService.queryAll(params);
			//2、2将查询的数据已key -value 存储到redis
			for (SysOrgEntity orgInfo : orgInfos) {
				infoMap.put(orgInfo.getOrgNo(), orgInfo.getOrgName());
			}
			//jedisUtil.set(RedisKeyEnum.SYS_ORG.getValue(),JSON.toJSONString(infoMap,true));
			jedisUtil.setMap(RedisKeyEnum.SYS_ORG.getValue(), infoMap,3000);
			return infoMap;
		}else {
			return infoMap;
		}
	}
	/**
	 * 系统用户 业务数据
	 * @return
	 */
	private Map<String, String> sysUserInfoMap() {
		// 1、从redis获取map
		Map<String, String> infoMap = jedisUtil.getMap(RedisKeyEnum.SYS_USER.getValue());
		if (ObjectUtils.isEmpty(infoMap)) {
			// 2、1没有进行查询
			infoMap = new HashMap<String, String>();
			Map<String, Object> params = new HashMap<String, Object>();
			List <SysUserEntity> userInfos  = sysUserService.queryAll(params);
			// 2、2将查询的数据已key -value 存储到redis
			for (SysUserEntity userInfo : userInfos) {
				infoMap.put(userInfo.getUserId(), userInfo.getRealName());
			}
			//jedisUtil.set(RedisKeyEnum.SYS_USER.getValue(), JSON.toJSONString(infoMap, true));
			jedisUtil.setMap(RedisKeyEnum.SYS_USER.getValue(), infoMap,3000);
			return infoMap;
		} else {
			return infoMap;
		}
	}
	/**
	 *  数据库字典 业务数据
	 * @param dictGroupCode
	 * @return
	 */
	private Map<String, String> sysDictInfoMap(String dictGroupCode) {
		// 1、从redis获取map
		String redis_dictInfos = jedisUtil.get(RedisKeyEnum.SYS_DICT.getValue());
		List<SysDictEntity> dictInfos = new ArrayList<SysDictEntity>();
		if(StringUtils.isNotBlank(redis_dictInfos)) {
			dictInfos = JSON.parseArray(redis_dictInfos, SysDictEntity.class);
		}else {
			// 2、1没有进行查询
			dictInfos = sysDictService.queryAll(new SysDictParam());
			// 2、2将查询的数据已key -value 存储到redis
			jedisUtil.set(RedisKeyEnum.SYS_DICT.getValue(),JSON.toJSONString(dictInfos,true));
		}
		//将dictInfos进行过滤
		List<SysDictEntity> collect = dictInfos.stream().filter(item-> item.getCode().equals(dictGroupCode)).collect(Collectors.toList());
		// 先把字典值转成map
		Map<String, String> dictInfoMap = new HashMap<String, String>();
		for (SysDictEntity dictInfo : collect) {
			dictInfoMap.put(dictInfo.getValue(), dictInfo.getName());
		}
		return dictInfoMap;
	}
	
	
}复制代码
  • 使用:
  1. 在需要翻译的控制层增加注解, 注意:最好是在控制层,返回的实体数据类型是JSONObject
  2. 在实体类增加目标target 字段

XXX.Controller

@GetMapping("/info/{id}")
    @ApiOperation(value = "根据主键查询详情",responseContainer = "data",response = IwmEnergyIsolationEntity.class)
    @TranslationSysFiled({
    	@SysField(value = "licenseStatus",target = "licenseStatusName",type = Constant.FieldTypeEnum.SYS_DICT,dictGroupCode = "LICENSE_STATUS"),
    	@SysField(value = "applicantUnitOrgNo",target = "applicantUnitOrgNoName",type = Constant.FieldTypeEnum.SYS_ORG),
    	@SysField(value = "startUser",target = "startUserName",type = Constant.FieldTypeEnum.SYS_USER),
    	@SysField(value = "isolationType",target = "isolationTypeName",type = Constant.FieldTypeEnum.SYS_DICT,dictGroupCode = "ISOLATION_TYPE"),
    	@SysField(value = "isolationLevel",target = "isolationLevelName",type = Constant.FieldTypeEnum.SYS_DICT,dictGroupCode = "ISOLATION_LEVEL"),
	})
    public RestResponse info(@PathVariable("id") String id) {
        IwmEnergyIsolationEntity iwmEnergyIsolation = iwmEnergyIsolationService.queryById(id);
        return RestResponse.success().put("isolation", iwmEnergyIsolation);
    }复制代码

IwmEnergyIsolationEntity.java

@Data
@Accessors(chain = true)
public class IwmEnergyIsolationEntity implements Serializable {

      //licenseStatus    //applicantUnitOrgNo    //startUser    //isolationType    //isolationLevel    //省略。。。。
    //用于翻译字段
    @TableField(exist = false)
    private String licenseStatusName;
    @TableField(exist = false)
    private String applicantUnitOrgNoName;
    @TableField(exist = false)
    private String startUserName;
    @TableField(exist = false)
    private String isolationTypeName;
    @TableField(exist = false)
    private String isolationLevelName;
}复制代码

参考文献:

blog.csdn.net/HuanFengZhi…

原文 

https://juejin.im/post/5ea7e7b85188256da0323553

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Springboot利用AOP切入注解翻译系统数据库字典、用户、组织名称

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址