Vaadin部署Tomcat遇序列化异常致应用卸载问题求助
问题根源
Tomcat在会话钝化(内存不足时暂存会话到磁盘)或重启时,会对HttpSession中的所有对象执行序列化操作。Vaadin的UI实例默认绑定在会话中,如果UI引用了未实现Serializable接口的类(比如你提到的ApiBookUtils、Tag),就会触发NotSerializableException,进而导致Tomcat卸载应用。本地以JAR运行时,默认使用内存会话,不会触发序列化流程,因此不会出现该问题。
具体解决步骤
让涉及的类实现Serializable接口
直接给抛出异常的类添加Serializable实现,类中的非序列化成员要加transient修饰(序列化时会跳过这些成员,恢复时需手动初始化)。示例:public class Tag implements Serializable { // 显式声明序列化版本号,避免兼容问题 private static final long serialVersionUID = 1L; private String name; // 非序列化成员加transient private transient SomeNonSerializableService service; }对于工具类
ApiBookUtils,如果是被UI实例引用的非静态类,要么实现Serializable,要么改成静态工具类(静态成员不属于实例,不会被序列化)。清理Vaadin UI中的非序列化引用
检查Vaadin UI类(或@Route标注的视图类),如果成员变量引用了未序列化的对象,要么让该对象类实现Serializable,要么用transient修饰该成员,并在UI的attach()方法中重新初始化。示例:@Route("") public class MainView extends VerticalLayout { // 用transient跳过序列化 private transient ApiBookUtils bookUtils; public MainView() { initUtils(); } @Override public void attach() { super.attach(); // 会话恢复时重新初始化 if (bookUtils == null) { initUtils(); } } private void initUtils() { bookUtils = new ApiBookUtils(); } }临时禁用Tomcat会话序列化(仅测试环境用)
修改Tomcat的conf/context.xml,配置会话不持久化,避免触发序列化。但此方法会导致Tomcat重启后会话丢失,不适合生产环境:<Context> <Manager className="org.apache.catalina.session.StandardManager" persist="false"/> </Context>检查Vaadin会话配置
确保没有自定义的会话存储逻辑将非序列化对象存入HttpSession。Vaadin 14+ Flow模式下,注意@ViewScoped、@SessionScoped的Bean是否都实现了Serializable接口。
内容的提问来源于stack exchange,提问作者Gary Greenberg

