Я использую @SessionAttributes на 2 контроллерах и испытываю некоторые очень странные действия. Мой первый контроллер (ViewController) - это просто контроллер представления, который отображает страницы JSP. Другой - контроллер, который обрабатывает запросы Ajax (AjaxController). У меня есть атрибут сеанса, который является просто объектом, который имеет HashMap в качестве члена. Объект является оберткой вокруг карты. Карта заполняется из базы данных и помещается в сеанс, который отлично отображается через ViewController. Однако, когда я делаю удаление с карты с помощью ajax-запроса (AjaxController) и обновляю страницу, ViewController SOMETIMES показывает, что элемент удален, но в остальное время элемент все еще существует. Вот фрагменты кода:Strange Spring @SessionAttributes Behavior
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 в один и тот же контроллер и испытал такое же поведение.
Спасибо за помощь!
EDIT:
Я переработан мой код немного, чтобы использовать UserPrincipal через springsecurity. Я понимаю, что этот объект хранится в сеансе. Несмотря ни на что, я вижу точно такое же поведение.
Вот конструктор UserPrincipal, который заполняет карту пользовательских настроек. Я установил контрольные точки здесь, чтобы убедиться, что установлены правильные listenerDBOs - они есть, каждый раз. Это единственный раз, когда слушатели получают из db в объект UserSettings в CustomUserPrincipal. Все остальные добавляет/удаляет выполняются с помощью контроллеров (быстро в сторону: не прибавляет не подведет ... только удаляет):
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 объективистского т вместо @SessionAttributes:
В 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="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, поэтому что-то, помеченное как @SessionAttributes в контроллере1, недоступно в контроллере2 и наоборот. Для этого вам придется вручную вводить материал в сеанс». -из ссылки выше –