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