mh
6 days ago
11 changed files with 313 additions and 9 deletions
@ -0,0 +1,48 @@ |
|||||||
|
package com.mh.user.annotation; |
||||||
|
|
||||||
|
import java.lang.annotation.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author LJF |
||||||
|
* @version 1.0 |
||||||
|
* @project mh_esi |
||||||
|
* @description 数据字典注解 |
||||||
|
* @date 2024-11-08 11:40:46 |
||||||
|
*/ |
||||||
|
@Target(ElementType.FIELD) |
||||||
|
@Inherited |
||||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||||
|
@Documented |
||||||
|
public @interface FieldParam { |
||||||
|
|
||||||
|
/** |
||||||
|
* 字典值 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
String value() default ""; |
||||||
|
|
||||||
|
/** |
||||||
|
* 字典类型 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
String type() default ""; |
||||||
|
|
||||||
|
/** |
||||||
|
* 字典标签 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
String label() default ""; |
||||||
|
|
||||||
|
/** |
||||||
|
* 要翻译的字段,目标字段翻译的字段+Str |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
String targetField() default ""; |
||||||
|
|
||||||
|
/** |
||||||
|
* 要翻译的字段值类型 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Class targetFieldValueClazz() default String.class; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
package com.mh.user.annotation; |
||||||
|
|
||||||
|
import java.lang.annotation.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author LJF |
||||||
|
* @version 1.0 |
||||||
|
* @project mh_esi |
||||||
|
* @description 需要翻译的字典值 |
||||||
|
* @date 2024-11-08 14:29:39 |
||||||
|
*/ |
||||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||||
|
@Target(ElementType.METHOD) |
||||||
|
@Documented |
||||||
|
public @interface TranslationDict { |
||||||
|
FieldParam[] value(); |
||||||
|
} |
@ -0,0 +1,136 @@ |
|||||||
|
package com.mh.user.aspect; |
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject; |
||||||
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
||||||
|
import com.mh.user.annotation.FieldParam; |
||||||
|
import com.mh.user.annotation.TranslationDict; |
||||||
|
import com.mh.user.model.SysDict; |
||||||
|
import com.mh.user.service.SysDictService; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.aspectj.lang.ProceedingJoinPoint; |
||||||
|
import org.aspectj.lang.annotation.Around; |
||||||
|
import org.aspectj.lang.annotation.Aspect; |
||||||
|
import org.aspectj.lang.reflect.MethodSignature; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
import java.lang.reflect.Method; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author LJF |
||||||
|
* @version 1.0 |
||||||
|
* @project mh_esi |
||||||
|
* @description 数据字典转换 |
||||||
|
* @date 2024-11-08 14:08:20 |
||||||
|
*/ |
||||||
|
@Aspect |
||||||
|
@Component |
||||||
|
@Slf4j |
||||||
|
public class DictDataTranslateAsp { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private SysDictService sysDictService; |
||||||
|
|
||||||
|
@Around("@annotation(com.mh.user.annotation.TranslationDict)") |
||||||
|
public Object aroundMethodTranslate(ProceedingJoinPoint joinPoint) throws Throwable { |
||||||
|
// 接收到请求时间
|
||||||
|
Long startTime = System.currentTimeMillis(); |
||||||
|
// 注意,如果调用joinPoint.proceed()方法,则修改的参数值不会生效,必须调用joinPoint.proceed(args)
|
||||||
|
Object result = joinPoint.proceed(); |
||||||
|
|
||||||
|
// 获取返回值类型
|
||||||
|
Class<?> returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType(); |
||||||
|
|
||||||
|
// 取出要翻译的字典值
|
||||||
|
String returnJsonResult = JSONObject.toJSONString(result); |
||||||
|
|
||||||
|
// 开始解析
|
||||||
|
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); |
||||||
|
|
||||||
|
// 获取注解上参数
|
||||||
|
TranslationDict annotation = method.getAnnotation(TranslationDict.class); |
||||||
|
FieldParam[] fieldParams = annotation.value(); |
||||||
|
|
||||||
|
// 遍历
|
||||||
|
for (FieldParam fieldParam : fieldParams) { |
||||||
|
log.info("字典类型:{},取值字段:{}", fieldParam.type(), fieldParam.targetField()); |
||||||
|
Pattern dictPattern = getPattern(fieldParam); |
||||||
|
Matcher matcher = dictPattern.matcher(returnJsonResult); |
||||||
|
StringBuffer sb = new StringBuffer(); |
||||||
|
// 转义字段
|
||||||
|
this.translateDict(fieldParam, dictPattern, matcher, sb); |
||||||
|
matcher.appendTail(sb); |
||||||
|
returnJsonResult = sb.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
result = JSONObject.parseObject(returnJsonResult, returnType); |
||||||
|
// 如果这里不返回result,则目标对象实际返回值会被置为null
|
||||||
|
// 处理完成时间
|
||||||
|
Long endTime = System.currentTimeMillis(); |
||||||
|
log.info("数据字典转换耗时:{}ms", endTime - startTime); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 字典值转义为中文 |
||||||
|
* |
||||||
|
* @param fieldParam |
||||||
|
* @param fieldPattern |
||||||
|
* @param fieldMatcher |
||||||
|
* @param sb |
||||||
|
*/ |
||||||
|
private void translateDict(FieldParam fieldParam, Pattern fieldPattern, Matcher fieldMatcher, StringBuffer sb) { |
||||||
|
//从缓存中一次性取值
|
||||||
|
List<SysDict> dictNames = sysDictService.findByType(fieldParam.type()); |
||||||
|
while (fieldMatcher.find()) { |
||||||
|
//取出要翻译字段对应的值
|
||||||
|
Matcher dictValueMatcher = fieldPattern.matcher(fieldMatcher.group()); |
||||||
|
dictValueMatcher.find(); |
||||||
|
String group = dictValueMatcher.group(); |
||||||
|
//""sex":1", ""sex":"1"",""sex":null"
|
||||||
|
//属性无值
|
||||||
|
if (group.split(":").length <= 1) continue; |
||||||
|
String dictName = ""; |
||||||
|
//获取字典值
|
||||||
|
String dictValue = group.split(":")[1].replace("\"", ""); |
||||||
|
//属性值非为空 为空赋值空串
|
||||||
|
if (StringUtils.isNotBlank(dictValue) && !dictValue.equalsIgnoreCase("null")) { |
||||||
|
//多值
|
||||||
|
if (dictValue.split(",").length > 1) { |
||||||
|
for (String s : dictValue.split(",")) { |
||||||
|
//fieldParam.dictType() + "_" + s 根据自己字典表设置的规则去查询
|
||||||
|
String type = s; |
||||||
|
Optional<SysDict> first = dictNames.stream().filter(d -> d.getValue().equals(type)).findFirst(); |
||||||
|
if (!first.isPresent()) continue; |
||||||
|
dictName += first.get().getLabel() + "/"; |
||||||
|
} |
||||||
|
} else { |
||||||
|
String type = dictValue; |
||||||
|
Optional<SysDict> first = dictNames.stream().filter(d -> d.getValue().equals(type)).findFirst(); |
||||||
|
if (!first.isPresent()) continue; |
||||||
|
dictName = first.get().getLabel(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
String s = "\"" + fieldParam.targetField() + "Str" + "\":\"" + dictName + "\"," + fieldMatcher.group(); |
||||||
|
log.info("拼接后字符串:{}", s); |
||||||
|
fieldMatcher.appendReplacement(sb, s); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private Pattern getPattern(FieldParam fieldParam) { |
||||||
|
Pattern fieldPattern;//属性整型 字符型
|
||||||
|
if (fieldParam.targetFieldValueClazz().equals(Integer.class)) { |
||||||
|
fieldPattern = Pattern.compile("\"" + fieldParam.targetField() + "\":(\\d+)?"); |
||||||
|
} else { |
||||||
|
fieldPattern = Pattern.compile("\"" + fieldParam.targetField() + "\":\"([0-9a-zA-Z_,]+)?\""); |
||||||
|
} |
||||||
|
return fieldPattern; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
package com.mh.user.config; |
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.*; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.springframework.context.annotation.Bean; |
||||||
|
import org.springframework.context.annotation.Configuration; |
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author LJF |
||||||
|
* @title : |
||||||
|
* @description 使用caffeine缓存技术 |
||||||
|
* @updateTime 2020-12-15 |
||||||
|
* @throws : |
||||||
|
*/ |
||||||
|
@Slf4j |
||||||
|
@Configuration |
||||||
|
public class CaffeineCacheConfig { |
||||||
|
|
||||||
|
// 软引用: 如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。
|
||||||
|
// 弱引用: 弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,
|
||||||
|
// 不管当前内存空间足够与否,都会回收它的内存
|
||||||
|
@Bean(name = "caffeineCache") |
||||||
|
public Cache<String, Object> caffeineCache() { |
||||||
|
return Caffeine.newBuilder() |
||||||
|
// 软引用
|
||||||
|
.softValues() |
||||||
|
// 弱引用
|
||||||
|
// .weakValues()
|
||||||
|
// 设置最后一次写入或访问后经过固定时间过期
|
||||||
|
.expireAfterWrite(8*60*60, TimeUnit.SECONDS) |
||||||
|
// 初始的缓存空间大小
|
||||||
|
.initialCapacity(100) |
||||||
|
// 缓存的最大条数
|
||||||
|
.maximumSize(1000) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
|
||||||
|
//定义缓存,可直接使用
|
||||||
|
@Bean |
||||||
|
public LoadingCache expiryCache(){ |
||||||
|
LoadingCache<String, Object> loadingCache = Caffeine.newBuilder() |
||||||
|
.initialCapacity(100) |
||||||
|
.maximumSize(1000) |
||||||
|
//缓存写入/删除监控
|
||||||
|
.writer(new CacheWriter<Object, Object>() { |
||||||
|
@Override |
||||||
|
public void write(Object key, Object value) { //此方法是同步阻塞的
|
||||||
|
log.info("--缓存写入--:key={}, value={}", key, value); |
||||||
|
} |
||||||
|
@Override |
||||||
|
public void delete(Object key, Object value, RemovalCause cause) { |
||||||
|
log.info("--缓存删除--:key={}", key); } |
||||||
|
}) |
||||||
|
.expireAfterAccess(6, TimeUnit.HOURS) //过期时间
|
||||||
|
.build((String key)->"刷新的数据"); //cacheload实现类,刷新时候调用
|
||||||
|
// loadingCache.put("name","侯征");
|
||||||
|
return loadingCache; |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue