我在2控制器上使用@SessionAttributes,並遇到一些非常奇怪的行爲。我的第一個控制器(ViewController)只是一個顯示JSP頁面的視圖控制器。另一個是處理Ajax請求的控制器(AjaxController)。我有一個會話屬性,它只是一個HashMap作爲成員的對象。該對象是地圖周圍的包裝。該映射從數據庫填充並放入會話中,該會話通過ViewController顯示正常。但是,當我通過ajax請求(AjaxController)從地圖中刪除並刷新頁面時,ViewController SOMETIMES顯示該元素已被刪除,但其他時間元素仍然存在。這裏的代碼片段:奇怪的春天@SessionAttributes行爲
的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";
}
}
AjaxController包含地圖的內容:
@Controller
@SessionAttributes({"userSettings"})
public class AjaxController {
@RequestMapping(value="https://stackoverflow.com/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被設置 - 每次都是這樣。這是偵聽器唯一一次從數據庫設置到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);
}
}
這是輔助功能UserSettingsAdapter類,增加了UserSettings對象,從CustomUserDetails構造函數調用:
public static void addListeners(Set<UserListenerDBO> userListeners, UserSettings userSettings) {
for (UserListenerDBO userListenerDBO : userListeners) {
if (userListenerDBO.isActive()) {
addListener(userListenerDBO, userSettings);
}
}
}
我也改變了控制器代碼用戶CustomUserPrincipal objec的T代替@SessionAttributes:
在視圖控制器:
@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="https://stackoverflow.com/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);
}
我希望這有助於闡明這個問題一些輕!
[@SessionAttributes問題(http://forum.springsource.org/showthread.php?49396-SessionAttribute-problems),你可能想看看這個 –
感謝鏈接。事情就是,線程說@SessionAttributes工作的方式與我所看到的行爲不同。該對象在兩個控制器中,但是當我通過userSettings.removeSetting(..)刪除設置時,它有時會刪除,有時不會。 – threejeez
「每個控制器都有它自己的ModelMap,因此控制器2中沒有可用的控制器1中的@SessionAttributes,反之亦然。爲此,您必須自己手動將這些內容放在會話中。」 - 從上面的鏈接 –