Preface
Starting with Spring MVC, session has recently been used to login to the company's system.
I have found a lot of information on the Internet, and I have roughly mentioned two ways to save session s:
1. Common HTTP Session for Java Web Engineering
2. Spring MVC-specific @SessionAttributes
Personally, I'm concerned about the use of @Session Attributes. After all, Spring MVC is now in use. But when I look at the articles on the Internet, they basically only explain the basic usage, but the detailed usage and details are basically not there. I think this is not enough, so I did some tests myself, and then I sorted out the next code to do a demo, record and share, what are the shortcomings of welcome to discuss.
Okay, that's all the crap. Now the main play begins!
conclusion
Well, in order to save some clients who don't like to read the code from the trouble of looking over the conclusions, I'll first list the conclusions after my tests.
1. Data can be automatically saved to session in Controller through Spring MVC's unique ModelMap and Model, or session data can be saved through traditional HttpSession and other parameters.
2. To save session data, you must use the @SessionAttributes annotation, which has two parameter declarations (value and types), and the annotation declaration must be written on the class, not on the method.
3. The saved session data must correspond to the list of parameters in the @SessionAttributes annotation. Undeclared parameters cannot be saved in session.
4. Session Statues can be used to clear the data saved in the session. It should be noted that all the data saved in the session can not be deleted separately. At the same time, the valid permission at the time of clearance follows the above rules 2 and 3 (by borrowing this rule, the effect of deleting specified session data can be achieved artificially)
5. When reading session data through ModelMap and so on, there are also the above-mentioned parameter permission restrictions.
6. When using ModelMap or Model to save session data, ModelMap must be passed in as a method parameter, and the new definition of the method is invalid. At the same time, as long as the ModelMap is passed in as a parameter, it will work even if it is called by other methods.
7. When using the @ResponseBody annotation (commonly used with ajax), session data cannot be saved
8. @SessionAttributes annotations can use two parameter lists, value and types
9. The traditional way of using HttpSession has no restrictions such as the annotations and permissions mentioned above. Here is a simple test, but no specific explanation is given.
Here are a few more common sense points
10. Operating session data can be cross-class and has nothing to do with the path of a package or url, etc.
11. Operating on the same session value, the following values will override the previous values
Test Code and Simple Description
Development tools: Spring Tool Suite.
spring is an Eclipse-based IDE development tool for spring MVC, which integrates Maven and Tomcat. It has been used recently and feels good. I recommend it.
Let's start with a screenshot of the project structure.
Because the @ResponseBody annotation for ajax is used in later tests, you configure the jar package in the pom.xml file.
<!-- Use@ResponseBody Two packages required for annotations --> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-core-asl</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.9.13</version> </dependency>
Here are the main test codes
1 package test.dmh.session; 2 3 import java.util.Enumeration; 4 5 import javax.servlet.http.HttpSession; 6 7 import org.slf4j.Logger; 8 import org.slf4j.LoggerFactory; 9 import org.springframework.stereotype.Controller; 10 import org.springframework.ui.Model; 11 import org.springframework.ui.ModelMap; 12 import org.springframework.web.bind.annotation.RequestMapping; 13 import org.springframework.web.bind.annotation.SessionAttributes; 14 import org.springframework.web.bind.support.SessionStatus; 15 16 /** 17 * @SessionAttributes Only parameter test1 is declared 18 */ 19 @Controller 20 @SessionAttributes(value={"test1"}) 21 public class HomeController { 22 23 private static final Logger logger = LoggerFactory.getLogger(HomeController.class); 24 25 @RequestMapping(value = "/show1") 26 public String show(ModelMap modelMap, HttpSession session) { 27 logger.info("show session"); 28 for (Object key : modelMap.keySet()) { 29 Object value = modelMap.get(key); 30 System.out.println(key + " = " + value); 31 } 32 System.out.println("***********************************"); 33 Enumeration<String> e = session.getAttributeNames(); 34 while (e.hasMoreElements()) { 35 String s = e.nextElement(); 36 System.out.println(s + " == " + session.getAttribute(s)); 37 } 38 System.out.println("***********************************"); 39 return "home"; 40 } 41 42 @RequestMapping("/set1") 43 public String setSession(ModelMap modelMap) { 44 logger.info("set session 1"); 45 modelMap.addAttribute("test1", "value 1"); //Set one to be in the ____________@SessionAttributes Parameters declared in 46 modelMap.addAttribute("test2", "value 2"); //Set an absent@SessionAttributes Parameters declared in 47 return "home"; 48 } 49 50 @RequestMapping("/setM") 51 public String setSessionM(Model model) { 52 logger.info("set session 1"); 53 model.addAttribute("test1", "value 1"); //Set one to be in the ____________@SessionAttributes Parameters declared in 54 model.addAttribute("test2", "value 2"); //Set an absent@SessionAttributes Parameters declared in 55 return "home"; 56 } 57 58 @RequestMapping("/clear1") 59 public String clear(SessionStatus status) { 60 logger.info("clear session 1"); 61 status.setComplete(); 62 return "home"; 63 } 64 65 }
1 package test.dmh.session.controller; 2 3 import javax.servlet.http.HttpSession; 4 5 import org.slf4j.Logger; 6 import org.slf4j.LoggerFactory; 7 import org.springframework.stereotype.Controller; 8 import org.springframework.ui.ModelMap; 9 import org.springframework.web.bind.annotation.RequestMapping; 10 11 /** 12 * No @SessionAttributes annotation was used 13 */ 14 @Controller 15 public class IndexController { 16 17 private static final Logger logger = LoggerFactory.getLogger(IndexController.class); 18 19 @RequestMapping("/set2") 20 public String setSession(ModelMap modelMap, HttpSession session) { 21 logger.info("set session 2 : without @SessionAttributes"); 22 modelMap.addAttribute("test3", "value 3"); 23 session.setAttribute("test4", "value 4"); 24 return "home"; 25 } 26 27 }
1 package test.dmh.session.controller; 2 3 import java.util.Enumeration; 4 import java.util.HashMap; 5 import java.util.Map; 6 7 import javax.servlet.http.HttpSession; 8 9 import org.slf4j.Logger; 10 import org.slf4j.LoggerFactory; 11 import org.springframework.stereotype.Controller; 12 import org.springframework.ui.ModelMap; 13 import org.springframework.web.bind.annotation.RequestMapping; 14 import org.springframework.web.bind.annotation.ResponseBody; 15 import org.springframework.web.bind.annotation.SessionAttributes; 16 import org.springframework.web.bind.support.SessionStatus; 17 18 @Controller 19 @SessionAttributes(value={"test5", "index"}) 20 public class IndexController2 { 21 22 private static final Logger logger = LoggerFactory.getLogger(IndexController2.class); 23 24 @RequestMapping("/set3") 25 public String setSession(ModelMap modelMap, HttpSession session) { 26 logger.info("set session 3"); 27 modelMap.addAttribute("test5", "value 5"); 28 session.setAttribute("test6", "value 6"); 29 30 ModelMap map = new ModelMap(); 31 map.addAttribute("test7", "value 7"); 32 33 this.setValueToSession(modelMap, session, "Hello World"); 34 35 return "home"; 36 } 37 38 @ResponseBody 39 @RequestMapping(value="/login") 40 public Map<String, Object> login(ModelMap modelMap, HttpSession session) { 41 logger.info("login"); 42 43 Map<String, Object> map = new HashMap<String, Object>(); 44 45 map.put("success", true); 46 map.put("info", "Log in successfully!"); 47 48 modelMap.addAttribute("testAjax", "test ajax value"); 49 session.setAttribute("httpTestAjax", "http test ajax Value"); 50 51 setValueToSession(modelMap, session, "This is Ajax"); 52 53 return map; 54 } 55 56 private void setValueToSession(ModelMap modelMap, HttpSession session, String value) { 57 logger.info("set session private"); 58 modelMap.addAttribute("index", value); 59 session.setAttribute("httpIndex", value); 60 } 61 62 @RequestMapping("/clear2") 63 public String clear(SessionStatus status) { 64 logger.info("clear session 2"); 65 status.setComplete(); 66 return "home"; 67 } 68 69 @RequestMapping(value = "/show2") 70 public String show(ModelMap modelMap, HttpSession session) { 71 logger.info("show session"); 72 for (Object key : modelMap.keySet()) { 73 Object value = modelMap.get(key); 74 System.out.println(key + " = " + value); 75 } 76 System.out.println("***********************************"); 77 Enumeration<String> e = session.getAttributeNames(); 78 while (e.hasMoreElements()) { 79 String s = e.nextElement(); 80 System.out.println(s + " == " + session.getAttribute(s)); 81 } 82 System.out.println("***********************************"); 83 return "home"; 84 } 85 86 }
If it's also a STS project like me, the default jsp file will have configuration <%@ page session= "false"%> and must be deleted or commented out. Otherwise, you can't display the data in the session on the page. Of course, it's also possible to look directly at the background code through the / show test I wrote here.
1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 2 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 3 4 <html> 5 <head> 6 <title>Home</title> 7 </head> 8 <body> 9 <h1> 10 Hello world! 11 </h1> 12 13 <p> The test1 is ${sessionScope.test1}. </p> 14 <p> The test2 is ${sessionScope.test2}. </p> 15 <p> The test3 is ${sessionScope.test3}. </p> 16 <p> The test4 is ${sessionScope.test4}. </p> 17 <p> The test5 is ${sessionScope.test5}. </p> 18 <p> The test6 is ${sessionScope.test6}. </p> 19 <p> The test7 is ${sessionScope.test7}. </p> 20 <p> The index is ${sessionScope.index}. </p> 21 <p> The httpIndex is ${sessionScope.httpIndex}. </p> 22 23 <br> 24 <input type="button" value="test" onclick="test();"> 25 26 <script src="resources/js/jquery.min.js"></script> 27 <script type="text/javascript"> 28 function test() { 29 $.ajax({ 30 type : "POST", 31 url : "login", 32 dataType : "json", 33 success : function(data) { 34 console.log(data); 35 window.open("/session/test", "_self"); 36 }, 37 error : function() { 38 alert("Wrong!"); 39 } 40 }); 41 } 42 </script> 43 44 45 </body> 46 </html>
There is also a test code specifically for @SessionAttributes parameter configuration
1 package test.dmh.session.controller; 2 3 import java.util.Enumeration; 4 5 import javax.servlet.http.HttpSession; 6 7 import org.slf4j.Logger; 8 import org.slf4j.LoggerFactory; 9 import org.springframework.stereotype.Controller; 10 import org.springframework.ui.ModelMap; 11 import org.springframework.web.bind.annotation.RequestMapping; 12 import org.springframework.web.bind.annotation.SessionAttributes; 13 import org.springframework.web.bind.support.SessionStatus; 14 15 @Controller 16 @SessionAttributes(value={"index1", "index2"}, types={String.class, Integer.class}) 17 public class IndexController3 { 18 19 private static final Logger logger = LoggerFactory.getLogger(IndexController3.class); 20 21 @RequestMapping("/setIndex") 22 public String setSession(ModelMap modelMap) { 23 logger.info("set session index"); 24 modelMap.addAttribute("index1", "aaa"); 25 modelMap.addAttribute("index2", "bbb"); 26 modelMap.addAttribute("index2", "ccc"); 27 modelMap.addAttribute("DDD"); 28 modelMap.addAttribute("FFF"); 29 modelMap.addAttribute(22); 30 31 return "home"; 32 } 33 34 @RequestMapping(value = "/showIndex") 35 public String show(ModelMap modelMap, HttpSession session) { 36 logger.info("show session"); 37 for (Object key : modelMap.keySet()) { 38 Object value = modelMap.get(key); 39 System.out.println(key + " = " + value); 40 } 41 System.out.println("***********************************"); 42 Enumeration<String> e = session.getAttributeNames(); 43 while (e.hasMoreElements()) { 44 String s = e.nextElement(); 45 System.out.println(s + " == " + session.getAttribute(s)); 46 } 47 System.out.println("***********************************"); 48 return "home"; 49 } 50 51 @RequestMapping("/clearIndex") 52 public String clear(SessionStatus status) { 53 logger.info("clear session index"); 54 status.setComplete(); 55 return "home"; 56 } 57 58 }
A brief description of the testing process is given.
Because there are so many parameters, I'm too lazy to think about names, and the serialized test1, 2, and 3 are gone.
The test was done by typing in the web address on the browser: http://localhost:8080/session/show1
Then change the suffix show1 to something else, such as set1, set2 and clear1, clear2. See the @RequestMapping configuration in my code for details.
After each input of Set1 and set2, you need to input show1 and show2 to view the contents of the session through the console. Of course, it is also possible to see and display information directly on the browser.
Here I would like to say a few main conclusions:
1. The @SessionAttributes annotation must be configured to automatically save data to session using ModelMap
2. The @SessionAttributes annotation can only be declared on the class. After the annotation, the method in this class can only operate session data on the parameters configured in @SessionAttributes, including saving, cleaning and reading.
Finally, there are some conclusions about parameter configuration in @SessionAttributes:
1. Configuration parameters provide value and types, which store array types. (You don't need to write an array with only one parameter, such as @SessionAttributes(value="test1", types=Integer.class).)
2. Use value to configure parameters similar to key pairs in Map
3. After the configuration parameters of practical types, the key saved in the background is its type. Personally, I feel that it is useful only when saving custom class objects, such as types=User.class, and common class objects such as String, etc. I think it is better to use the key value of value. Of course, the specific situation still needs to be specifically analyzed.
Finally, I would like to thank the bloggers who I think are more useful in the process of searching for information. Interested students can also visit the blog.
My Opinion on the Correct Use of Session in Spring MVC
Spring MVC@SessionAttributes annotation
The above article is my original summary based on official and other people's information. It is only for learning and communication. Code testing is available.