如何解决Java中java.util.Timer类无序列化器的异常?
解决Jackson序列化
java.util.Timer时的No serializer found异常 这个问题我之前也碰到过,本质是Jackson默认无法序列化像java.util.Timer这类没有可被序列化属性的类,而且默认配置下遇到这种“空Bean”会直接抛出异常。结合你的代码场景,给你几个最实用的解决方案:
方案1:忽略Timer字段的序列化(推荐)
因为你的Timer是用来执行定时任务的内部组件,完全不需要被序列化(比如返回给前端或者持久化到数据库),直接用Jackson的@JsonIgnore注解标记这个字段或者它的getter方法即可:
修改后的ModelClass代码
import com.fasterxml.jackson.annotation.JsonIgnore; import java.io.Serializable; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class ModelClass implements Serializable { private static final long serialVersionUID = 613977314761191083L; private String id; private String name; @JsonIgnore // 标记此字段不参与序列化 private Timer timer; public ModelClass() { timer = new Timer(); } // 以下getter、setter方法保持不变 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; timer.schedule(new TimerTask() { @Override public void run() { System.out.println(name + " " + new Date().toString()); } }, 0, 2000); } public Timer getTimer() { return timer; } public void setTimer(Timer timer) { this.timer = timer; } }
或者你也可以在getTimer()方法上添加@JsonIgnore,效果是一样的:
@JsonIgnore public Timer getTimer() { return timer; }
这个方案最直接,也符合业务逻辑——毕竟定时任务组件不需要对外暴露。
方案2:全局禁用FAIL_ON_EMPTY_BEANS特性
如果你的项目中有多个类似的空Bean需要处理,也可以全局关闭Jackson的FAIL_ON_EMPTY_BEANS序列化特性,这样Jackson遇到没有可序列化属性的类时会直接跳过而不是抛出异常。
配置示例(Spring Boot环境)
import com.fasterxml.jackson.databind.SerializationFeature; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.fasterxml.jackson.databind.ObjectMapper; @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); // 关闭空Bean序列化失败的特性 objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); return objectMapper; } }
不过要注意,这个方案是全局生效的,可能会掩盖其他潜在的序列化问题(比如某个类忘记添加可序列化的属性),所以除非必要,优先用方案1。
方案3:自定义Timer的序列化器(极少用)
如果出于特殊需求必须序列化Timer,可以自定义一个Json序列化器,比如只序列化Timer的标识或者忽略其内容:
自定义序列化器示例
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; import java.util.Timer; public class TimerSerializer extends JsonSerializer<Timer> { @Override public void serialize(Timer timer, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 这里可以自定义序列化内容,比如写一个固定标识,或者直接跳过 gen.writeString("Timer-instance"); } }
然后在ModelClass的timer字段上添加@JsonSerialize注解:
@JsonSerialize(using = TimerSerializer.class) private Timer timer;
不过这个场景在实际业务中非常少见,因为Timer本身是用于任务调度的实例,序列化它几乎没有业务价值。
内容的提问来源于stack exchange,提问作者Debasish Halder
相关产品推荐
相关产品推荐

