1

spring 中 bean 的默认作用域是单例。但是,当我定义下一个服务时:

@Service("usersLoggedInService")
public class UsersLoggedInServiceImpl implements UsersLoggedInService {

private Map<Long, String> OnlineUsers = new LinkedHashMap<Long, String>();

@Override
public Map<Long, String> getOnlineUsers() {
    return OnlineUsers;
}

@Override
public void setOnlineUsers(Long id, String username) {
    OnlineUsers.put(id, username);
}

    @Override
public void removeLoggedOutUser(Long id){
    if(!OnlineUsers.isEmpty() && OnlineUsers.size()>0)
        OnlineUsers.remove(id);
}
} 

并将其用于登录审核,因此每当新用户登录时,我都会通过以下方式将其添加到 OnlineUsers LinkedHashMap:

usersLoggedInService.setOnlineUsers(user.getId(), user.getUsername());

在我的服务班之一。这工作正常,我可以看到地图中添加的用户。

但是,在注销时,我想删除在 LinkedhashMap 中添加的用户,当我检查 usersLoggedInService.getOnlineUsers() 时,我可以看到它是空的。我不明白为什么。

注销处理程序定义:

<logout invalidate-session="true" 
        logout-url="/logout.htm"
        success-handler-ref="myLogoutHandler"/>

及其实现:

 @Component
 public class MyLogoutHandler extends SimpleUrlLogoutSuccessHandler {

@Resource(name = "usersLoggedInService")
UsersLoggedInService usersLoggedInService; 

@Override
public void onLogoutSuccess(HttpServletRequest request,
        HttpServletResponse response, Authentication authentication)
        throws IOException, ServletException {
    if (authentication != null) {
        Object principal = authentication.getPrincipal();
            if(principal instanceof User){
                User user = (User) principal;
                usersLoggedInService.removeLoggedOutUser(user.getId());     

            }


    }
    setDefaultTargetUrl("/login");
    super.onLogoutSuccess(request, response, authentication);
}

}

请让我知道问题出在哪里。我不希望这张地图是空的。

- - -更新 - - -

当新用户登录时,我可以看到所有已添加到 LinkedHashmap 中的用户。此方法位于用户服务类之一中:

  @Service("userService")
  public class UserServiceImpl implements UserService {

  @Autowired
  UsersLoggedInService usersLoggedInService; 

   @Override
public User getUserDetail() {
    Authentication auth = SecurityContextHolder.getContext()
            .getAuthentication();   
    Object principal = auth.getPrincipal();
      if(principal instanceof User){
            User user = (User) principal;
            usersLoggedInService.setOnlineUsers(user.getId(), user.getUsername());

            return user;
        }
        return null;
}

}

当用户登录时,假设有两个用户登录,我将 Map 设为 {1=user1, 9=user2},但如果有任何用户注销,则在 onLogoutSuccess() 方法中,我将 Map 值设为 {}。现在,如果再有一个用户登录,那么我会得到地图 {1=user1, 9=user2, 3=user3}。因此,Map 仅在 onLogoutSuccess() 方法内部变空,并且在其他任何地方显示填充值。

4

2 回答 2

4

根据您的描述,似乎为处理程序创建了新的服务实例。

可能是您的配置的默认范围不是单例(应该很容易检查)。

另外,您可以尝试使用@Autowired注释吗?文档之间@Autowire@Resource文档之间存在细微差别,看起来它不应该导致这样的问题,但无论如何值得尝试:

@Component
public class MyLogoutHandler extends SimpleUrlLogoutSuccessHandler {

    @Autowired
    private UsersLoggedInsService usersLoggedInService;

    // ...
}

-----更新#1 ------

是的,尝试@Autowired使用@Qualifier(当我尝试没有限定符的示例时,spring 创建了两个实例):

  @Autowired
  @Qualifier("usersLoggedInService")
  UsersLoggedInService usersLoggedInService; 

----更新#2 ------

好吧,我只是在示例项目中复制了您的所有代码,并且it works on my machine.

您是否可以在GitHub等服务上共享您的代码库?

于 2012-12-20T02:56:23.090 回答
1

请显示正在调用的类setOnlineUsers。你是如何以及在什么地方检查地图不为空的?

尝试将记录器放入方法中onLogoutSuccess并检查您是否获得了新的或相同的UsersLoggedInService.

我假设您在连接 UsersLoggedIn* s *Service 的 bean 中有错字。有一个额外的's'

于 2012-12-20T10:47:38.190 回答