Як використовувати атрибути Session у Spring-mvc


108

Чи можете ви допомогти мені написати аналоговий код цього весняного стилю mvc?

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

І як додати @ModelAttributeдо сеансу елемент, який позначається анотацією, а потім отримати доступ до нього?

Відповіді:


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: навесні -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.Pass 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 (якщо ви не використовуєте клейкі сесії, жертвуючи доступністю для зручності). Таким чином, квасоля, яка охоплює сеанс, як правило, має бути тупими серійними POJO. Таким чином ви готуєтесь до масштабування у випадку необхідності.
chris

Що з RequestContextHolder?
користувач1589188

Ін'єкція Userbean працюватиме лише у тому випадку, якщо ви називаєте bean у класі tha, також встановлено sessionмасштаб, інакше якщо не існує сеансу, то це викине виняток, оскільки не було б жодного активного сеансу в контексті @runtime, коли ми вводимо userbean i інший клас !!
Хосе Мланга

41

Використовуйте @SessionAttributes

Див. Документи: Використання @SessionAttributes для зберігання атрибутів моделі в сеансі HTTP між запитами

" Розуміння весняних моделей MVC і атрибутів сеансу " також дає дуже хороший огляд весняних сеансів MVC та пояснює, як / коли @ModelAttributes передаються в сеанс (якщо контролер @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

Нижченаведений анотований код встановив би "значення" на "ім'я"

@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, які нам потрібні безпосередньо, коли ви оголосите їх методами Controller (GET / POST запит)
Shessuky

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();
        }
    }
}

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

Навесні 4 Веб MVC. Ви можете використовувати @SessionAttributeв методі з @SessionAttributesна рівні контролера

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

    GetMapping("/showOrder")
    public String showPage(@SessionAttribute("SessionKey") SearchCriteria searchCriteria) {
     // method body
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.