1

春の 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());

私のサービスクラスの1つで。これは正常に機能し、マップに追加されたユーザーを確認できます。

しかし、ログアウト時に 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 に既に追加されているすべてのユーザーが表示されます。このメソッドは、ユーザー サービス クラスの 1 つに含まれています。

  @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;
}

}

ユーザーがログインしたとき、2 人のユーザーがログインしたと仮定すると、マップは {1=user1, 9=user2} として取得されますが、いずれかのユーザーがログアウトした場合、onLogoutSuccess() メソッド内でマップ値を {} として取得します。もう 1 人のユーザーがログインすると、マップ {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(修飾子なしでその例を試したとき、春は2つのインスタンスを作成しました):

  @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 に答える