Cách sử dụng thuộc tính Session trong Spring-mvc


108

Bạn có thể giúp tôi viết tương tự phong cách mùa xuân mvc của mã này?

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

Và làm thế nào để thêm một phần tử được chú thích bởi @ModelAttributechú thích vào phiên và sau đó có quyền truy cập vào nó?

Câu trả lời:


185

Nếu bạn muốn xóa đối tượng sau mỗi phản hồi mà bạn không cần phiên,

Nếu bạn muốn giữ đối tượng trong phiên người dùng, có một số cách:

  1. thêm trực tiếp một thuộc tính vào phiên:

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

    và bạn có thể lấy nó từ bộ điều khiển như sau:

    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
  2. Làm cho phiên điều khiển của bạn có phạm vi

    @Controller
    @Scope("session")
  3. Phạm vi đối tượng, ví dụ: bạn có đối tượng người dùng phải có trong phiên mọi lúc:

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

    sau đó đưa lớp vào từng bộ điều khiển mà bạn muốn

       @Autowired
       private User user

    để giữ cho lớp học đúng phiên.

  4. Chèn proxy AOP: trong 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>

    sau đó đưa lớp vào từng bộ điều khiển mà bạn muốn

    @Autowired
    private User user

5.Pass HttpSession đến phương thức:

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

6. Tạo ModelAttribute trong phiên bởi @SessionAttributes ("ShoppingCart"):

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

hoặc bạn có thể thêm Model vào toàn bộ Lớp điều khiển như,

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

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

mỗi cái đều có ưu điểm và nhược điểm:

@session có thể sử dụng nhiều bộ nhớ hơn trong các hệ thống đám mây, nó sao chép phiên tới tất cả các nút và phương pháp trực tiếp (1 và 5) có cách tiếp cận lộn xộn, không tốt cho kiểm thử đơn vị.

Để truy cập jsp phiên

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

trong Jstl:

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

trong Thymeleaf:

<p th:text="${session.ShoppingCart.prop}" th:unless="${session == null}"> . </p>

6
3. Nếu bộ điều khiển của bạn là singleton thì bạn cần định nghĩa proxyMode = ScopedProxyMode.TARGET_CLASS cho thành phần được chèn với phạm vi phiên. @Scope (value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
Vadim Kolesnikov

1
Làm cho phạm vi phiên điều khiển là tùy chọn tồi tệ nhất ở đây, mặc dù ban đầu nó trông đơn giản và dễ sử dụng. Nhưng nếu bạn muốn mở rộng ứng dụng của mình một thời gian nào đó trong tương lai, bạn sẽ gặp rắc rối vì có thể bạn sẽ cần một cửa hàng phiên phân tán như Redis (trừ khi bạn sử dụng phiên cố định, hy sinh tính khả dụng để thuận tiện). Do đó, các bean theo phạm vi phiên thường phải là các POJO có thể tuần tự hóa ngu ngốc. Bằng cách này, bạn có thể chuẩn bị cho việc mở rộng quy mô trong trường hợp cần thiết.
chris

Còn RequestContextHolder thì sao?
user1589188

Việc tiêm Userbean sẽ chỉ hoạt động nếu bạn đang gọi bean trong một lớp cũng được sessionxác định phạm vi, ngược lại nếu không có phiên nào tồn tại thì nó sẽ ném ra ngoại lệ vì sẽ không có bất kỳ phiên hoạt động nào trong ngữ cảnh @runtime khi chúng ta tiêm userbean vào một lớp khác !!
Jose Mhlanga

41

Sử dụng @SessionAttributes

Xem tài liệu: Sử dụng @SessionAttributes để lưu trữ các thuộc tính mô hình trong phiên HTTP giữa các yêu cầu

" Hiểu mô hình Spring MVC và các thuộc tính phiên " cũng cung cấp một cái nhìn tổng quan rất tốt về các phiên Spring MVC và giải thích cách / khi nào @ModelAttributecác s được chuyển vào phiên (nếu bộ điều khiển được @SessionAttributeschú thích).

Bài báo đó cũng giải thích rằng tốt hơn nên sử dụng @SessionAttributestrên mô hình thay vì đặt các thuộc tính trực tiếp trên HttpSession vì điều đó giúp Spring MVC trở nên bất khả tri về chế độ xem.


Làm thế nào bạn có thể tận dụng sessionAttributes để chuyển các đối tượng giữa các Bộ điều khiển?
larrytech

27

SessionAttributechú thích là cách đơn giản nhất và chuyển tiếp thay vì nhận phiên từ đối tượng yêu cầu và thuộc tính cài đặt. Bất kỳ đối tượng nào cũng có thể được thêm vào mô hình trong bộ điều khiển và nó sẽ được lưu trữ trong phiên nếu tên của nó khớp với đối số trong @SessionAttributeschú thích. Trong ví dụ dưới đây, personObjsẽ có sẵn trong phiê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;
    }

}

