我有一个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

  • 希望会有所帮助。

    09-13 01:11