赞
踩
升级后,运行显示项目的时候出现下面错误
2023-08-12 10:57:39.174 [http-nio-8080-exec-3] [1;31mERROR[0;39m [36morg.jeecg.common.aspect.DictAspect:104[0;39m - json解析失败Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: java.util.HashMap["create_time"])
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: java.util.HashMap["create_time"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1300)
at com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer.serialize(UnsupportedTypeSerializer.java:35)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:808)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithoutTypeInfo(MapSerializer.java:764)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:720)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:35)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4568)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3821)
at org.jeecg.common.aspect.DictAspect.parseDictText(DictAspect.java:102)
at org.jeecg.common.aspect.DictAspect.doAround(DictAspect.java:59)
at jdk.internal.reflect.GeneratedMethodAccessor186.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
at org.jeecg.common.aspect.AutoLogAspect.around(AutoLogAspect.java:57)
at jdk.internal.reflect.GeneratedMethodAccessor246.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at com.nbcio.modules.estar.tw.controller.TwProjectController
看上面提示主要应该是下面的问题
at org.jeecg.common.aspect.DictAspect.parseDictText(DictAspect.java:102)
at org.jeecg.common.aspect.DictAspect.doAround(DictAspect.java:59)
原因是没有处理joda-time类型的时间日期,修改WebMvcConfiguration如下:
- 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.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.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;
- import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
- 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;
-
- /**
- * Spring Boot 2.0 解决跨域问题
- *
- * @Author qinfeng
- *
- */
- @Configuration
- public class WebMvcConfiguration implements WebMvcConfigurer {
-
- @Value("${jeecg.path.upload}")
- private String upLoadPath;
- @Value("${jeecg.path.webapp}")
- private String webAppPath;
- @Value("${spring.resource.static-locations}")
- private String staticLocations;
-
- @Autowired(required = false)
- private PrometheusMeterRegistry prometheusMeterRegistry;
-
- /**
- * 静态资源的配置 - 使得可以从磁盘中读取 Html、图片、视频、音频等
- */
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/**")
- //update-begin-author:taoyan date:20211116 for: jeecg.path.webapp配置无效 #3126
- .addResourceLocations("file:" + upLoadPath + "//")
- .addResourceLocations("file:" + webAppPath + "//")
- //update-end-author:taoyan date:20211116 for: jeecg.path.webapp配置无效 #3126
- .addResourceLocations(staticLocations.split(","));
- }
-
- /**
- * 方案一: 默认访问根路径跳转 doc.html页面 (swagger文档页面)
- * 方案二: 访问根路径改成跳转 index.html页面 (简化部署方案: 可以把前端打包直接放到项目的 webapp,上面的配置)
- */
- @Override
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/").setViewName("doc.html");
- }
-
- @Bean
- @Conditional(CorsFilterCondition.class)
- public CorsFilter corsFilter() {
- final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
- final CorsConfiguration corsConfiguration = new CorsConfiguration();
- //是否允许请求带有验证信息
- corsConfiguration.setAllowCredentials(true);
- // 允许访问的客户端域名
- corsConfiguration.addAllowedOriginPattern("*");
- // 允许服务端访问的客户端请求头
- corsConfiguration.addAllowedHeader("*");
- // 允许访问的方法名,GET POST等
- corsConfiguration.addAllowedMethod("*");
- urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
- return new CorsFilter(urlBasedCorsConfigurationSource);
- }
-
- /**
- * 添加Long转json精度丢失的配置,同时改造日期josn解析出错问题
- * @Return: void
- */
- @Override
- public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
- MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(objectMapper());
- converters.add(jackson2HttpMessageConverter);
- }
-
- /**
- * 自定义ObjectMapper
- */
- @Bean
- @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;
- }
-
- /**
- * SpringBootAdmin的Httptrace不见了
- * https://blog.csdn.net/u013810234/article/details/110097201
- */
- @Bean
- public InMemoryHttpTraceRepository getInMemoryHttpTrace(){
- return new InMemoryHttpTraceRepository();
- }
-
- /**
- * 解决springboot2.6
- * 日期时间格式化
- * @return
- */
- /*@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));
- };
- }*/
- /**
- * 解决springboot2.6
- * 解决metrics端点不显示jvm信息的问题(zyf)
- */
- @Bean
- InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor) {
- return () -> meterRegistryPostProcessor.postProcessAfterInitialization(prometheusMeterRegistry, "");
- }
-
- }
parseDictText部分修改如下:
- private void parseDictText(Object result) {
- if (result instanceof Result) {
- if (((Result) result).getResult() instanceof IPage) {
- List<JSONObject> items = new ArrayList<>();
-
- //step.1 筛选出加了 Dict 注解的字段列表
- List<Field> dictFieldList = new ArrayList<>();
- // 字典数据列表, key = 字典code,value=数据列表
- Map<String, List<String>> dataListMap = new HashMap<>();
-
- for (Object record : ((IPage) ((Result) result).getResult()).getRecords()) {
- ObjectMapper mapper = new ObjectMapper();
- String json="{}";
- try {
- //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
- //json = mapper.writeValueAsString(record); //改用objectMapper,解决java8 LocalDateTime JSON解析问题
- json = objectMapper.writeValueAsString(record);
- } catch (JsonProcessingException e) {
- log.error("json解析失败"+e.getMessage(),e);
- }
- JSONObject item = JSONObject.parseObject(json);
- //update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
- //for (Field field : record.getClass().getDeclaredFields()) {
- // 遍历所有字段,把字典Code取出来,放到 map 里
- for (Field field : oConvertUtils.getAllFields(record)) {
- String value = item.getString(field.getName());
- if (oConvertUtils.isEmpty(value)) {
- continue;
- }
- //update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
- if (field.getAnnotation(Dict.class) != null) {
- if (!dictFieldList.contains(field)) {
- dictFieldList.add(field);
- }
- String code = field.getAnnotation(Dict.class).dicCode();
- String text = field.getAnnotation(Dict.class).dicText();
- String table = field.getAnnotation(Dict.class).dictTable();
-
- List<String> dataList;
- String dictCode = code;
- if (!StringUtils.isEmpty(table)) {
- dictCode = String.format("%s,%s,%s", table, text, code);
- }
- dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>());
- this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(",")));
- }
- //date类型默认转换string格式化日期
- if (field.getType().getName().equals("java.util.Date")&&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()))));
- }
- }
- items.add(item);
- }
-
- //step.2 调用翻译方法,一次性翻译
- Map<String, List<DictModel>> translText = this.translateAllDict(dataListMap);
-
- //step.3 将翻译结果填充到返回结果里
- for (JSONObject record : items) {
- for (Field field : dictFieldList) {
- String code = field.getAnnotation(Dict.class).dicCode();
- String text = field.getAnnotation(Dict.class).dicText();
- String table = field.getAnnotation(Dict.class).dictTable();
-
- String fieldDictCode = code;
- if (!StringUtils.isEmpty(table)) {
- fieldDictCode = String.format("%s,%s,%s", table, text, code);
- }
-
- String value = record.getString(field.getName());
- if (oConvertUtils.isNotEmpty(value)) {
- List<DictModel> dictModels = translText.get(fieldDictCode);
- if(dictModels==null || dictModels.size()==0){
- continue;
- }
-
- String textValue = this.translDictText(dictModels, value);
- log.debug(" 字典Val : " + textValue);
- log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + ": " + textValue);
-
- // TODO-sun 测试输出,待删
- log.debug(" ---- dictCode: " + fieldDictCode);
- log.debug(" ---- value: " + value);
- log.debug(" ----- text: " + textValue);
- log.debug(" ---- dictModels: " + JSON.toJSONString(dictModels));
-
- record.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue);
- }
- }
- }
-
- ((IPage) ((Result) result).getResult()).setRecords(items);
- }
-
- }
- }
这样就解决了上面开头标题的问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。