Cara menggunakan atribut Sesi di Spring-mvc

108

Bisakah Anda membantu saya menulis analog gaya mvc musim semi dari kode ini?

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

Dan bagaimana cara menambahkan elemen yang dianotasi oleh @ModelAttributeanotasi ke sesi dan kemudian mendapatkan akses ke sana?

gstackoverflow
sumber

Jawaban:

185

Jika Anda ingin menghapus objek setelah setiap respons Anda tidak memerlukan sesi,

Jika Anda ingin menyimpan objek selama sesi pengguna, Ada beberapa cara:

  1. langsung menambahkan satu atribut ke sesi:

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

    dan Anda bisa mendapatkannya dari pengontrol seperti ini:

    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
  2. Jadikan sesi pengontrol Anda tercakup

    @Controller
    @Scope("session")
    
  3. Cakupan Objek, misalnya Anda memiliki objek pengguna yang harus berada dalam sesi setiap saat:

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

    lalu masukkan kelas di setiap pengontrol yang Anda inginkan

       @Autowired
       private User user
    

    yang membuat kelas tetap dalam sesi.

  4. Injeksi proxy AOP: di musim semi -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>
    

    lalu masukkan kelas di setiap pengontrol yang Anda inginkan

    @Autowired
    private User user
    

5. Lewati HttpSession ke metode:

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

6. Buat ModelAttribute di sesi Dengan @SessionAttributes ("ShoppingCart"):

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

atau Anda dapat menambahkan Model Ke seluruh Kelas Pengontrol seperti,

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

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

masing-masing memiliki kelebihan dan kekurangan:

@session dapat menggunakan lebih banyak memori dalam sistem cloud itu menyalin sesi ke semua node, dan metode langsung (1 dan 5) memiliki pendekatan yang berantakan, tidak baik untuk pengujian unit.

Untuk mengakses sesi jsp

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

di Jstl:

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

di Thymeleaf:

<p th:text="${session.ShoppingCart.prop}" th:unless="${session == null}"> . </p>
Ali.Mojtehedy
sumber
6
3. Jika pengontrol Anda tunggal maka Anda perlu mendefinisikan proxyMode = ScopedProxyMode.TARGET_CLASS untuk komponen yang diinjeksi dengan cakupan sesi. @Scope (nilai = "sesi", proxyMode = ScopedProxyMode.TARGET_CLASS)
Vadim Kolesnikov
1
Membuat sesi pengontrol tercakup adalah opsi terburuk di sini, meskipun terlihat sederhana dan mudah digunakan pada awalnya. Tetapi jika Anda ingin menskalakan aplikasi Anda di masa mendatang, Anda akan mengalami masalah karena Anda mungkin memerlukan penyimpanan sesi terdistribusi seperti Redis (kecuali jika Anda menggunakan sesi lengket, mengorbankan ketersediaan untuk kenyamanan). Jadi, kacang dengan cakupan sesi umumnya harus menjadi POJO serial yang bodoh. Dengan cara ini Anda siap untuk melakukan penskalaan jika diperlukan.
chris
Bagaimana dengan RequestContextHolder?
pengguna1589188
Menyuntikkan Userkacang hanya akan berfungsi jika Anda memanggil kacang di kelas yang juga memiliki sessioncakupan, jika tidak, jika tidak ada sesi maka ia akan mengeluarkan pengecualian karena tidak akan ada sesi aktif dalam konteks @runtime saat kita menyuntikkan userkacang di kelas lain !!
Jose Mhlanga
41

Menggunakan @SessionAttributes

Lihat dokumen: Menggunakan @SessionAttributes untuk menyimpan atribut model dalam sesi HTTP di antara permintaan

" Memahami Atribut Sesi Model dan Model MVC Musim Semi " juga memberikan gambaran umum yang sangat bagus tentang sesi MVC Musim Semi dan menjelaskan bagaimana / kapan @ModelAttributes ditransfer ke sesi (jika pengontrol @SessionAttributesdiberi keterangan).

Artikel itu juga menjelaskan bahwa lebih baik menggunakan @SessionAttributesmodel daripada menyetel atribut secara langsung di HttpSession karena itu membantu Spring MVC menjadi view-agnostic.

Filter Heinrich
sumber
Bagaimana Anda memanfaatkan sessionAttributes untuk mentransfer objek antara Pengontrol?
larrytech
27

SessionAttributeanotasi adalah yang paling sederhana dan langsung daripada mendapatkan sesi dari objek permintaan dan atribut pengaturan. Objek apa pun dapat ditambahkan ke model di controller dan itu akan disimpan dalam sesi jika namanya cocok dengan argumen di @SessionAttributesanotasi. Di bawah ini misalnya, personObjakan tersedia dalam sesi.

@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
sumber
sesi bekerja hanya untuk permintaan dalam contoh pengontrol yang sama. Bagaimana jika kontrol perlu dikirim ke pengontrol lain, sesi ini akan dihancurkan dan yang baru dibuat jika perlu.
larrytech
1
@larrytech bagaimana mungkin? Saya pikir Anda baru saja lupa menambahkan SessionAttributes ke pengontrol kedua Anda
Yura
19

Kode yang dianotasi di bawah ini akan menetapkan "nilai" menjadi "nama"

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

Untuk mengakses yang sama dalam penggunaan JSP ${sessionScope.name}.

Untuk @ModelAttributemelihat tautan ini

aksappy
sumber
4

Bukankah itu termudah dan terpendek seperti itu? Saya mengetahuinya dan baru saja mengujinya - bekerja sempurna di sini:

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

ps Saya datang ke sini mencari jawaban dari " Bagaimana menggunakan atribut Sesi di Spring-mvc ", tetapi membaca begitu banyak tanpa melihat yang paling jelas yang telah saya tulis di kode saya. Saya tidak melihatnya, jadi saya pikir itu salah, tapi ternyata tidak. Jadi, mari berbagi pengetahuan itu dengan solusi termudah untuk pertanyaan utama.

strash
sumber
1
Kamu benar ! itulah yang saya pikirkan karena Anda dapat mengakses semua objek Http yang kami butuhkan secara langsung ketika Anda mendeklarasikannya dalam metode Controller (GET / permintaan POST)
Shessuky
1

Coba ini...

@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
sumber
0

Ketika saya mencoba login saya (yang merupakan modal bootstrap), saya menggunakan anotasi @sessionattributes. Tetapi masalahnya adalah ketika tampilan adalah pengalihan ("redirect: / home"), nilai yang saya masukkan ke sesi ditampilkan di url. Beberapa sumber Internet menyarankan untuk mengikuti http://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/htmlsingle/#mvc-redirecting Tetapi saya menggunakan HttpSession sebagai gantinya. Sesi ini akan ada sampai Anda menutup browser. Berikut adalah contoh kode

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

Anda tidak mengubah hal tertentu di sisi tampilan.

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

Setelah login tambahkan kode di atas ke sembarang tempat di situs web Anda. Jika sesi disetel dengan benar, Anda akan melihat nilai di sana. Pastikan Anda menambahkan tag jstl dan ekspresi El dengan benar (Ini adalah tautan untuk menyetel tag jstl https://menukablog.wordpress.com/2016/05/10/add-jstl-tab-library-to-you-project- benar / )

Menuka Ishan
sumber
0

Gunakan Metode ini sangat sederhana dan mudah digunakan

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

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

di jsp sekali pakai lalu angkat

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

Di Spring 4 Web MVC. Anda dapat menggunakan @SessionAttributemetode ini dengan @SessionAttributesdi level Controller

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

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