From 9c07f7a007fccba5d337e0a426a3c0fadd10c7ef Mon Sep 17 00:00:00 2001 From: click33 <2393584716@qq.com> Date: Wed, 25 Feb 2026 19:13:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20sa-token-jackson3?= =?UTF-8?q?=20=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sa-token-bom/pom.xml | 5 + sa-token-dependencies/pom.xml | 8 ++ sa-token-plugin/pom.xml | 1 + .../plugin/SaTokenPluginForJackson.java | 2 +- sa-token-plugin/sa-token-jackson3/pom.xml | 46 +++++++ .../json/SaJsonTemplateForJackson3.java | 121 ++++++++++++++++++ .../plugin/SaTokenPluginForJackson3.java | 37 ++++++ .../cn.dev33.satoken.plugin.SaTokenPlugin | 1 + 8 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 sa-token-plugin/sa-token-jackson3/pom.xml create mode 100644 sa-token-plugin/sa-token-jackson3/src/main/java/cn/dev33/satoken/json/SaJsonTemplateForJackson3.java create mode 100644 sa-token-plugin/sa-token-jackson3/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForJackson3.java create mode 100644 sa-token-plugin/sa-token-jackson3/src/main/resources/META-INF/satoken/cn.dev33.satoken.plugin.SaTokenPlugin diff --git a/sa-token-bom/pom.xml b/sa-token-bom/pom.xml index 220b6585..5a7662a9 100644 --- a/sa-token-bom/pom.xml +++ b/sa-token-bom/pom.xml @@ -119,6 +119,11 @@ sa-token-jackson ${revision} + + cn.dev33 + sa-token-jackson3 + ${revision} + cn.dev33 sa-token-fastjson diff --git a/sa-token-dependencies/pom.xml b/sa-token-dependencies/pom.xml index 1701c921..61435bd0 100644 --- a/sa-token-dependencies/pom.xml +++ b/sa-token-dependencies/pom.xml @@ -21,6 +21,7 @@ 3.7.4 2.13.4.1 2.11.2 + 3.0.0 3.1.0 6.0.0 3.0.9.RELEASE @@ -97,6 +98,13 @@ jackson-databind ${jackson-databind.version} + + + + tools.jackson.core + jackson-databind + ${jackson3-databind.version} + diff --git a/sa-token-plugin/pom.xml b/sa-token-plugin/pom.xml index 92c9c783..f96056de 100644 --- a/sa-token-plugin/pom.xml +++ b/sa-token-plugin/pom.xml @@ -20,6 +20,7 @@ sa-token-jackson + sa-token-jackson3 sa-token-fastjson sa-token-fastjson2 sa-token-snack3 diff --git a/sa-token-plugin/sa-token-jackson/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForJackson.java b/sa-token-plugin/sa-token-jackson/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForJackson.java index 2c312949..a9b2b8f2 100644 --- a/sa-token-plugin/sa-token-jackson/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForJackson.java +++ b/sa-token-plugin/sa-token-jackson/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForJackson.java @@ -20,7 +20,7 @@ import cn.dev33.satoken.json.SaJsonTemplateDefaultImpl; import cn.dev33.satoken.json.SaJsonTemplateForJackson; /** - * SaToken 插件安装:JSON 转换器 (jackjson 版) + * SaToken 插件安装:JSON 转换器 (jackson 版) * * @author click33 * @since 1.41.0 diff --git a/sa-token-plugin/sa-token-jackson3/pom.xml b/sa-token-plugin/sa-token-jackson3/pom.xml new file mode 100644 index 00000000..343c4cc6 --- /dev/null +++ b/sa-token-plugin/sa-token-jackson3/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + + cn.dev33 + sa-token-plugin + ${revision} + ../pom.xml + + jar + + sa-token-jackson3 + sa-token-jackson3 + sa-token-jackson3: Sa-Token 与 Jackson 3 整合 + + + + + cn.dev33 + sa-token-core + + + + tools.jackson.core + jackson-databind + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + + + + diff --git a/sa-token-plugin/sa-token-jackson3/src/main/java/cn/dev33/satoken/json/SaJsonTemplateForJackson3.java b/sa-token-plugin/sa-token-jackson3/src/main/java/cn/dev33/satoken/json/SaJsonTemplateForJackson3.java new file mode 100644 index 00000000..ccd569ab --- /dev/null +++ b/sa-token-plugin/sa-token-jackson3/src/main/java/cn/dev33/satoken/json/SaJsonTemplateForJackson3.java @@ -0,0 +1,121 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.json; + +import cn.dev33.satoken.exception.SaJsonConvertException; +import cn.dev33.satoken.util.SaFoxUtil; +import tools.jackson.core.JacksonException; +import tools.jackson.databind.DeserializationFeature; +import tools.jackson.databind.DefaultTyping; +import tools.jackson.databind.SerializationFeature; +import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator; +import tools.jackson.databind.jsontype.PolymorphicTypeValidator; +import tools.jackson.databind.json.JsonMapper; + +import java.util.Map; + +/** + * JSON 转换器,Jackson 3 版实现 + * + * @author click33 + * @since 1.45.0 + */ +public class SaJsonTemplateForJackson3 implements SaJsonTemplate { + + /** + * 底层 Mapper 对象(带多态类型信息,用于 Session 等复杂对象序列化) + */ + public final JsonMapper objectMapper; + + /** + * 处理 Map 的 Mapper(无多态类型配置,用于简单 JSON 解析) + */ + public final JsonMapper mapObjectMapper; + + public SaJsonTemplateForJackson3() { + // 1、构建反序列化限制器(PolymorphicTypeValidator),限制哪些类型可以被自动多态反序列化 + // 这里允许所有 Object 类型和其子类型参与多态反序列化,从而支持复杂对象(如 SaSession)的序列化、反序列化 + PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder() + .allowIfSubType(Object.class) // 允许 Object.class 的子类型被反序列化 + .allowIfBaseType(Object.class) // 允许 Object.class 作为基类型(在启用多态时) + .build(); // 构建 Validator 实例 + + // 2、通过 JsonMapper 的 builder 模式创建 objectMapper(用于带多态类型信息的 JSON 处理,Jackson3 默认不可变需用构建器) + this.objectMapper = JsonMapper.builder() + // 启用默认多态类型处理,并以 "@class" 作为写入类型信息的属性名(即持久化时包含类型字段),仅对非 final 类型生效 + .activateDefaultTypingAsProperty(ptv, DefaultTyping.NON_FINAL, "@class") + .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) // 序列化时如果 bean 没有属性,则不抛出异常 + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) // 反序列化时如果有未知属性,也不抛出异常(兼容性更好) + .build(); // 构建真正的 JsonMapper 实例 + + // 3、创建 mapObjectMapper,用于简单类型(如 Map)的序列化和反序列化,和 objectMapper 独立,且不启用多态类型 + this.mapObjectMapper = JsonMapper.builder() + .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) // 序列化时如果 bean 没有属性,则不抛出异常 + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) // 反序列化时如果有未知属性,也不抛出异常,避免出错 + .build(); // 构建用于处理简单场景的 JsonMapper 实例 + } + + /** + * 序列化:对象 -> json 字符串 + */ + @Override + public String objectToJson(Object obj) { + if (SaFoxUtil.isEmpty(obj)) { + return null; + } + try { + if (obj instanceof Map) { + return mapObjectMapper.writeValueAsString(obj); + } + return objectMapper.writeValueAsString(obj); + } catch (JacksonException e) { + throw new SaJsonConvertException(e); + } + } + + /** + * 反序列化:json 字符串 → 对象 + */ + @Override + public T jsonToObject(String jsonStr, Class type) { + if (SaFoxUtil.isEmpty(jsonStr)) { + return null; + } + try { + return objectMapper.readValue(jsonStr, type); + } catch (JacksonException e) { + throw new SaJsonConvertException(e); + } + } + + /** + * 将 json 字符串解析为 Map + */ + @Override + public Map jsonToMap(String jsonStr) { + if (SaFoxUtil.isEmpty(jsonStr)) { + return null; + } + try { + @SuppressWarnings("unchecked") + Map map = mapObjectMapper.readValue(jsonStr, Map.class); + return map; + } catch (JacksonException e) { + throw new SaJsonConvertException(e); + } + } + +} diff --git a/sa-token-plugin/sa-token-jackson3/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForJackson3.java b/sa-token-plugin/sa-token-jackson3/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForJackson3.java new file mode 100644 index 00000000..aff451c6 --- /dev/null +++ b/sa-token-plugin/sa-token-jackson3/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginForJackson3.java @@ -0,0 +1,37 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.plugin; + +import cn.dev33.satoken.SaManager; +import cn.dev33.satoken.json.SaJsonTemplateDefaultImpl; +import cn.dev33.satoken.json.SaJsonTemplateForJackson3; + +/** + * SaToken 插件安装:JSON 转换器 (Jackson 3 版) + * + * @author click33 + * @since 1.45.0 + */ +public class SaTokenPluginForJackson3 implements SaTokenPlugin { + + @Override + public void install() { + // 只有在未提供自定义的 json 解析器时才会生效,给予其较弱的优先级 + if (SaManager.getSaJsonTemplate().getClass() == SaJsonTemplateDefaultImpl.class) { + SaManager.setSaJsonTemplate(new SaJsonTemplateForJackson3()); + } + } +} diff --git a/sa-token-plugin/sa-token-jackson3/src/main/resources/META-INF/satoken/cn.dev33.satoken.plugin.SaTokenPlugin b/sa-token-plugin/sa-token-jackson3/src/main/resources/META-INF/satoken/cn.dev33.satoken.plugin.SaTokenPlugin new file mode 100644 index 00000000..bee1a12e --- /dev/null +++ b/sa-token-plugin/sa-token-jackson3/src/main/resources/META-INF/satoken/cn.dev33.satoken.plugin.SaTokenPlugin @@ -0,0 +1 @@ +cn.dev33.satoken.plugin.SaTokenPluginForJackson3