字典拦截器性能优化(无@dict注解不走拦截器)

issues/I561IU 3.2版本,跑测试用例代码抛出异常
处理报错: Table 'jeecg-boot.user_tab_cols' doesn't exist
pull/3805/head
zhangdaiscott 2022-06-13 13:11:57 +08:00
parent 9e774a457c
commit 1b5616282e
4 changed files with 265 additions and 220 deletions

View File

@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
@ -25,7 +24,6 @@ import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@ -46,6 +44,11 @@ public class DictAspect {
@Autowired
public RedisTemplate redisTemplate;
@Autowired
private ObjectMapper objectMapper;
private static final String JAVA_UTIL_DATE = "java.util.Date";
/**
* Pointcut
*/
@ -60,7 +63,7 @@ public class DictAspect {
long time2=System.currentTimeMillis();
log.debug("获取JSON数据 耗时:"+(time2-time1)+"ms");
long start=System.currentTimeMillis();
this.parseDictText(result);
result=this.parseDictText(result);
long end=System.currentTimeMillis();
log.debug("注入字典到JSON数据 耗时"+(end-start)+"ms");
return result;
@ -88,7 +91,7 @@ public class DictAspect {
* vuetable
* @param result
*/
private void parseDictText(Object result) {
private Object parseDictText(Object result) {
if (result instanceof Result) {
if (((Result) result).getResult() instanceof IPage) {
List<JSONObject> items = new ArrayList<>();
@ -97,13 +100,23 @@ public class DictAspect {
List<Field> dictFieldList = new ArrayList<>();
// 字典数据列表, key = 字典codevalue=数据列表
Map<String, List<String>> dataListMap = new HashMap<>(5);
//取出结果集
List<Object> records=((IPage) ((Result) result).getResult()).getRecords();
//update-begin--Author:zyf -- Date:20220606 ----for【VUEN-1230】 判断是否含有字典注解,没有注解返回-----
Boolean hasDict= checkHasDict(records);
if(!hasDict){
return result;
}
for (Object record : ((IPage) ((Result) result).getResult()).getRecords()) {
ObjectMapper mapper = new ObjectMapper();
log.info(" __ 进入字典翻译切面 DictAspect —— " );
//update-end--Author:zyf -- Date:20220606 ----for【VUEN-1230】 判断是否含有字典注解,没有注解返回-----
for (Object record : records) {
String json="{}";
try {
//update-begin--Author:zyf -- Date:20220531 ----for【issues/#3629】 DictAspect Jackson序列化报错-----
//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
json = mapper.writeValueAsString(record);
json = objectMapper.writeValueAsString(record);
//update-end--Author:zyf -- Date:20220531 ----for【issues/#3629】 DictAspect Jackson序列化报错-----
} catch (JsonProcessingException e) {
log.error("json解析失败"+e.getMessage(),e);
}
@ -137,10 +150,12 @@ public class DictAspect {
this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(",")));
}
//date类型默认转换string格式化日期
if (CommonConstant.JAVA_UTIL_DATE.equals(field.getType().getName())&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){
SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
}
//update-begin--Author:zyf -- Date:20220531 ----for【issues/#3629】 DictAspect Jackson序列化报错-----
//if (JAVA_UTIL_DATE.equals(field.getType().getName())&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){
//SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
//}
//update-end--Author:zyf -- Date:20220531 ----for【issues/#3629】 DictAspect Jackson序列化报错-----
}
items.add(item);
}
@ -186,6 +201,7 @@ public class DictAspect {
}
}
return result;
}
/**
@ -394,4 +410,20 @@ public class DictAspect {
return textValue.toString();
}
/**
* Dict
* @param records
* @return
*/
private Boolean checkHasDict(List<Object> records){
if(oConvertUtils.isNotEmpty(records) && records.size()>0){
for (Field field : oConvertUtils.getAllFields(records.get(0))) {
if (oConvertUtils.isNotEmpty(field.getAnnotation(Dict.class))) {
return true;
}
}
}
return false;
}
}

View File

@ -1,19 +1,25 @@
package org.jeecg.config;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.actuate.trace.http.InMemoryHttpTraceRepository;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.cors.CorsConfiguration;
@ -22,7 +28,11 @@ import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
@ -42,6 +52,9 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
@Value("${spring.resource.static-locations}")
private String staticLocations;
@Autowired(required = false)
private PrometheusMeterRegistry prometheusMeterRegistry;
/**
* - 使 Html
*/
@ -80,37 +93,38 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
/**
* Longjson
* @Return: void
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(objectMapper());
converters.add(jackson2HttpMessageConverter);
}
/**
* springboot2.6
*
* @return
* ObjectMapper
*/
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//返回时间数据序列化
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
//接收时间数据反序列化
builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
};
@Primary
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
//处理bigDecimal
objectMapper.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
objectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
//处理失败
objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES, false);
//默认的处理日期时间格式
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
/**
@ -124,12 +138,11 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
/**
* springboot2.6
* metricsjvm(zyf)
*/
@Bean
InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, PrometheusMeterRegistry registry) {
return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, "");
InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor) {
return () -> meterRegistryPostProcessor.postProcessAfterInitialization(prometheusMeterRegistry, "");
}
}

