Como usar atributos de sessão no Spring-mvc

108

Você poderia me ajudar a escrever um análogo ao estilo Spring MVC deste código?

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

E como adicionar um elemento que é anotado por @ModelAttributeanotação à sessão e, em seguida, obter acesso a ele?

gstackoverflow
fonte

Respostas:

185

Se você deseja excluir o objeto após cada resposta, você não precisa da sessão,

Se você deseja manter o objeto durante a sessão do usuário, existem algumas maneiras:

  1. adicione diretamente um atributo à sessão:

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

    e você pode obtê-lo do controlador assim:

    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
  2. Faça sua sessão de controlador com escopo

    @Controller
    @Scope("session")
    
  3. Defina o escopo dos objetos, por exemplo, você tem um objeto de usuário que deve estar sempre em sessão:

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

    em seguida, injete classe em cada controlador que você deseja

       @Autowired
       private User user
    

    que mantém a aula na sessão.

  4. A injeção de proxy AOP: em 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>
    

    em seguida, injete classe em cada controlador que você deseja

    @Autowired
    private User user
    

5. Passe HttpSession para o método:

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

6. Faça ModelAttribute na sessão por @SessionAttributes ("ShoppingCart"):

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

ou você pode adicionar o modelo a toda classe 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 um tem vantagem e desvantagem:

@session pode usar mais memória em sistemas em nuvem, pois copia a sessão para todos os nós, e o método direto (1 e 5) tem uma abordagem confusa, não é bom para teste de unidade.

Para acessar a sessão jsp

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

em Jstl:

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

em Thymeleaf:

<p th:text="${session.ShoppingCart.prop}" th:unless="${session == null}"> . </p>
Ali.Mojtehedy
fonte
6
3. Se o seu controlador for singleton, você precisará definir proxyMode = ScopedProxyMode.TARGET_CLASS para o componente injetado com escopo de sessão. @Scope (value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
Vadim Kolesnikov
1
Definir o escopo da sessão do controlador é a pior opção aqui, embora pareça simples e fácil de usar no início. Mas se você quiser expandir seu aplicativo em algum momento no futuro, terá problemas, pois provavelmente precisará de um armazenamento de sessão distribuído como o Redis (a menos que use sessões fixas, sacrificando a disponibilidade por conveniência). Portanto, os beans com escopo de sessão geralmente devem ser POJOs serializáveis ​​burros. Dessa forma, você está preparado para escalar horizontalmente, caso haja necessidade.
chris
E sobre RequestContextHolder?
user1589188
Injetar o Userbean só funcionará se você estiver chamando o bean em uma classe que também tem sessionescopo, caso contrário, se não houver sessão, ele lançará uma exceção, pois não haveria nenhuma sessão ativa no contexto @runtime quando injetamos o userbean em outra classe !!
Jose Mhlanga
41

Usar @SessionAttributes

Veja os documentos: Usando @SessionAttributes para armazenar atributos de modelo na sessão HTTP entre solicitações

" Understanding Spring MVC Model and Session Attributes " também oferece uma visão geral muito boa das sessões do Spring MVC e explica como / quando @ModelAttributes são transferidos para a sessão (se o controlador estiver @SessionAttributesanotado).

Esse artigo também explica que é melhor usar @SessionAttributesno modelo em vez de definir atributos diretamente na HttpSession, porque isso ajuda o Spring MVC a ser agnóstico de visualização.

Filtro Heinrich
fonte
Como você pode aproveitar o sessionAttributes para transferir objetos entre os controladores?
Larrytech
27

SessionAttributea anotação é a mais simples e direta em vez de obter a sessão do objeto de solicitação e do atributo de configuração. Qualquer objeto pode ser adicionado ao modelo no controlador e será armazenado na sessão se seu nome corresponder ao argumento na @SessionAttributesanotação. Abaixo, por exemplo, personObjestará disponível na sessão.

@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
fonte
sessões funcionam apenas para solicitações dentro da mesma instância do controlador. E se o controle precisar ser enviado para outro controlador, esta sessão será destruída e uma nova será criada, se necessário.
Larrytech
1
@larrytech como poderia ser? Acho que você se esqueceu de adicionar SessionAttributes ao seu segundo controlador
Yura
19

O código anotado abaixo definiria "valor" para "nome"

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

Para acessar o mesmo em uso JSP ${sessionScope.name}.

Para @ModelAttributever este link

aksappy
fonte
4

Não é mais fácil e mais curto assim? Eu sabia e apenas testei - funcionando perfeitamente aqui:

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

ps Eu vim aqui procurando por uma resposta de " Como usar atributos de sessão no Spring-mvc ", mas li tantos sem ver o mais óbvio que eu havia escrito em meu código. Eu não vi, então pensei que era errado, mas não estava. Então, vamos compartilhar esse conhecimento com a solução mais fácil para a questão principal.

strash
fonte
1
Você está certo ! isso é o que eu estava pensando, já que você pode acessar todos os objetos Http que precisamos diretamente quando você os declara nos métodos do controlador (solicitação GET / POST)
Shessuky
1

Experimente isso ...

@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 Índia
fonte
0

Quando tento meu login (que é um modal de bootstrap), usei a anotação @sessionattributes. Mas o problema foi quando a view é um redirecionamento ("redirect: / home"), os valores que eu inseri na sessão mostram na url. Algumas fontes da Internet sugerem seguir http://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/htmlsingle/#mvc-redirecting Mas, em vez disso, usei HttpSession. Esta sessão estará lá até você fechar os navegadores. Aqui está um exemplo de código

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

Você não muda nada específico no lado da vista.

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

Após o login, adicione os códigos acima em qualquer lugar do seu site. Se a sessão for configurada corretamente, você verá os valores lá. Certifique-se de adicionar corretamente as tags jstl e as expressões El- (aqui está o link para definir as tags jstl https://menukablog.wordpress.com/2016/05/10/add-jstl-tab-library-to-you-project- corretamente / )

Menuka Ishan
fonte
0

Use este método muito simples fácil de usar

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

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

no jsp uma vez, use e depois remova

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

No Spring 4 Web MVC. Você pode usar @SessionAttributeno método @SessionAttributesem nível de controlador

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

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