2 つのコントローラーで @SessionAttributes を使用していますが、非常に奇妙な動作が発生しています。私の最初のコントローラー (ViewController) は、JSP ページを表示する単純なビュー コントローラーです。もう 1 つは、Ajax リクエストを処理するコントローラー (AjaxController) です。メンバーとして HashMap を持つ単なるオブジェクトであるセッション属性があります。オブジェクトはマップのラッパーです。マップはデータベースから読み込まれ、ViewController を介して正常に表示されるセッションに配置されます。ただし、ajax 要求 (AjaxController) を介してマップから削除を行い、ページを更新すると、ViewController は要素が削除されたことを示しますが、要素がまだそこにあることもあります。コード スニペットは次のとおりです。
ViewController (ホームページは、userSettings に含まれるマップのコンテンツを表示するだけです。
@Controller
@SessionAttributes({"userSettings"})
public class ViewController {
@RequestMapping(value="/", method=RequestMethod.GET)
public String home(ModelMap model) {
UserSettings userSettings = (UserSettings) model.get("userSettings");
String userListenersJson = userSettings.toJson(); // for bootsrtapping the js on the front end
return "views/home";
}
}
Ajaxコントローラー:
@Controller
@SessionAttributes({"userSettings"})
public class AjaxController {
@RequestMapping(value="/users/listeners/{externalId}", method=RequestMethod.DELETE)
public @ResponseBody
AjaxResponse<?> deleteListener(ModelMap model,
@PathVariable long externalId) {
UserSettings userSettings = (UserSettings) model.get("userSettings");
userSettings.removeSetting(externalId);
return new AjaxResponse<String>(null, true);
}
}
ここで @SessionAttributes を間違って使用していますか? なぜこれが時々うまくいくのですか?また、すべてのビューと ajax 機能を同じコントローラーに配置しようとしましたが、同じ動作を経験しました。
助けてくれてありがとう!
編集:
springsecurity を介して UserPrincipal を使用するために、コードを少しリファクタリングしました。私の理解では、このオブジェクトはセッションに保存されています。とにかく、まったく同じ動作が見られます。
ユーザー設定マップを設定する UserPrincipal コンストラクターを次に示します。ここでブレークポイントを設定して、正しい listenerDBO が設定されるようにしました。リスナーが db から CustomUserPrincipal の UserSettings オブジェクトに設定されるのはこれだけです。他のすべての追加/削除はコントローラーを介して行われます (簡単に言うと、追加は決して失敗しません... 削除のみです):
public CustomUserPrincipal(UserDBO userDBO) {
// set UserSettings obj
UserSettingsAdapter.addListeners(userDBO.getUserListenerDBOs(), userSettings);
}
UserSettings オブジェクト自体:
public class UserSettings implements Serializable {
private static final long serialVersionUID = -1882864351438544088L;
private static final Logger log = Logger.getLogger(UserSettings.class);
private Map<Long, Listener> userListeners = Collections.synchronizedMap(new HashMap<Long, Listener>(1));
// get the listeners as an arraylist
public List<Listener> userListeners() {
return new ArrayList<Listener>(userListeners.values());
}
public Map<Long, Listener> getUserListeners() {
return userListeners;
}
public Listener addListener(Listener listener) {
userListeners.put(listener.getId(), listener);
return listener;
}
// I'm logging here to try and debug the issue. I do see the success
// message each time this function is called
public Listener removeListener(Long id) {
Listener l = userListeners.remove(id);
if (l == null) {
log.info("failed to remove listener with id " + id);
} else {
log.info("successfully removed listener with id " + id);
}
log.info("Resulting map: " + userListeners.toString());
log.info("Map hashcode: " + userListeners.hashCode());
return l;
}
public Listener getListener(long id) {
return userListeners.get(id);
}
}
これは、UserSettings オブジェクトに追加する UserSettingsAdapter クラスのヘルパー関数であり、CustomUserDetails コンストラクターから呼び出されます。
public static void addListeners(Set<UserListenerDBO> userListeners, UserSettings userSettings) {
for (UserListenerDBO userListenerDBO : userListeners) {
if (userListenerDBO.isActive()) {
addListener(userListenerDBO, userSettings);
}
}
}
@SessionAttributes の代わりに CustomUserPrincipal オブジェクトを使用するようにコントローラー コードも変更しました。
ViewController で:
@RequestMapping(value="/", method=RequestMethod.GET)
public String home(ModelMap model) {
CustomUserPrincipal userPrincipal = authenticationHelpers.getUserPrincipal();
UserSettings userSettings = userPrincipal.getUserSettings();
String userListenersJson = userSettings.toJson();
return "views/home";
}
AjaxController では:
@RequestMapping(value="/users/listeners/{externalId}", method=RequestMethod.DELETE)
public @ResponseBody
AjaxResponse<?> deleteListener(ModelMap model,
@PathVariable long externalId) {
CustomUserPrincipal userPrincipal = authenticationHelpers.getUserPrincipal();
UserSettings userSettings = userPrincipal.getUserSettings();
userSettings.removeListener(externalId);
return new AjaxResponse<String>(null, true);
}
これが問題に光を当てるのに役立つことを願っています!