适用范围春季

时间:2012-12-20 00:34:57

标签: java spring spring-mvc spring-security

spring中bean的默认范围是singleton。但是当我定义了下一个服务时:

@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()方法内,我得到地图值为{}。现在,如果再有一个用户登录,那么我得到地图{1 = user1,9 = user2,3 = user3}。因此,Map仅在onLogoutSuccess()方法中变为空,并且在其他地方显示填充值。

2 个答案:

答案 0 :(得分:4)

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

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

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

@Component
public class MyLogoutHandler extends SimpleUrlLogoutSuccessHandler {

    @Autowired
    private UsersLoggedInsService usersLoggedInService;

    // ...
}

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

是的,请@Autowired@Qualifier一起尝试(当我尝试不带限定符弹簧的示例创建两个实例时):

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

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

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

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

答案 1 :(得分:1)

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

尝试在方法onLogoutSuccess中放入记录器,并检查您是否获得了UsersLoggedInService的新实例或相同实例。

我假设您在bean中有一个拼写错误,您正在连接UsersLoggedIn * s *服务。还有一个's'