From eadc4f749a2452ab2c3705bcaf75fca32ee41a2d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 24 Jan 2021 12:15:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E5=B8=A6=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E9=87=8C=E6=89=80=E6=9C=89=20fastjson=20=E7=9A=84=E5=86=85?= =?UTF-8?q?=E5=AE=B9=EF=BC=8C=E7=BB=9F=E4=B8=80=E4=BD=BF=E7=94=A8=20jackso?= =?UTF-8?q?n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 不考虑使用 gson 的原因,是基本停止了维护 --- pom.xml | 41 --------------- ruoyi-ui/src/utils/request.js | 7 +-- .../dashboard/common/pojo/CommonResult.java | 3 -- .../operatelog/core/aop/OperateLogAspect.java | 6 +-- .../core/type/JacksonLongSetTypeHandler.java | 45 +++++++++++++++++ .../framework/redis/config/RedisConfig.java | 3 +- .../redis/core/pubsub/ChannelMessage.java | 4 +- .../framework/security/core/LoginUser.java | 16 +++--- .../web/config/WebConfiguration.java | 50 ------------------- .../dataobject/logger/SysOperateLogDO.java | 6 +-- .../dataobject/permission/SysRoleDO.java | 4 +- .../dal/mysql/dataobject/user/SysUserDO.java | 4 +- .../redis/dao/auth/SysLoginUserRedisDAO.java | 6 +-- .../redis/dao/common/SysCaptchaRedisDAO.java | 3 -- .../dashboard/util/json/JSONUtils.java | 30 +++++++++-- .../dashboard/util/servlet/ServletUtils.java | 4 +- src/main/resources/application.yaml | 5 ++ 17 files changed, 106 insertions(+), 131 deletions(-) create mode 100644 src/main/java/cn/iocoder/dashboard/framework/mybatis/core/type/JacksonLongSetTypeHandler.java diff --git a/pom.xml b/pom.xml index b04f82bd9..39f97ab43 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,6 @@ - @@ -55,7 +54,6 @@ 1.16.14 1.4.1.Final 0.9.1 - 1.2.75 5.5.6 2.2.7 @@ -64,32 +62,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -211,25 +183,12 @@ ${jjwt.version} - - com.alibaba - fastjson - ${fastjson.version} - - org.projectlombok lombok ${lombok.version} - - - eu.bitwalker - UserAgentUtils - 1.21 - - org.mapstruct mapstruct diff --git a/ruoyi-ui/src/utils/request.js b/ruoyi-ui/src/utils/request.js index b9404d162..759f03433 100644 --- a/ruoyi-ui/src/utils/request.js +++ b/ruoyi-ui/src/utils/request.js @@ -61,9 +61,10 @@ service.interceptors.response.use(res => { } ).then(() => { store.dispatch('LogOut').then(() => { - if (location.pathname !== '/login') { // 避免重复跳转 - location.href = '/index'; - } + // if (location.pathname !== '/login') { // 避免重复跳转 + // + // } + location.href = '/index'; }) }) } else if (code === 500) { diff --git a/src/main/java/cn/iocoder/dashboard/common/pojo/CommonResult.java b/src/main/java/cn/iocoder/dashboard/common/pojo/CommonResult.java index 80b938dfb..14e34070d 100644 --- a/src/main/java/cn/iocoder/dashboard/common/pojo/CommonResult.java +++ b/src/main/java/cn/iocoder/dashboard/common/pojo/CommonResult.java @@ -4,7 +4,6 @@ import cn.iocoder.dashboard.common.exception.ErrorCode; import cn.iocoder.dashboard.common.exception.GlobalException; import cn.iocoder.dashboard.common.exception.ServiceException; import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants; -import com.alibaba.fastjson.annotation.JSONField; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import org.springframework.util.Assert; @@ -69,13 +68,11 @@ public final class CommonResult implements Serializable { return result; } - @JSONField(serialize = false) // 避免 fastjson 序列化 @JsonIgnore // 避免 jackson 序列化 public boolean isSuccess() { return GlobalErrorCodeConstants.SUCCESS.getCode().equals(code); } - @JSONField(serialize = false) // 避免 fastjson 序列化 @JsonIgnore // 避免 jackson 序列化 public boolean isError() { return !isSuccess(); diff --git a/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java b/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java index 6465b3112..8f5dba063 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java +++ b/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java @@ -11,8 +11,8 @@ import cn.iocoder.dashboard.framework.logger.operatelog.core.service.OperateLogF import cn.iocoder.dashboard.framework.security.core.util.SecurityUtils; import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogCreateReqVO; +import cn.iocoder.dashboard.util.json.JSONUtils; import cn.iocoder.dashboard.util.servlet.ServletUtils; -import com.alibaba.fastjson.JSON; import com.google.common.collect.Maps; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -319,7 +319,7 @@ public class OperateLogAspect { // 被忽略时,标记为 ignore 字符串,避免和 null 混在一起 args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]"); } - return JSON.toJSONString(args); + return JSONUtils.toJSONString(args); } private static String obtainResultData(Object result) { @@ -327,7 +327,7 @@ public class OperateLogAspect { if (result instanceof CommonResult) { result = ((CommonResult) result).getData(); } - return JSON.toJSONString(result); + return JSONUtils.toJSONString(result); } private static boolean isIgnoreArgs(Object object) { diff --git a/src/main/java/cn/iocoder/dashboard/framework/mybatis/core/type/JacksonLongSetTypeHandler.java b/src/main/java/cn/iocoder/dashboard/framework/mybatis/core/type/JacksonLongSetTypeHandler.java new file mode 100644 index 000000000..d95ed3800 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/mybatis/core/type/JacksonLongSetTypeHandler.java @@ -0,0 +1,45 @@ +package cn.iocoder.dashboard.framework.mybatis.core.type; + +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; +import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.util.Set; + +/** + * 参考 {@link com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler} 实现 + * 在我们将字符串反序列化为 Set 并且泛型为 Long 时,如果每个元素的数值太小,会被处理成 Integer 类型,导致可能存在隐性的 BUG。 + * + * 例如说哦,{@link SysUserDO#getPostIds()} 属性 + * + * @author 芋道源码 + */ +public class JacksonLongSetTypeHandler extends AbstractJsonTypeHandler { + + // TODO 芋艿,需要将 Spring 的设置下进来 + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private static final TypeReference> typeReference = new TypeReference>(){}; + + @Override + protected Object parse(String json) { + try { + return objectMapper.readValue(json, typeReference); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + protected String toJson(Object obj) { + try { + return objectMapper.writeValueAsString(obj); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/framework/redis/config/RedisConfig.java b/src/main/java/cn/iocoder/dashboard/framework/redis/config/RedisConfig.java index 0a00e3a45..4bf993014 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/redis/config/RedisConfig.java +++ b/src/main/java/cn/iocoder/dashboard/framework/redis/config/RedisConfig.java @@ -1,7 +1,6 @@ package cn.iocoder.dashboard.framework.redis.config; import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener; -import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -29,7 +28,7 @@ public class RedisConfig { // 使用 String 序列化方式,序列化 KEY 。 template.setKeySerializer(RedisSerializer.string()); // 使用 JSON 序列化方式(库是 FastJSON ),序列化 VALUE 。 - template.setValueSerializer(new GenericFastJsonRedisSerializer()); + template.setValueSerializer(RedisSerializer.json()); return template; } diff --git a/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/ChannelMessage.java b/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/ChannelMessage.java index 7df444750..645ae1336 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/ChannelMessage.java +++ b/src/main/java/cn/iocoder/dashboard/framework/redis/core/pubsub/ChannelMessage.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.framework.redis.core.pubsub; -import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; /** * Redis Channel Message 接口 @@ -12,7 +12,7 @@ public interface ChannelMessage { * * @return Channel */ - @JSONField(serialize = false) // 必须序列化 + @JsonIgnore // 必须序列化 String getChannel(); } diff --git a/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java b/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java index d8b060469..9ba5cf43d 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java +++ b/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.framework.security.core; import cn.iocoder.dashboard.common.enums.CommonStatusEnum; -import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; @@ -49,43 +49,43 @@ public class LoginUser implements UserDetails { private Integer status; @Override - @JSONField(serialize = false) // 避免序列化 + @JsonIgnore// 避免序列化 public String getPassword() { return password; } @Override - @JSONField(serialize = false) // 避免序列化 + @JsonIgnore public String getUsername() { return username; } @Override - @JSONField(serialize = false) // 避免序列化 + @JsonIgnore// 避免序列化 public boolean isEnabled() { return CommonStatusEnum.ENABLE.getStatus().equals(status); } @Override - @JSONField(serialize = false) // 避免序列化 + @JsonIgnore// 避免序列化 public Collection getAuthorities() { return null; } @Override - @JSONField(serialize = false) // 避免序列化 + @JsonIgnore// 避免序列化 public boolean isAccountNonExpired() { return true; // 返回 true,不依赖 Spring Security 判断 } @Override - @JSONField(serialize = false) // 避免序列化 + @JsonIgnore// 避免序列化 public boolean isAccountNonLocked() { return true; // 返回 true,不依赖 Spring Security 判断 } @Override - @JSONField(serialize = false) // 避免序列化 + @JsonIgnore// 避免序列化 public boolean isCredentialsNonExpired() { return true; // 返回 true,不依赖 Spring Security 判断 } diff --git a/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java b/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java index 2f15cfe8d..46fc878da 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java +++ b/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java @@ -1,15 +1,9 @@ package cn.iocoder.dashboard.framework.web.config; -import cn.iocoder.dashboard.util.servlet.ServletUtils; -import com.alibaba.fastjson.serializer.SerializerFeature; -import com.alibaba.fastjson.support.config.FastJsonConfig; -import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; -import org.springframework.http.MediaType; -import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; @@ -18,10 +12,6 @@ import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import java.nio.charset.Charset; -import java.util.Collections; -import java.util.List; /** * Web 配置类 @@ -40,46 +30,6 @@ public class WebConfiguration implements WebMvcConfigurer { && clazz.getPackage().getName().startsWith(webProperties.getControllerPackage())); } - // ========== MessageConverter 相关 ========== - - @Override - public void configureMessageConverters(List> converters) { - // 创建 FastJsonHttpMessageConverter 对象 - // 重写 canRead 和 canWrite 方法,判断只处理自己写的 API 为前缀的 URL。原因是,FastJSON 和一些三方框架集成存在问题,例如说: - // 1. 与 Spring Boot Admin 时,由于 Registration 基于 Builder 构造对象,导致它无法反序列化 - // 2. 与 Spring Boot Actuator 时,貌似也存在问题,具体还没去排查。 - // 但是,为什么不替换回 Jackson 呢? - // 原因是,一些 Number 数值比较小时,反序列化回来是 Integer 类型,实际是 Long 类型。此时,在序列化时,会报 Integer 无法转换成 Long 的异常 - FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter() { - - @Override - protected boolean canRead(MediaType mediaType) { - return isApiPrefix() && super.canRead(mediaType); - } - - @Override - protected boolean canWrite(MediaType mediaType) { - return isApiPrefix() && super.canWrite(mediaType); - } - - private boolean isApiPrefix() { - HttpServletRequest request = ServletUtils.getRequest(); - return request != null && request.getRequestURI().startsWith(webProperties.getApiPrefix()); - } - - }; - // 自定义 FastJson 配置 - FastJsonConfig fastJsonConfig = new FastJsonConfig(); - fastJsonConfig.setCharset(Charset.defaultCharset()); // 设置字符集 - fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect, // 剔除循环引用 - SerializerFeature.WriteNonStringKeyAsString); // 解决 Integer 作为 Key 时,转换为 String 类型,避免浏览器报错 - fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig); - // 设置支持的 MediaType - fastJsonHttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON)); - // 添加到 converters 中 - converters.add(0, fastJsonHttpMessageConverter); // 注意,添加到最开头,放在 MappingJackson2XmlHttpMessageConverter 前面 - } - // ========== Filter 相关 ========== /** diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java index 14a0654d3..9005e592c 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java @@ -1,13 +1,13 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger; import cn.iocoder.dashboard.common.pojo.CommonResult; +import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum; import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; -import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.Data; import lombok.EqualsAndHashCode; @@ -75,7 +75,7 @@ public class SysOperateLogDO extends BaseDO { * 拓展字段,有些复杂的业务,需要记录一些字段 * 例如说,记录订单编号,则可以添加 key 为 "orderId",value 为订单编号 */ - @TableField(typeHandler = FastjsonTypeHandler.class) + @TableField(typeHandler = JacksonTypeHandler.class) private Map exts; /** diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/permission/SysRoleDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/permission/SysRoleDO.java index 4354813dd..18bc788cf 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/permission/SysRoleDO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/permission/SysRoleDO.java @@ -2,13 +2,13 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission; import cn.iocoder.dashboard.common.enums.CommonStatusEnum; import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.dashboard.framework.mybatis.core.type.JacksonLongSetTypeHandler; import cn.iocoder.dashboard.framework.security.core.enums.DataScopeEnum; import cn.iocoder.dashboard.modules.system.enums.permission.RoleCodeEnum; import cn.iocoder.dashboard.modules.system.enums.permission.SysRoleTypeEnum; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler; import lombok.Data; import lombok.EqualsAndHashCode; @@ -71,7 +71,7 @@ public class SysRoleDO extends BaseDO { * * 适用于 {@link #dataScope} 的值为 {@link DataScopeEnum#DEPT_CUSTOM} 时 */ - @TableField(typeHandler = FastjsonTypeHandler.class) + @TableField(typeHandler = JacksonLongSetTypeHandler.class) private Set dataScopeDeptIds; } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/user/SysUserDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/user/SysUserDO.java index d95b49c3f..29a056010 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/user/SysUserDO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/user/SysUserDO.java @@ -2,11 +2,11 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user; import cn.iocoder.dashboard.common.enums.CommonStatusEnum; import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.dashboard.framework.mybatis.core.type.JacksonLongSetTypeHandler; import cn.iocoder.dashboard.modules.system.enums.common.SysSexEnum; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler; import lombok.Data; import lombok.EqualsAndHashCode; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -54,7 +54,7 @@ public class SysUserDO extends BaseDO { /** * 岗位编号数组 */ - @TableField(typeHandler = FastjsonTypeHandler.class) + @TableField(typeHandler = JacksonLongSetTypeHandler.class) private Set postIds; /** * 用户邮箱 diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/dao/auth/SysLoginUserRedisDAO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/dao/auth/SysLoginUserRedisDAO.java index c76807178..0bb954c43 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/dao/auth/SysLoginUserRedisDAO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/dao/auth/SysLoginUserRedisDAO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.dal.redis.dao.auth; import cn.iocoder.dashboard.framework.security.core.LoginUser; -import com.alibaba.fastjson.JSON; +import cn.iocoder.dashboard.util.json.JSONUtils; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Repository; @@ -22,12 +22,12 @@ public class SysLoginUserRedisDAO { public LoginUser get(String sessionId) { String redisKey = formatKey(sessionId); - return JSON.parseObject(stringRedisTemplate.opsForValue().get(redisKey), LoginUser.class); + return JSONUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), LoginUser.class); } public void set(String sessionId, LoginUser loginUser) { String redisKey = formatKey(sessionId); - stringRedisTemplate.opsForValue().set(redisKey, JSON.toJSONString(loginUser), LOGIN_USER.getTimeout()); + stringRedisTemplate.opsForValue().set(redisKey, JSONUtils.toJSONString(loginUser), LOGIN_USER.getTimeout()); } public void delete(String accessToken) { diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/dao/common/SysCaptchaRedisDAO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/dao/common/SysCaptchaRedisDAO.java index 8e9d32446..adde4012e 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/dao/common/SysCaptchaRedisDAO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/dao/common/SysCaptchaRedisDAO.java @@ -1,12 +1,9 @@ package cn.iocoder.dashboard.modules.system.dal.redis.dao.common; -import cn.iocoder.dashboard.framework.security.core.LoginUser; -import com.alibaba.fastjson.JSON; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Repository; import javax.annotation.Resource; - import java.time.Duration; import static cn.iocoder.dashboard.modules.system.dal.redis.RedisKeyConstants.CAPTCHA_CODE; diff --git a/src/main/java/cn/iocoder/dashboard/util/json/JSONUtils.java b/src/main/java/cn/iocoder/dashboard/util/json/JSONUtils.java index 85633751f..8a7521758 100644 --- a/src/main/java/cn/iocoder/dashboard/util/json/JSONUtils.java +++ b/src/main/java/cn/iocoder/dashboard/util/json/JSONUtils.java @@ -1,6 +1,9 @@ package cn.iocoder.dashboard.util.json; -import com.alibaba.fastjson.JSON; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; /** * JSON 工具类 @@ -9,16 +12,35 @@ import com.alibaba.fastjson.JSON; */ public class JSONUtils { + private static ObjectMapper objectMapper = new ObjectMapper(); + + // TODO 芋艿,需要将 Spring 的设置下进来 + public static void setObjectMapper(ObjectMapper objectMapper) { + JSONUtils.objectMapper = objectMapper; + } + public static String toJSONString(Object object) { - return JSON.toJSONString(object); + try { + return objectMapper.writeValueAsString(object); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } } public static T parseObject(String text, Class clazz) { - return JSON.parseObject(text, clazz); + try { + return objectMapper.readValue(text, clazz); + } catch (IOException e) { + throw new RuntimeException(e); + } } public static T parseObject(byte[] bytes, Class clazz) { - return JSON.parseObject(bytes, clazz); + try { + return objectMapper.readValue(bytes, clazz); + } catch (IOException e) { + throw new RuntimeException(e); + } } } diff --git a/src/main/java/cn/iocoder/dashboard/util/servlet/ServletUtils.java b/src/main/java/cn/iocoder/dashboard/util/servlet/ServletUtils.java index ae9f61db5..e3cb86d77 100644 --- a/src/main/java/cn/iocoder/dashboard/util/servlet/ServletUtils.java +++ b/src/main/java/cn/iocoder/dashboard/util/servlet/ServletUtils.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.util.servlet; import cn.hutool.core.io.IoUtil; import cn.hutool.extra.servlet.ServletUtil; -import com.alibaba.fastjson.JSON; +import cn.iocoder.dashboard.util.json.JSONUtils; import org.springframework.http.MediaType; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; @@ -28,7 +28,7 @@ public class ServletUtils { */ @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码 public static void writeJSON(HttpServletResponse response, Object object) { - String content = JSON.toJSONString(object); + String content = JSONUtils.toJSONString(object); ServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE); } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 9a4e02e8c..0f0da2669 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -31,6 +31,11 @@ spring: url: http://127.0.0.1:8080/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址 # Spring Boot Admin Server 服务端的相关配置 context-path: /admin # 配置 Spring + # Jackson 配置项 + jackson: + serialization: + write-dates-as-timestamps: true # 设置时间的格式,使用时间戳 + write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401 # 芋道配置项,设置当前项目所有自定义的配置 yudao: