3.spring boot入门篇之添加fastjson

一、添加fastjson方式有两种:

添加fastjson依赖:

<!-- 添加fastjson 依赖包. -->
<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>1.2.15</version>
</dependency>

1.spring boot启动类继承WebMvcConfigurationSupport,重写configureMessageConverters方法。

	@Override
	public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
		super.configureMessageConverters(converters);
		// 1.需要先定义一个convert 转换消息的对象
		FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
		// 2.添加fastJson的配置信息,比如,是否需要格式化返回的json数据
		FastJsonConfig fastJsonConfig = new FastJsonConfig();
		// 空值特别处理
		// WriteNullListAsEmpty 将Collection类型字段的字段空值输出为[]
		// WriteNullStringAsEmpty 将字符串类型字段的空值输出为空字符串 ""
		// WriteNullNumberAsZero 将数值类型字段的空值输出为0
		// WriteNullBooleanAsFalse 将Boolean类型字段的空值输出为false
		fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat, SerializerFeature.WriteNullListAsEmpty,
				SerializerFeature.WriteNullStringAsEmpty);
		// 处理中文乱码问题
		List<MediaType> fastMediaTypes = new ArrayList<>();
		fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
		fastConverter.setSupportedMediaTypes(fastMediaTypes);
		// 3.在convert中添加配置信息
		fastConverter.setFastJsonConfig(fastJsonConfig);
		// 4.将convert添加到converters当中
		converters.add(fastConverter);

	}

2.用@Bean注解来实现,代码如下

@Bean
	public HttpMessageConverters fastJsonHttpMessageConverters() {
		FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
		// 2.添加fastJson的配置信息,比如,是否需要格式化返回的json数据
		FastJsonConfig fastJsonConfig = new FastJsonConfig();
		// 空值特别处理
		// WriteNullListAsEmpty 将Collection类型字段的字段空值输出为[]
		// WriteNullStringAsEmpty 将字符串类型字段的空值输出为空字符串 ""
		// WriteNullNumberAsZero 将数值类型字段的空值输出为0
		// WriteNullBooleanAsFalse 将Boolean类型字段的空值输出为false
		fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat, SerializerFeature.WriteNullListAsEmpty,
				SerializerFeature.WriteNullStringAsEmpty);
		// 处理中文乱码问题
		List<MediaType> fastMediaTypes = new ArrayList<>();
		fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
		fastConverter.setSupportedMediaTypes(fastMediaTypes);
		// 3.在convert中添加配置信息
		fastConverter.setFastJsonConfig(fastJsonConfig);

		HttpMessageConverter<?> converter = fastConverter;
		return new HttpMessageConverters(converter);
	}

 

二、在java bean里面使用@JSONField注解,如

