วิธีใช้แอตทริบิวต์เซสชันใน 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. ผ่าน HttpSession ไปที่ method:

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

หรือคุณสามารถเพิ่ม Model ให้กับ Controller Class ทั้งหมดเช่น

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

ใน Thymeleaf:

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

6
3. หากคอนโทรลเลอร์ของคุณเป็นแบบซิงเกิลตันคุณต้องกำหนด proxyMode = ScopedProxyMode.TARGET_CLASS สำหรับคอมโพเนนต์ที่แทรกด้วยขอบเขตเซสชัน @Scope (value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
Vadim Kolesnikov

1
การกำหนดขอบเขตเซสชันคอนโทรลเลอร์เป็นตัวเลือกที่แย่ที่สุดที่นี่แม้ว่าจะดูเรียบง่ายและใช้งานง่ายในตอนแรก แต่ถ้าคุณต้องการปรับขนาดแอปพลิเคชันของคุณออกไปสักระยะในอนาคตคุณจะประสบปัญหาเนื่องจากคุณอาจต้องใช้ที่เก็บเซสชันแบบกระจายเช่น Redis (เว้นแต่คุณจะใช้เซสชันที่เหนียวเหนอะหนะโดยเสียสละความพร้อมใช้งานเพื่อความสะดวก) ดังนั้นโดยทั่วไปถั่วที่กำหนดขอบเขตเซสชันควรเป็น POJO ที่ต่ออนุกรมกันได้ ด้วยวิธีนี้คุณจะเตรียมพร้อมสำหรับการลดขนาดในกรณีที่จำเป็น
chris

RequestContextHolder เกี่ยวกับอะไร
user1589188

การฉีดUserbean จะใช้ได้ผลก็ต่อเมื่อคุณเรียก bean ในคลาส tha ก็ถูกsessionกำหนดขอบเขตไว้เช่นกันมิฉะนั้นหากไม่มีเซสชันจะแสดงข้อยกเว้นเนื่องจากจะไม่มีเซสชันที่ใช้งานอยู่ในบริบท @runtime เมื่อเราฉีดuserbean i คลาสอื่น !!
Jose Mhlanga

41

ใช้ @SessionAttributes

ดูเอกสาร: การใช้ @SessionAttributes เพื่อจัดเก็บแอตทริบิวต์โมเดลในเซสชัน HTTP ระหว่างคำขอ

"การทำความเข้าใจ Spring MVC Model และ Session Attributes " ยังให้ภาพรวมที่ดีมากของเซสชัน Spring MVC และอธิบายถึงวิธี / เวลา@ModelAttributeที่จะถ่ายโอนไปยังเซสชัน (หากมีการ@SessionAttributesใส่คำอธิบายประกอบตัวควบคุม)

บทความนั้นยังอธิบายด้วยว่าควรใช้@SessionAttributesกับแบบจำลองแทนการตั้งค่าแอตทริบิวต์โดยตรงบน HttpSession เนื่องจากจะช่วยให้ Spring MVC ไม่เชื่อเรื่องพระเจ้า


คุณจะใช้ประโยชน์จาก sessionAttributes เพื่อถ่ายโอนวัตถุระหว่าง Controllers ได้อย่างไร?
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 ไปยังคอนโทรลเลอร์ตัวที่สองของคุณ
Yura

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

${sessionScope.name}ในการเข้าถึงการเดียวกันในการใช้ JSP

สำหรับ@ModelAttributeเห็นนี้การเชื่อมโยง


4

มันง่ายและสั้นที่สุดไม่ใช่เหรอ? ฉันรู้แล้วและเพิ่งทดสอบ - ทำงานได้อย่างสมบูรณ์แบบที่นี่:

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

ps ฉันมาที่นี่เพื่อค้นหาคำตอบของ " วิธีใช้แอตทริบิวต์เซสชันใน Spring-mvc " แต่อ่านจำนวนมากโดยไม่เห็นชัดเจนที่สุดว่าฉันเขียนในโค้ดของฉัน ฉันไม่เห็นมันดังนั้นฉันคิดว่ามันผิด แต่ไม่มันไม่ใช่ ดังนั้นมาแบ่งปันความรู้นั้นพร้อมกับวิธีแก้ปัญหาที่ง่ายที่สุดสำหรับคำถามหลัก


1
คุณถูก ! นั่นคือสิ่งที่ฉันคิดเนื่องจากคุณสามารถเข้าถึงวัตถุ Http ทั้งหมดที่เราต้องการได้โดยตรงเมื่อคุณประกาศในวิธีการควบคุม (คำขอ 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

เมื่อฉันพยายามเข้าสู่ระบบ (ซึ่งเป็นโมดอล bootstrap) ฉันใช้คำอธิบายประกอบ @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
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.