View File

@ -1,179 +1,179 @@
//package org.jeecg.modules.system.test;
//
//import org.jeecg.JeecgSystemApplication;
//import org.jeecg.common.constant.CommonConstant;
//import org.jeecg.common.system.util.JwtUtil;
//import org.jeecg.common.util.RedisUtil;
//import org.jeecg.common.util.RestUtil;
//import org.junit.Test;
//import org.junit.runner.RunWith;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.test.context.SpringBootTest;
//import org.springframework.test.context.ActiveProfiles;
//import org.springframework.test.context.junit4.SpringRunner;
//import org.springframework.http.HttpHeaders;
//import org.springframework.http.HttpMethod;
//import org.springframework.http.MediaType;
//import com.alibaba.fastjson.JSONObject;
//import org.springframework.http.ResponseEntity;
//
///**
// * 系统用户单元测试
// */
//@RunWith(SpringRunner.class)
//@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,classes = JeecgSystemApplication.class)
//@SuppressWarnings({"FieldCanBeLocal", "SpringJavaAutowiredMembersInspection"})
//public class SysUserTest {
// /**
// * 测试地址:实际使用时替换成你自己的地址
// */
// private final String BASE_URL = "http://localhost:8080/jeecg-boot/sys/user/";
// //测试:用户名和密码
// private final String USERNAME = "admin";
// private final String PASSWORD = "123456";
// @Autowired
// private RedisUtil redisUtil;
//
// /**
// * 测试用例:查询记录
// */
// @Test
// public void testQuery() {
// // 请求地址
// String url = BASE_URL + "list";
// // 请求 Header 用于传递Token
// HttpHeaders headers = this.getHeaders();
// // 请求方式是 GET 代表获取数据
// HttpMethod method = HttpMethod.GET;
//
// System.out.println("请求地址:" + url);
// System.out.println("请求方式:" + method);
//
// // 利用 RestUtil 请求该url
// ResponseEntity<JSONObject> result = RestUtil.request(url, method, headers, null, null, JSONObject.class);
// if (result != null && result.getBody() != null) {
// System.out.println("返回结果:" + result.getBody().toJSONString());
// } else {
// System.out.println("查询失败");
// }
// }
//
// /**
// * 测试用例:新增
// */
// @Test
// public void testAdd() {
// // 请求地址
// String url = BASE_URL + "add" ;
// // 请求 Header 用于传递Token
// HttpHeaders headers = this.getHeaders();
// // 请求方式是 POST 代表提交新增数据
// HttpMethod method = HttpMethod.POST;
//
// System.out.println("请求地址:" + url);
// System.out.println("请求方式:" + method);
//
// JSONObject params = new JSONObject();
// params.put("username", "wangwuTest");
// params.put("password", "123456");
// params.put("confirmpassword","123456");
// params.put("realname", "单元测试");
// params.put("activitiSync", "1");
// params.put("userIdentity","1");
// params.put("workNo","0025");
//
// System.out.println("请求参数:" + params.toJSONString());
//
// // 利用 RestUtil 请求该url
// ResponseEntity<JSONObject> result = RestUtil.request(url, method, headers, null, params, JSONObject.class);
// if (result != null && result.getBody() != null) {
// System.out.println("返回结果:" + result.getBody().toJSONString());
// } else {
// System.out.println("查询失败");
// }
// }
//
//
// /**
// * 测试用例:修改
// */
// @Test
// public void testEdit() {
// // 数据Id
// String dataId = "1331795062924374018";
// // 请求地址
// String url = BASE_URL + "edit";
// // 请求 Header 用于传递Token
// HttpHeaders headers = this.getHeaders();
// // 请求方式是 PUT 代表提交修改数据
// HttpMethod method = HttpMethod.PUT;
//
// System.out.println("请求地址:" + url);
// System.out.println("请求方式:" + method);
//
// JSONObject params = new JSONObject();
// params.put("username", "wangwuTest");
// params.put("realname", "单元测试1111");
// params.put("activitiSync", "1");
// params.put("userIdentity","1");
// params.put("workNo","0025");
// params.put("id",dataId);
//
// System.out.println("请求参数:" + params.toJSONString());
//
// // 利用 RestUtil 请求该url
// ResponseEntity<JSONObject> result = RestUtil.request(url, method, headers, null, params, JSONObject.class);
// if (result != null && result.getBody() != null) {
// System.out.println("返回结果:" + result.getBody().toJSONString());
// } else {
// System.out.println("查询失败");
// }
// }
//
//
// /**
// * 测试用例:删除
// */
// @Test
// public void testDelete() {
// // 数据Id
// String dataId = "1331795062924374018";
// // 请求地址
// String url = BASE_URL + "delete" + "?id=" + dataId;
// // 请求 Header 用于传递Token
// HttpHeaders headers = this.getHeaders();
// // 请求方式是 DELETE 代表删除数据
// HttpMethod method = HttpMethod.DELETE;
//
// System.out.println("请求地址:" + url);
// System.out.println("请求方式:" + method);
//
// // 利用 RestUtil 请求该url
// ResponseEntity<JSONObject> result = RestUtil.request(url, method, headers, null, null, JSONObject.class);
// if (result != null && result.getBody() != null) {
// System.out.println("返回结果:" + result.getBody().toJSONString());
// } else {
// System.out.println("查询失败");
// }
// }
//
//
// private String getToken() {
// String token = JwtUtil.sign(USERNAME, PASSWORD);
// redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
// redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, 60);
// return token;
// }
//
// private HttpHeaders getHeaders() {
// String token = this.getToken();
// System.out.println("请求Token" + token);
//
// HttpHeaders headers = new HttpHeaders();
// String mediaType = MediaType.APPLICATION_JSON_VALUE;
// headers.setContentType(MediaType.parseMediaType(mediaType));
// headers.set("Accept", mediaType);
// headers.set("X-Access-Token", token);
// return headers;
// }
//}
package org.jeecg.modules.system.test;
import org.jeecg.JeecgSystemApplication;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.RestUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.ResponseEntity;
/**
*
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,classes = JeecgSystemApplication.class)
@SuppressWarnings({"FieldCanBeLocal", "SpringJavaAutowiredMembersInspection"})
public class SysUserTest {
/**
* 使
*/
private final String BASE_URL = "http://localhost:8080/jeecg-boot/sys/user/";
//测试:用户名和密码
private final String USERNAME = "admin";
private final String PASSWORD = "123456";
@Autowired
private RedisUtil redisUtil;
/**
*
*/
@Test
public void testQuery() {
// 请求地址
String url = BASE_URL + "list";
// 请求 Header 用于传递Token
HttpHeaders headers = this.getHeaders();
// 请求方式是 GET 代表获取数据
HttpMethod method = HttpMethod.GET;
System.out.println("请求地址:" + url);
System.out.println("请求方式:" + method);
// 利用 RestUtil 请求该url
ResponseEntity<JSONObject> result = RestUtil.request(url, method, headers, null, null, JSONObject.class);
if (result != null && result.getBody() != null) {
System.out.println("返回结果:" + result.getBody().toJSONString());
} else {
System.out.println("查询失败");
}
}
/**
*
*/
@Test
public void testAdd() {
// 请求地址
String url = BASE_URL + "add" ;
// 请求 Header 用于传递Token
HttpHeaders headers = this.getHeaders();
// 请求方式是 POST 代表提交新增数据
HttpMethod method = HttpMethod.POST;
System.out.println("请求地址:" + url);
System.out.println("请求方式:" + method);
JSONObject params = new JSONObject();
params.put("username", "wangwuTest");
params.put("password", "123456");
params.put("confirmpassword","123456");
params.put("realname", "单元测试");
params.put("activitiSync", "1");
params.put("userIdentity","1");
params.put("workNo","0025");
System.out.println("请求参数:" + params.toJSONString());
// 利用 RestUtil 请求该url
ResponseEntity<JSONObject> result = RestUtil.request(url, method, headers, null, params, JSONObject.class);
if (result != null && result.getBody() != null) {
System.out.println("返回结果:" + result.getBody().toJSONString());
} else {
System.out.println("查询失败");
}
}
/**
*
*/
@Test
public void testEdit() {
// 数据Id
String dataId = "1331795062924374018";
// 请求地址
String url = BASE_URL + "edit";
// 请求 Header 用于传递Token
HttpHeaders headers = this.getHeaders();
// 请求方式是 PUT 代表提交修改数据
HttpMethod method = HttpMethod.PUT;
System.out.println("请求地址:" + url);
System.out.println("请求方式:" + method);
JSONObject params = new JSONObject();
params.put("username", "wangwuTest");
params.put("realname", "单元测试1111");
params.put("activitiSync", "1");
params.put("userIdentity","1");
params.put("workNo","0025");
params.put("id",dataId);
System.out.println("请求参数:" + params.toJSONString());
// 利用 RestUtil 请求该url
ResponseEntity<JSONObject> result = RestUtil.request(url, method, headers, null, params, JSONObject.class);
if (result != null && result.getBody() != null) {
System.out.println("返回结果:" + result.getBody().toJSONString());
} else {
System.out.println("查询失败");
}
}
/**
*
*/
@Test
public void testDelete() {
// 数据Id
String dataId = "1331795062924374018";
// 请求地址
String url = BASE_URL + "delete" + "?id=" + dataId;
// 请求 Header 用于传递Token
HttpHeaders headers = this.getHeaders();
// 请求方式是 DELETE 代表删除数据
HttpMethod method = HttpMethod.DELETE;
System.out.println("请求地址:" + url);
System.out.println("请求方式:" + method);
// 利用 RestUtil 请求该url
ResponseEntity<JSONObject> result = RestUtil.request(url, method, headers, null, null, JSONObject.class);
if (result != null && result.getBody() != null) {
System.out.println("返回结果:" + result.getBody().toJSONString());
} else {
System.out.println("查询失败");
}
}
private String getToken() {
String token = JwtUtil.sign(USERNAME, PASSWORD);
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, 60);
return token;
}
private HttpHeaders getHeaders() {
String token = this.getToken();
System.out.println("请求Token" + token);
HttpHeaders headers = new HttpHeaders();
String mediaType = MediaType.APPLICATION_JSON_VALUE;
headers.setContentType(MediaType.parseMediaType(mediaType));
headers.set("Accept", mediaType);
headers.set("X-Access-Token", token);
return headers;
}
}

View File

@ -50,7 +50,7 @@
<shiro.version>1.8.0</shiro.version>
<java-jwt.version>3.11.0</java-jwt.version>
<shiro-redis.version>3.1.0</shiro-redis.version>
<codegenerate.version>1.3.8</codegenerate.version>
<codegenerate.version>1.3.9</codegenerate.version>
<autopoi-web.version>1.4.0</autopoi-web.version>
<minio.version>8.0.3</minio.version>
<justauth-spring-boot-starter.version>1.3.4</justauth-spring-boot-starter.version>