我有一个Apache Wicket 1.5应用程序,该应用程序使用Shiro进行安全保护,并使用Guice进行依赖项注入。
它的大多数页面都是无状态的,但是我的一些模型对象(用户数据,当前菜单状态等)需要在同一会话中的所有请求之间保持一致。所有这些对象都具有逻辑(通常是使用远程EJB3接口访问数据库的简单查找程序方法)和状态,并且它们都实现了Serializable。
这是一个简短的摘要,应该传达出这个想法:
@SessionScoped
public class UsersImpl implements Users, Serializable {
private static final long serialVersionUID = 8841809043461673585L;
private final Logger log = LoggerFactory.getLogger( UsersImpl.class );
@Inject
public UserService users;
@Inject
public RoleService roles;
private UserDTO currentUser;
public UserVO findUserByUser( UserVO user ) {
UserDTO userDto = null;
try {
userDto = users.findUserByUser( user.toUserDTO() );
} catch( Exception e ) {
log.error( "Error finding user:"+user.id, e );
}
return userDto != null ? new UserVO( userDto ) : null;
}
(...)
}
我使用
@Singleton
开发和对类进行了单元测试(为简单起见),这种方式一切正常,但是由于我已经切换到@SessionScoped
进行生产,所以我经常遇到这样的错误:Guice provision errors:
1) Error in custom provider, org.apache.shiro.session.InvalidSessionException:
java.lang.IllegalArgumentException:
HttpSession based implementations of the Shiro Session interface requires attribute keys to be String objects. The HttpSession class does not support anything other than String keys.
显然,Guice似乎使用了一些自定义的Key对象将对象存储在会话中,而Shiro HttpSession实现无法处理该对象。不过,奇怪的是,并非所有
@SessionScoped
类都发生此异常,但是肯定有多个。我一直在疯狂地搜索网络,寻找一个我能做的主意-某种方式迫使Guice使用Strings作为键,某种方式使HttpSession更加兼容,等等-但我似乎找不到任何方式有用的信息。另外,从我对错误消息的搜索结果来看,我似乎是地球上唯一甚至完全没有这个问题的人...
有什么办法可以使这项工作吗?还是我在这里做错了什么?
最佳答案
好吧,这个问题很难回答,但是我尝试给您一些选择。
您的错误来自预先检查...所以,我认为您的应用程序甚至都没有启动,对吧?然后很可能在Production阶段使用,或者急切地创建了一些绑定,并且该对象引用了Session
范围中的另一个对象,这是有问题的。因此,现在您应该将所有SessionScope
直接注入更改为提供者注入,如以下示例所示:
你能改变吗
@Inject
public UserService users;
至
@Inject
public Provider<UserService> userProvider; //and call userProvider.get() when you will need it?
为什么这样?
SessionScoped
对象只能通过whit GuiceFilter.doFilter()
来访问,因此,如果您混合使用范围,则可能会在某些运行时异常中结束。特别是,当您将Stage
更改为Production
或将一些Singletons设置为热切加载时。您可以了解更多here。混合Providers
Scopes
是一个好习惯Subject
仅绑定在ShiroFilter.doFilter()
check my post内部。然后,如果您在外面,请说GuiceFilter
,那时候可能没有Subject
绑定。同样,尝试使用Providers
。 希望会有所帮助。