You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keycloak自定义SPI报错:如何添加jackson-datatype-jsr310模块?

解决Keycloak自定义SPI返回LocalDateTime的Jackson序列化错误

针对你遇到的Java 8 date/time type java.time.LocalDateTime not supported by default错误,可通过以下几种方式解决:

方法1:在自定义SPI中注册Jackson JSR310模块(推荐)

步骤1:添加依赖

在你的SPI项目的pom.xml中引入Jackson JSR310模块依赖,版本请匹配Keycloak内置的Jackson版本(比如Keycloak 22.x对应Jackson 2.15.3):

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.15.3</version>
    <scope>provided</scope> <!-- 若Keycloak容器已自带该jar,使用provided避免重复打包 -->
</dependency>

步骤2:自动注册模块

创建一个实现JacksonModuleProvider的类,让Keycloak启动时自动加载JSR310模块:

package com.b.keycloak.jackson;

import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.keycloak.jackson.JacksonModuleProvider;
import org.keycloak.models.KeycloakSession;
import java.util.Collections;
import java.util.List;

public class JavaTimeModuleProvider implements JacksonModuleProvider {
    @Override
    public List<com.fasterxml.jackson.databind.Module> getModules(KeycloakSession session) {
        return Collections.singletonList(new JavaTimeModule());
    }
}

步骤3:注册Provider

在项目的src/main/resources/META-INF/services目录下创建文件org.keycloak.jackson.JacksonModuleProvider,内容为上述类的全限定名:

com.b.keycloak.jackson.JavaTimeModuleProvider

重新编译打包SPI的jar,替换容器中providers目录下的旧jar,重启Keycloak即可。

方法2:在容器中添加JSR310模块jar

如果Keycloak容器未内置该模块,可直接将jar包挂载或复制到容器的providers目录:

方式A:Docker run挂载

下载对应版本的jackson-datatype-jsr310.jar,启动容器时添加挂载参数:

docker run -d \
  -v /path/to/your-spi.jar:/opt/bitnami/keycloak/providers/your-spi.jar \
  -v /path/to/jackson-datatype-jsr310.jar:/opt/bitnami/keycloak/providers/jackson-datatype-jsr310.jar \
  bitnami/keycloak:latest

方式B:构建自定义镜像

创建Dockerfile:

FROM bitnami/keycloak:latest
COPY jackson-datatype-jsr310.jar /opt/bitnami/keycloak/providers/
COPY your-spi.jar /opt/bitnami/keycloak/providers/

执行构建命令:

docker build -t custom-keycloak .

然后启动自定义镜像:

docker run -d custom-keycloak

方法3:手动配置ObjectMapper(临时方案)

在自定义端点的方法中,手动获取Keycloak的ObjectMapper并注册模块:

@POST
@NoCache
@Path("/users/{username}/endpoint")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response endpoint(
        @PathParam("username") final String username, SomeRequestBody someRequestBody) {
    // 获取Keycloak的Jackson ObjectMapper
    ObjectMapper mapper = keycloakSession.getContext().getContextObject(ObjectMapper.class);
    // 注册JSR310模块(避免重复注册)
    if (!mapper.isRegisteredModule(new JavaTimeModule())) {
        mapper.registerModule(new JavaTimeModule());
        // 可选:配置时间序列化为ISO8601格式,而非时间戳
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    }
    // 后续业务逻辑
    return Response.ok(new SomeResponse("Some field", LocalDateTime.now())).build();
}

内容的提问来源于stack exchange,提问作者Dinu Nicolae

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 13:46:23