phiên hoạt động chỉ cho các yêu cầu trong cùng một phiên bản trình điều khiển. Điều gì sẽ xảy ra nếu điều khiển cần được gửi đến một bộ điều khiển khác, phiên này sẽ bị hủy và một phiên mới được tạo nếu cần thiết.
larrytech

1
@larrytech sao có thể vậy? Tôi nghĩ bạn vừa quên thêm SessionAttributes vào bộ điều khiển thứ hai của mình
Yura

19

Mã chú thích bên dưới sẽ đặt "giá trị" thành "tên"

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

Để truy cập giống nhau trong sử dụng JSP ${sessionScope.name}.

Để @ModelAttributexem liên kết này


4

Đó không phải là cách dễ nhất và ngắn nhất sao? Tôi biết điều đó và chỉ thử nghiệm nó - hoạt động hoàn hảo ở đây:

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

ps Tôi đến đây để tìm kiếm câu trả lời về " Cách sử dụng thuộc tính Session trong Spring-mvc ", nhưng đọc quá nhiều mà không thấy rõ ràng nhất mà tôi đã viết trong mã của mình. Tôi không nhìn thấy nó, vì vậy tôi nghĩ nó sai, nhưng không, không phải vậy. Vì vậy, hãy chia sẻ kiến ​​thức đó với giải pháp dễ nhất cho câu hỏi chính.


1
Bạn đúng ! đó là những gì tôi đã suy nghĩ vì bạn có thể acess tất cả Http đối tượng mà chúng ta cần phải trực tiếp khi bạn khai báo chúng trong các phương pháp điều khiển (GET / POST yêu cầu)
Shessuky

1

Thử cái này...

@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

Khi tôi cố gắng đăng nhập (là một phương thức bootstrap), tôi đã sử dụng chú thích @sessionattributes. Nhưng vấn đề là khi chế độ xem là một chuyển hướng ("redirect: / home"), các giá trị tôi đã nhập vào phiên hiển thị trong url. Một số nguồn Internet khuyên bạn nên làm theo http://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/htmlsingle/#mvc-redirecting Nhưng thay vào đó tôi đã sử dụng HttpSession. Phiên này sẽ ở đó cho đến khi bạn đóng trình duyệt. Đây là mã mẫu

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

Bạn không thay đổi điều cụ thể về mặt xem.

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

Sau khi đăng nhập, hãy thêm các mã trên vào bất kỳ nơi nào trong trang web của bạn. Nếu phiên được đặt chính xác, bạn sẽ thấy các giá trị ở đó. Đảm bảo bạn đã thêm chính xác thẻ jstl và biểu thức El- (Đây là liên kết để đặt thẻ jstl https://menukablog.wordpress.com/2016/05/10/add-jstl-tab-library-to-you-project- chính xác / )


0

Sử dụng Phương pháp này rất đơn giản dễ sử dụng

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

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

trong jsp một lần sử dụng sau đó loại bỏ

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

0

Trong Spring 4 Web MVC. Bạn có thể sử dụng @SessionAttributetrong phương pháp với @SessionAttributesở cấp Bộ điều khiển

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

    GetMapping("/showOrder")
    public String showPage(@SessionAttribute("SessionKey") SearchCriteria searchCriteria) {
     // method body
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.