Как использовать атрибуты сеанса в Spring-mvc

108

Не могли бы вы помочь мне написать аналог этого кода в стиле spring mvc?

 session.setAttribute("name","value");

А как добавить @ModelAttributeв сессию аннотированный аннотацией элемент и потом получить к нему доступ?

gstackoverflow
источник

Ответы:

185

Если вы хотите удалять объект после каждого ответа, вам не нужен сеанс,

Если вы хотите сохранить объект во время сеанса пользователя, есть несколько способов:

  1. напрямую добавить один атрибут в сеанс:

    @RequestMapping(method = RequestMethod.GET)
    public String testMestod(HttpServletRequest request){
       ShoppingCart cart = (ShoppingCart)request.getSession().setAttribute("cart",value);
       return "testJsp";
    }
    

    и вы можете получить его с контроллера следующим образом:

    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
  2. Сделайте сеанс контроллера ограниченным

    @Controller
    @Scope("session")
    
  3. Область действия объектов, например, у вас есть пользовательский объект, который должен быть в сеансе каждый раз:

    @Component
    @Scope("session")
    public class User
     {
        String user;
        /*  setter getter*/
      }
    

    затем введите класс в каждый контроллер, который вы хотите

       @Autowired
       private User user
    

    что держит класс на сеансе.

  4. Внедрение прокси AOP: в spring -xml:

    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
    
      <bean id="user"    class="com.User" scope="session">     
          <aop:scoped-proxy/>
      </bean>
    </beans>
    

    затем введите класс в каждый контроллер, который вы хотите

    @Autowired
    private User user
    

5. передать HttpSession в метод:

 String index(HttpSession session) {
            session.setAttribute("mySessionAttribute", "someValue");
            return "index";
        }

6.Создайте атрибут ModelAttribute в сеансе с помощью @SessionAttributes ("ShoppingCart"):

  public String index (@ModelAttribute("ShoppingCart") ShoppingCart shoppingCart, SessionStatus sessionStatus) {
//Spring V4
//you can modify session status  by sessionStatus.setComplete();
}

или вы можете добавить модель ко всему классу контроллера, например,

@Controller
    @SessionAttributes("ShoppingCart")
    @RequestMapping("/req")
    public class MYController {

        @ModelAttribute("ShoppingCart")
        public Visitor getShopCart (....) {
            return new ShoppingCart(....); //get From DB Or Session
        }  
      }

у каждого есть свои преимущества и недостатки:

@session может использовать больше памяти в облачных системах, он копирует сеанс на все узлы, а прямой метод (1 и 5) имеет беспорядочный подход, он не подходит для модульного тестирования.

Для доступа к сеансу jsp

<%=session.getAttribute("ShoppingCart.prop")%>

в Jstl:

<c:out value="${sessionScope.ShoppingCart.prop}"/>

в Тимелеафе:

<p th:text="${session.ShoppingCart.prop}" th:unless="${session == null}"> . </p>
Али.Мойтехеди
источник
6
3. Если ваш контроллер одноэлементный, вам необходимо определить proxyMode = ScopedProxyMode.TARGET_CLASS для внедренного компонента с областью сеанса. @Scope (value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
Вадим Колесников
1
Наихудший вариант здесь - сделать сеанс контроллера ограниченным, хотя сначала он выглядит простым и легким в использовании. Но если вы захотите масштабировать свое приложение когда-нибудь в будущем, вы столкнетесь с проблемами, поскольку вам, вероятно, понадобится распределенное хранилище сеансов, такое как Redis (если вы не используете липкие сеансы, жертвуя доступностью для удобства). Таким образом, bean-компоненты с ограниченным сеансом обычно должны быть тупыми сериализуемыми POJO. Таким образом, вы будете готовы к горизонтальному масштабированию в случае необходимости.
Крис
А как насчет RequestContextHolder?
user1589188
Внедрение Userbean-компонента будет работать только в том случае, если вы вызываете bean-компонент в классе, который также имеет sessionобласть видимости, в противном случае, если сеанс не существует, он выдает исключение, поскольку не будет активного сеанса в контексте @runtime, когда мы внедряем userbean-компонент в другой класс !!
Хосе Мхланга,
41

Использовать @SessionAttributes

См. Документы: Использование @SessionAttributes для хранения атрибутов модели в сеансе HTTP между запросами

« Понимание модели Spring MVC и атрибутов сеанса » также дает очень хороший обзор сеансов Spring MVC и объясняет, как / когда @ModelAttributeони передаются в сеанс (если контроллер @SessionAttributesаннотирован).

В этой статье также объясняется, что лучше использовать @SessionAttributesв модели вместо того, чтобы устанавливать атрибуты непосредственно в HttpSession, потому что это помогает Spring MVC быть независимым от просмотра.

Генрих Фильтр
источник
Как можно использовать атрибуты sessionAttributes для передачи объектов между контроллерами?
larrytech
27

SessionAttributeаннотация является наиболее простой и понятной вместо получения сеанса из объекта запроса и установки атрибута. Любой объект может быть добавлен в модель в контроллере, и он будет сохранен в сеансе, если его имя совпадает с аргументом в @SessionAttributesаннотации. Ниже, например, personObjбудет доступно в сеансе.

@Controller
@SessionAttributes("personObj")
public class PersonController {

    @RequestMapping(value="/person-form")
    public ModelAndView personPage() {
        return new ModelAndView("person-page", "person-entity", new Person());
    }

    @RequestMapping(value="/process-person")
    public ModelAndView processPerson(@ModelAttribute Person person) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("person-result-page");

        modelAndView.addObject("pers", person);
        modelAndView.addObject("personObj", person);

        return modelAndView;
    }

}
Амар
источник
сеансы работают только для запросов в одном экземпляре контроллера. Что делать, если необходимо передать управление другому контроллеру, этот сеанс будет уничтожен и при необходимости будет создан новый.
larrytech
1
@larrytech, как это могло быть? Я думаю, вы просто забыли добавить атрибуты SessionAttributes к своему второму контроллеру
Юра
19

