You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

JAX-RS客户端解析响应日期失败问题求助

解决Spring Boot与JavaEE 7 JAX-RS客户端的日期序列化/反序列化不兼容问题

看起来你遇到的核心问题是两端JSON框架不兼容:Spring Boot用的是Jackson(靠@JsonFormat注解控制日期格式),但JavaEE 7端的JAX-RS客户端默认用的是JSON-B的Yasson实现——Jackson的注解对Yasson完全不起作用,这才导致了日期解析失败。

先拆解下错误根源:Spring Boot输出的日期格式是2016-07-14T21:00:00.000+0000,但Yasson默认的java.util.Date解析规则不匹配这个格式,所以抛出了DateTimeParseException。下面给你几个可行的解决方案:

方案1:在JavaEE端的DTO上使用JSON-B专属注解

既然JavaEE端用的是JSON-B,就把Jackson的@JsonFormat替换成JSON-B的@JsonbDateFormat,并匹配Spring Boot输出的日期格式:

import javax.json.bind.annotation.JsonbDateFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;

@Data
public class BudgetRecipientsReferenceViewHolder implements Serializable {
    private static final long serialVersionUID = -2971479083071002129L;
    private Long treasuryBranchCode;
    private String budgetRecipientAccount;
    private String budgetRecipientName;
    private boolean active;
    private String budgetRecipientINN;
    
    // 完全匹配Spring Boot输出的日期格式
    @JsonbDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    private Date openDate;
    
    @JsonbDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    private Date closeDate;
}

这里的yyyy-MM-dd'T'HH:mm:ss.SSSZ正好对应错误日志里的2016-07-14T21:00:00.000+0000格式,Z用来匹配时区偏移(比如+0000)。

方案2:统一Spring Boot的日期输出格式为Yasson默认支持的类型

如果你不想修改JavaEE端的代码,可以调整Spring Boot的Jackson配置,让它输出Yasson默认能解析的ISO-8601格式日期:

在Spring Boot的application.properties里添加配置:

# 让Jackson输出标准ISO-8601日期格式
spring.jackson.date-format=com.fasterxml.jackson.databind.util.StdDateFormat
spring.jackson.serialization.write-dates-as-timestamps=false

或者直接指定格式字符串:

spring.jackson.date-format=yyyy-MM-dd'T'HH:mm:ss.SSSXXX

这样Spring Boot输出的日期会变成2016-07-14T21:00:00.000Z,Yasson无需额外配置就能正常解析。

方案3:在JavaEE端全局配置Yasson的日期解析规则

如果不想逐个修改DTO的注解,可以在JAX-RS客户端创建时,全局配置Yasson的日期解析格式:

@Override 
public BudgetRecipientsReferenceViewHolderResponse getBudgetRecipients(String language, DefaultRequest request, String sessionKey) {
    // 配置Yasson使用指定格式解析日期
    JsonbConfig jsonbConfig = new JsonbConfig()
            .setProperty(JsonbDateFormat.DEFAULT_FORMAT, "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
            // 可选:开启零时间默认值,作为解析失败的 fallback
            .setProperty(YassonProperties.ZERO_TIME_PARSE_DEFAULTING, true);
            
    Jsonb jsonb = JsonbBuilder.create(jsonbConfig);
    
    return ClientBuilder.newClient()
           .register(new JsonbFeature(jsonb)) // 注册自定义配置的JSON-B处理器
           .target(URI.create("http://127.0.0.1:8082/dboreferences/budgetRecipientsReferenceView/getAll"))
           .request(MediaType.APPLICATION_JSON)
           .header(GlobalConsts.SESSION_TOKEN, sessionKey)
           .post(Entity.entity(request, MediaType.APPLICATION_JSON), BudgetRecipientsReferenceViewHolder.class);
}

补充小提示

你之前删除@JsonFormat注解没生效,是因为Spring Boot的Jackson默认输出格式和Yasson默认解析格式不匹配;另外注意原注解里的hh是12小时制,而日志里的时间是21点(24小时制),建议统一用HH避免潜在问题。

内容的提问来源于stack exchange,提问作者artyom.poteshkin98

火山引擎 最新活动