@JSONField(format="yyyy-MM-dd HH:mm")//Date类型的格式化
@JSONField(serialize=false)//该属性不进行序列化
<think>首先,用户的问题是关于在Spring Security中使用FastJSON时出现的类转换异常:"class com.alibaba.fastjson.JSONObject cannot be cast to class org.springframework.security.core.GrantedAuthority"。用户提供了引用内容,这些引用涉及到Spring Security、FastJSON、Redis序列化等问题。 关键点: - 用户试图将FastJSON的JSONObject转换为GrantedAuthority对象。 - 引用中提到了Redis序列化问题,特别是当使用FastJSON序列化时,出现了类型转换错误。 - 引用[3]特别提到了升级FastJSON后出现"autoType is not support"错误,以及无法自动转化实体类的问题。 - 引用[4]提到了一个SerializationException,涉及"accountNonLocked"字段无法识别。 用户的问题核心是:如何解决将JSONObject转换为GrantedAuthority的类转换异常。 在Spring Security中,GrantedAuthority通常表示用户的权限。当从Redis或其他存储中反序列化用户数据时,如果序列化/反序列化配置不当,可能会导致类型转换问题。 从引用中,我可以推断: - 用户可能在Redis中存储了用户信息(如LoginUser对象),该对象包含GrantedAuthority集合。 - 当从Redis获取数据时,使用FastJSON进行反序列化,但由于序列化器配置问题,GrantedAuthority对象被序列化为JSONObject,而不是还原为具体的GrantedAuthority实现类。 - 这导致了类转换异常,因为JSONObject不能被强制转换为GrantedAuthority接口。 解决方案: 1. **正确配置Redis序列化器**:确保在Spring Boot应用中,RedisTemplate使用适当的序列化器来处理GrantedAuthority对象。FastJSON可能需要额外的配置来支持多态类型处理。 2. **使用自定义序列化器**:为GrantedAuthority实现自定义的序列化/反序列化逻辑,因为GrantedAuthority是一个接口,FastJSON可能无法直接处理。 3. **启用FastJSON的autoType支持**:但要注意安全风险。引用[3]提到了autoType问题,这可能需要在反序列化时指定类型。 4. **检查对象结构**:确保存储的对象结构与反序列化时预期的类型匹配。引用[4]指出字段"accountNonLocked"未被识别,表明可能有版本不匹配或字段缺失问题。 基于引用[3]中的代码片段: ```java public <T> T getCacheObject(final String key, Class<T> clazz) { ValueOperations<String, T> operation = redisTemplate.opsForValue(); Object jsonObject = operation.get(key); try { return JSON.parseObject(JSON.toJSONString(jsonObject), clazz); } catch (Exception e) { e.printStackTrace(); if (null != jsonObject) { return (T) jsonObject; } else { return null; } } } ``` 这里,从Redis获取的对象被转换为JSON字符串,然后使用JSON.parseObject反序列化为指定类。问题可能在于GrantedAuthority没有被正确处理。 建议的解决方案: - 为GrantedAuthority使用自定义的序列化器。 - 或者,在反序列化时,提供TypeReference来指定具体类型。 在Spring Security中,GrantedAuthority通常由SimpleGrantedAuthority实现。所以,在反序列化时,需要确保JSON被解析为正确的实现类。 步骤: 1. **配置RedisTemplate使用FastJSON序列化器**:但需要处理接口类型。 2. **创建自定义的RedisSerializer**:针对GrantedAuthority实现序列化逻辑。 3. **在反序列化时指定类型**:例如,使用TypeReference。 例如,修改getCacheObject方法: ```java public <T> T getCacheObject(final String key, Class<T> clazz) { ValueOperations<String, T> operation = redisTemplate.opsForValue(); Object obj = operation.get(key); if (obj instanceof JSONObject) { JSONObject jsonObject = (JSONObject) obj; // 对于GrantedAuthority,需要特殊处理 if (GrantedAuthority.class.isAssignableFrom(clazz)) { // 假设权限是字符串形式,如 "ROLE_USER" String authority = jsonObject.getString("authority"); return (T) new SimpleGrantedAuthority(authority); } return JSON.parseObject(jsonObject.toJSONString(), clazz); } return (T) obj; } ``` 但这不是很通用。更好的方式是使用FastJSON的特性。 引用[3]提到autoType问题。FastJSON在1.2.25版本后默认关闭autoType,需要显式开启或使用ParserConfig。 解决方案: - 在反序列化GrantedAuthority时,使用TypeReference或ParserConfig指定类型。 例如: ```java ParserConfig.getGlobalInstance().addAccept("org.springframework.security.core.authority.SimpleGrantedAuthority"); ``` 然后在parseObject时使用。 但更安全的方式是避免直接反序列化接口,而是反序列化为具体类。 在Spring Security上下文中,用户对象(如UserDetails实现)应该被完整序列化/反序列化。 最佳实践: - 确保用户对象实现了Serializable。 - 使用自定义的RedisSerializer,比如基于Jackson或FastJSON,但配置好来处理安全对象。 在Spring Boot中,可以配置RedisTemplate: ```java @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); // 使用FastJSON序列化FastJsonRedisSerializer<Object> serializer = new FastJsonRedisSerializer<>(Object.class); // 配置ParserConfig以支持安全类 ParserConfig parserConfig = new ParserConfig(); parserConfig.addAccept("org.springframework.security.core."); serializer.setParserConfig(parserConfig); template.setDefaultSerializer(serializer); return template; } ``` 但需要自定义FastJsonRedisSerializer来处理。 或者,使用Spring提供的Jackson2JsonRedisSerializer,它可能更兼容。 用户提到FastJSON,所以坚持使用FastJSON。 总结回答结构: 1. **解释问题**:简要说明为什么会出现类转换异常。 2. **解决方案**: - 配置FastJSON的autoType支持。 - 使用自定义序列化器。 - 在反序列化时指定具体类型。 3. **代码示例**:提供修改后的getCacheObject方法或RedisTemplate配置。 4. **注意事项**:提醒autoType的安全风险。 最后,生成相关问题。 系统级指令要求: - 行内数学表达式用$...$。 - 独立公式用$$...$$。 - 使用中文回答。 - 生成相关问题。 - 引用末尾添加标识如[^1]。 用户提供引用:[^1]到[^5],我会在回答中引用它们。 回答组织: 1. 问题分析。 2. 解决方案。 3. 代码示例。 4. 相关问题。</think>### 解决 Spring Security 中 FastJSON 的 JSONObject 无法转换为 GrantedAuthority 的问题 在 Spring Security 中使用 FastJSON序列化 Redis 缓存数据时,出现 `class com.alibaba.fastjson.JSONObject cannot be cast to class org.springframework.security.core.GrantedAuthority` 异常,通常是由于序列化/反序列化配置不当导致的。根本原因在于 FastJSON 默认无法正确处理接口类型(如 `GrantedAuthority`),且 Redis 存储的数据结构可能不兼容。以下是逐步解决方案: --- ### 问题分析 1. **接口类型处理问题**: `GrantedAuthority` 是一个接口(通常由 `SimpleGrantedAuthority` 实现)。FastJSON 在反序列化时,若未明确指定具体实现类,会生成 `JSONObject` 而非目标对象,导致强制转换失败[^3][^4]。 2. **autoType 安全限制**: FastJSON 升级后默认关闭 autoType 支持(防止安全漏洞),需显式配置以允许反序列化 Spring Security 相关类[^3]。 3. **字段不匹配问题**: 用户对象(如 `LoginUser`)可能包含 `GrantedAuthority` 集合,但反序列化FastJSON 无法识别 `accountNonLocked` 等字段(Spring Security 特有字段),导致数据损坏[^4]。 --- ### 解决方案 #### 步骤 1: 配置 FastJSON 支持 autoType(安全风险可控) 在应用启动时配置 FastJSON 的 `ParserConfig`,允许反序列化 `GrantedAuthority` 及其实现类。 **代码示例**: ```java import com.alibaba.fastjson.parser.ParserConfig; @SpringBootApplication public class Application { public static void main(String[] args) { // 启用 autoType 并添加安全白名单 ParserConfig.getGlobalInstance().setAutoTypeSupport(true); ParserConfig.getGlobalInstance().addAccept("org.springframework.security.core."); SpringApplication.run(Application.class, args); } } ``` - **说明**: `addAccept("org.springframework.security.core.")` 允许反序列化该包下的所有类(如 `SimpleGrantedAuthority`)。 **注意**:autoType 有安全风险,仅添加必要包名可降低风险[^3]。 #### 步骤 2: 自定义 Redis 反序列化逻辑 修改 Redis 工具类中的 `getCacheObject` 方法,显式处理 `GrantedAuthority` 类型: ```java import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; public <T> T getCacheObject(final String key, Class<T> clazz) { Object jsonObject = redisTemplate.opsForValue().get(key); if (jsonObject == null) return null; try { // 针对 GrantedAuthority 特殊处理 if (GrantedAuthority.class.isAssignableFrom(clazz)) { String authorityStr = JSON.parseObject(JSON.toJSONString(jsonObject), String.class); return (T) new SimpleGrantedAuthority(authorityStr); // 转换为具体实现类 } // 其他类型使用 FastJSON 标准反序列化 return JSON.parseObject(JSON.toJSONString(jsonObject), clazz); } catch (Exception e) { throw new SerializationException("反序列化失败: " + e.getMessage(), e); } } ``` #### 步骤 3: 统一序列化格式(推荐) 为 Redis 配置自定义序列化器,避免手动转换: 1. **创建 FastJSON 序列化器**: ```java import org.springframework.data.redis.serializer.RedisSerializer; import com.alibaba.fastjson.JSON; public class FastJsonRedisSerializer<T> implements RedisSerializer<T> { private final Class<T> clazz; public FastJsonRedisSerializer(Class<T> clazz) { this.clazz = clazz; } @Override public byte[] serialize(T t) { return JSON.toJSONBytes(t); } @Override public T deserialize(byte[] bytes) { if (bytes == null) return null; return JSON.parseObject(bytes, clazz); } } ``` 2. **在 RedisTemplate 中应用序列化器**: ```java @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); // 为 GrantedAuthority 使用自定义序列化FastJsonRedisSerializer<GrantedAuthority> authoritySerializer = new FastJsonRedisSerializer<>(GrantedAuthority.class); template.setValueSerializer(authoritySerializer); template.afterPropertiesSet(); return template; } ``` - **优势**:确保 `GrantedAuthority` 始终被序列化为字符串(如 `"ROLE_ADMIN"`),反序列化时自动还原为 `SimpleGrantedAuthority`[^1][^4]。 --- ### 注意事项 1. **安全与兼容性**: - 若启用 autoType,需定期更新 FastJSON 版本以修复漏洞。 - 检查 `LoginUser` 类是否实现 `Serializable` 接口,否则 Redis 序列化可能失败[^1][^5]。 2. **字段一致性**: 确保 `LoginUser` 中的字段(如 `accountNonLocked`)与 JSON 数据匹配。若字段缺失,添加 `@JSONField(serialize = false)` 忽略未知字段: ```java public class LoginUser implements UserDetails { @JSONField(serialize = false) private boolean accountNonLocked; // 忽略 FastJSON 不支持的字段 } ``` 3. **依赖管理**: 检查 FastJSONSpring Security 版本兼容性。推荐使用较新版本(如 FastJSON ≥ 1.2.83)[^3]。 --- ### 总结 通过配置 FastJSON 的 autoType 白名单、自定义 Redis 序列化器,或显式处理 `GrantedAuthority` 类型,可解决类转换异常。核心是**确保接口类型被反序列化为具体实现类**。若问题持续,检查 Redis 存储的数据格式是否完整[^1][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值