В приведенном ниже аннотированном коде "value" будет установлено "name".

@RequestMapping("/testing")
@Controller
public class TestController {
@RequestMapping(method = RequestMethod.GET)
public String testMestod(HttpServletRequest request){
    request.getSession().setAttribute("name", "value");
    return "testJsp";
  }
}

Чтобы получить доступ к тому же используется JSP ${sessionScope.name}.

Для @ModelAttributeпросмотра этой ссылки

Аксаппи
источник
4

Разве это не самый простой и короткий путь? Я знал это и просто протестировал - здесь отлично работает:

@GetMapping
public String hello(HttpSession session) {
    session.setAttribute("name","value");
    return "hello";
}

ps Я пришел сюда в поисках ответа « Как использовать атрибуты сеанса в Spring-mvc », но прочитал так много, не увидев наиболее очевидного из того, что я написал в своем коде. Я не видел этого, поэтому подумал, что это неправильно, но нет, это не так. Итак, давайте поделимся этими знаниями и предложим самый простой ответ на главный вопрос.

суровый
источник
1
Ты прав ! это то, о чем я думал, поскольку вы можете получить доступ ко всем объектам Http, которые нам нужны напрямую, когда вы объявляете их в методах контроллера (запрос GET / POST)
Шесуки
1

Попробуй это...

@Controller
@RequestMapping("/owners/{ownerId}/pets/{petId}/edit")
@SessionAttributes("pet")
public class EditPetForm {

    @ModelAttribute("types")

    public Collection<PetType> populatePetTypes() {
        return this.clinic.getPetTypes();
    }

    @RequestMapping(method = RequestMethod.POST)
    public String processSubmit(@ModelAttribute("pet") Pet pet, 
            BindingResult result, SessionStatus status) {
        new PetValidator().validate(pet, result);
        if (result.hasErrors()) {
            return "petForm";
        }else {
            this.clinic.storePet(pet);
            status.setComplete();
            return "redirect:owner.do?ownerId="
                + pet.getOwner().getId();
        }
    }
}
R Паланивель-Тамилнад Индия
источник
0

Когда я пытаюсь войти в систему (что является модальной загрузкой), я использовал аннотацию @sessionattributes. Но проблема заключалась в том, что когда представление является перенаправленным ("redirect: / home"), значения, которые я ввел для сеанса, отображаются в URL-адресе. Некоторые источники в Интернете предлагают следовать http://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/htmlsingle/#mvc-redirecting Но вместо этого я использовал HttpSession. Этот сеанс будет там, пока вы не закроете браузеры. Вот пример кода

        @RequestMapping(value = "/login")
        @ResponseBody
        public BooleanResponse login(HttpSession session,HttpServletRequest request){
            //HttpServletRequest used to take data to the controller
            String username = request.getParameter("username");
            String password = request.getParameter("password");

           //Here you set your values to the session
           session.setAttribute("username", username);
           session.setAttribute("email", email);

          //your code goes here
}

Вы не меняете конкретную вещь на стороне просмотра.

<c:out value="${username}"></c:out>
<c:out value="${email}"></c:out>

После входа в систему добавьте указанные выше коды в любое место на своем веб-сайте. Если сеанс настроен правильно, вы увидите там значения. Убедитесь, что вы правильно добавили теги jstl и выражения El- (вот ссылка для установки тегов jstl https://menukablog.wordpress.com/2016/05/10/add-jstl-tab-library-to-you-project- правильно / )

Менука Ишан
источник
0

Использование Этот метод очень прост и удобен в использовании

HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getNativeRequest();

                                                            request.getSession().setAttribute("errorMsg", "your massage");

в jsp один раз использовать, затем удалить

<c:remove var="errorMsg" scope="session"/>      
Бача
источник
0

В Spring 4 Web MVC. Вы можете использовать @SessionAttributeметод @SessionAttributesна уровне контроллера

@Controller
@SessionAttributes("SessionKey")
public class OrderController extends BaseController {

    GetMapping("/showOrder")
    public String showPage(@SessionAttribute("SessionKey") SearchCriteria searchCriteria) {
     // method body
}
sendon1982
источник