Cómo usar los atributos de sesión en Spring-mvc

108

¿Podrías ayudarme a escribir un análogo de estilo Spring MVC de este código?

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

¿Y cómo agregar un elemento anotado por @ModelAttributeanotación a la sesión y luego obtener acceso a él?

gstackoverflow
fuente

Respuestas:

185

Si desea eliminar el objeto después de cada respuesta, no necesita sesión,

Si desea conservar el objeto durante la sesión del usuario, hay algunas formas:

  1. agregue directamente un atributo a la sesión:

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

    y puedes obtenerlo del controlador de esta manera:

    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
  2. Haga que su sesión de controlador tenga un alcance

    @Controller
    @Scope("session")
  3. Alcance los objetos, por ejemplo, tiene un objeto de usuario que debería estar en sesión cada vez:

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

    luego inyecta clase en cada controlador que quieras

       @Autowired
       private User user

    que mantiene la clase en sesión.

  4. La inyección de proxy AOP: en 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>

    luego inyecta clase en cada controlador que quieras

    @Autowired
    private User user

5.Pase HttpSession al método:

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

6.Haga ModelAttribute en sesión por @SessionAttributes ("ShoppingCart"):

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

o puede agregar el modelo a toda la clase de controlador como,

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

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

cada uno tiene ventajas y desventajas:

@session puede usar más memoria en los sistemas en la nube; copia la sesión en todos los nodos, y el método directo (1 y 5) tiene un enfoque desordenado, no es bueno para la prueba unitaria.

Para acceder a la sesión jsp

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

en Jstl:

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

en Thymeleaf:

<p th:text="${session.ShoppingCart.prop}" th:unless="${session == null}"> . </p>
Ali.Mojtehedy
fuente
6
3. Si su controlador es singleton, entonces necesita definir proxyMode = ScopedProxyMode.TARGET_CLASS para el componente inyectado con alcance de sesión. @Scope (value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
Vadim Kolesnikov
1
Hacer que la sesión del controlador tenga un alcance es la peor opción aquí, aunque parece simple y fácil de usar al principio. Pero si desea escalar su aplicación en algún momento en el futuro, tendrá problemas, ya que probablemente necesitará una tienda de sesiones distribuida como Redis (a menos que use sesiones fijas, sacrificando la disponibilidad por conveniencia). Por lo tanto, los beans con ámbito de sesión generalmente deberían ser POJO serializables tontos. De esta forma, estará preparado para la ampliación horizontal en caso de que surja la necesidad.
chris
¿Qué pasa con RequestContextHolder?
user1589188
Inyectar el Userbean solo funcionará si está llamando al bean en una clase que también tiene un sessionalcance, de lo contrario, si no existe una sesión, arroja una excepción, ya que no habría ninguna sesión activa en el contexto @runtime cuando inyectamos el userbean en otra clase !!
Jose Mhlanga
41

Utilizar @SessionAttributes

Consulte los documentos: Uso de @SessionAttributes para almacenar atributos de modelo en la sesión HTTP entre solicitudes

" Comprender los atributos de sesión y modelo de Spring MVC " también ofrece una muy buena descripción general de las sesiones de Spring MVC y explica cómo / cuándo @ModelAttributese transfieren los correos electrónicos a la sesión (si el controlador está @SessionAttributesanotado).

Ese artículo también explica que es mejor usarlo @SessionAttributesen el modelo en lugar de establecer atributos directamente en HttpSession porque eso ayuda a Spring MVC a ser independiente de la vista.

Filtro Heinrich
fuente
¿Cómo se pueden aprovechar los atributos de sesión para transferir objetos entre controladores?
larrytech
27

SessionAttributeLa anotación es la más simple y directa en lugar de obtener la sesión del objeto de solicitud y el atributo de configuración. Cualquier objeto se puede agregar al modelo en el controlador y se almacenará en la sesión si su nombre coincide con el argumento en la @SessionAttributesanotación. A continuación, por ejemplo, personObjestará disponible en sesión.

@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;
    }

}
Amar
fuente
las sesiones funcionan solo para solicitudes dentro de la misma instancia de controlador. ¿Qué pasa si el control debe enviarse a otro controlador, esta sesión se destruirá y se creará una nueva si es necesario?
larrytech
1
@larrytech ¿cómo podría ser? Creo que te has olvidado de agregar SessionAttributes a tu segundo controlador
Yura
19

El siguiente código anotado establecería "valor" en "nombre"

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

Para acceder al mismo en JSP, use ${sessionScope.name}.

Para @ModelAttributever este enlace

aksappy
fuente
4

¿No es así más fácil y más corto ? Lo sabía y lo probé, funcionando perfectamente aquí:

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

ps . Vine aquí buscando una respuesta de " Cómo usar los atributos de sesión en Spring-mvc ", pero leí tantos sin ver lo más obvio que había escrito en mi código. No lo vi, así que pensé que estaba mal, pero no, no lo estaba. Entonces, compartamos ese conocimiento con la solución más fácil para la pregunta principal.

strash
fuente
1
Tienes razón ! eso es lo que estaba pensando, ya que puede acceder a todos los objetos Http que necesitamos directamente cuando los declara en los métodos del controlador (solicitud GET / POST)
Shessuky
1

Prueba esto...

@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 Palanivel-Tamilnadu India
fuente
0

Cuando intenté iniciar sesión (que es un modal de arranque), utilicé la anotación @sessionattributes. Pero el problema fue cuando la vista es una redirección ("redirección: / home"), los valores que ingresé a la sesión se muestran en la URL. Algunas fuentes de Internet sugieren seguir http://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/htmlsingle/#mvc-redirecting Pero usé HttpSession en su lugar. Esta sesión estará ahí hasta que cierre los navegadores. Aquí hay un código de muestra

        @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
}

No cambia algo específico en el lado de la vista.

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

Después de iniciar sesión, agregue los códigos anteriores a cualquier lugar de su sitio web. Si la sesión está configurada correctamente, verá los valores allí. Asegúrese de haber agregado correctamente las etiquetas jstl y las expresiones El- (aquí hay un enlace para configurar las etiquetas jstl https://menukablog.wordpress.com/2016/05/10/add-jstl-tab-library-to-you-project- correctamente / )

Menuka Ishan
fuente
0

Utilice este método muy simple fácil de usar

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

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

en jsp una vez usar y luego eliminar

<c:remove var="errorMsg" scope="session"/>      
Bachas
fuente
0

En Spring 4 Web MVC. Puede usar @SessionAttributeen el método con @SessionAttributesnivel de controlador

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

    GetMapping("/showOrder")
    public String showPage(@SessionAttribute("SessionKey") SearchCriteria searchCriteria) {
     // method body
}
sendon1982
fuente