Java tomcat会话不可序列化为带有@Value injection的spring组件
这是一个相当奇怪的问题。在春季,我将bean配置为会话Java tomcat会话不可序列化为带有@Value injection的spring组件,java,spring,session,tomcat,serialization,Java,Spring,Session,Tomcat,Serialization,这是一个相当奇怪的问题。在春季,我将bean配置为会话 @Component @Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS) public class UserSession implements Serializable{...} public class UserInterceptor extends HandlerInterceptorAdapter{ ... @Autowired priva
@Component
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class UserSession implements Serializable{...}
public class UserInterceptor extends HandlerInterceptorAdapter{
...
@Autowired private UserSession userSession;
@Autowired private WebUser webUser;
public boolean preHandle(...){
userSession.setUserId(webUser.getUserId());
userSession.setUserList(webUser.getUsers());
...
}
...
}
有一个与此会话交互的拦截器
@Component
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class UserSession implements Serializable{...}
public class UserInterceptor extends HandlerInterceptorAdapter{
...
@Autowired private UserSession userSession;
@Autowired private WebUser webUser;
public boolean preHandle(...){
userSession.setUserId(webUser.getUserId());
userSession.setUserList(webUser.getUsers());
...
}
...
}
WebUser
是一个界面,根据环境的不同,它将在其中注入不同的WebUser
。在profileLOCAL
中,In将注入LocalWebUser
@Component
@Primary
@Profile({"LOCAL"})
public class LocalWebUser implements WebUser, Serializable{
@Autowired private transient UserManager userManager;
@Value("${env.tester.userId}")
private transient String userId;
@Override
public List<String> getUsers() {
return this.userManager.getUsers();
}
...
}
@组件
@初级的
@配置文件({“本地”})
公共类LocalWebUser实现WebUser,可序列化{
@自动连线的私有瞬态用户管理器;
@值(${env.tester.userId}”)
私有临时字符串用户标识;
@凌驾
公共列表getUsers(){
返回这个.userManager.getUsers();
}
...
}
注意,我确实将make字段设置为transient
,以防止常见的序列化问题。然而,在tomcat中,它抛出LocalWebUser
是不可序列化的
原因:java.io.NotSerializableException:
com.company.component.web.LocalWebUser$1
位于java.io.ObjectOutputStream.WriteObject 0(ObjectOutputStream.java:1164)
位于java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
位于java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
LocalWebUser
实际上并没有存储在session中,只是session从中检索值。为什么它抱怨它不可序列化
我确实找到了一个解决方案,通过从属性中删除
@Value
注入,异常消失了,这让我更加困惑……一种可能是@Value注释通过字节码操作将userId
字段的类型修改为其他不可序列化的类型
因此,当您调用userSession.setUserId(webUser.getUserId())
时,它会将不可序列化的类型复制到userSession
然而,我找不到任何关于@Value注释的参考来支持这一点,所以这只是一种预感
您可能可以通过在运行时使用调试器检查
userId
字段的类型来验证这一点。它不是在抱怨LocalWebUser
。它在抱怨LocalWebUser$1
,这是LocalWebUser
中的一个匿名内部类。查看LocalWebUser
中的代码,了解类似以下内容:
Object something = new Something() { .... };
这是一个匿名的内部类。如果这是不可序列化的,并且对它的引用正在泄漏到会话中存储的对象中,那么这就是您的问题。wow。很好的观察。getUsers()上有一些guava转换,它将
new Function()
,这可能是原因?也许是。您是否能够在任何地方看到生成的代码,或者Guava是否编译为内存字节码?