Js|servlet
In Web server-side programming, session state management is an important issue that must be considered frequently. This paper analyzes the session management mechanism of Jsp/servlet and the problems it faces, and then proposes an improved session management method.
First, the servlet session management mechanism
HTTP is a stateless protocol, according to the design. It means that the Web application does not know about the information previously requested by the same user. One way to maintain session-state information is to use the session-tracking functionality provided by the servlet or JSP container. The Servlet API specification defines a simple httpsession interface through which we can easily implement session tracking.
The HttpSession interface provides a way to store and return standard session properties. Standard session properties, such as session identifiers, application data, and so on, are saved in the form of a "name-value" pair. In short, the HttpSession interface provides a standard way to save objects to memory and extract them from the same user's subsequent request. The method of saving data in a session is setattribute (string s, Object o), and the method of extracting the original saved object from the session is getattribute (string s).
In the HTTP protocol, there is no explicit termination signal when the user is no longer active. For this reason, we don't know if the user is going to return again, and if there is no way to solve the problem, a large number of HttpSession objects will accumulate in memory.
To this end, the servlet uses the "time-out limit" method to determine whether the user is still accessing: If a user does not issue a subsequent request within a certain amount of time, the user's session is invalidated and his HttpSession object is released. The default time-out interval for a session is defined by the servlet container. This value can be obtained by means of the Getmaxinactiveinterval method, modified by the Setmaxinactiveinterval method, in which the timeout time is measured in seconds. If the timeout value of the session is set to-1, the session never times out. The servlet can obtain the last access time before the current request through the Getlastaccessedtime method.
To get the HttpSession object, we can call the GetSession method of the HttpServletRequest object. In order to maintain session state correctly, we must invoke the GetSession method before sending any reply.
User sessions can be either invalidated by manual method or automatically invalidated. A voided session means that the HttpSession object and its data are deleted from memory. For example, if the user no longer sends a request within a certain period of time (the default 30 minutes), the Java Web server automatically invalidates his session.
The SERVLET/JSP session tracking mechanism has certain limitations, such as:
· The session object is saved in memory and occupies a considerable amount of resources.
· Session tracking relies on cookies. Some users have turned off cookies for a variety of reasons, especially for security reasons.
· Session trace to use the session identifier created by the server. In the context of multiple Web servers and multiple JVMs, the Web server does not recognize session identifiers created by other servers, and session tracking mechanisms do not work.
To understand the session-tracking mechanism in depth, we must first understand how the session works in the Servlet/jsp container.
Second, session identifier
Whenever a new user requests a JSP page that uses a HttpSession object, the JSP container sends a special number to the browser in addition to sending back the answer page. This particular number is called the session identifier, which is a unique user identifier. Thereafter, the HttpSession object resides in memory, waiting for the same user to call its method again when it returns.
On the client side, the browser saves the session identifier and FU Fa the session ID to the server in each subsequent request. The session identifier tells the JSP container that the current request is not the first request made by the user, and the server has previously created the HttpSession object for that user. At this point, the JSP container no longer creates a new HttpSession object for the user, but instead looks for a HttpSession object with the same session identifier, and then establishes the association between the HttpSession object and the current request.
The session identifier is sent as a cookie between the server and the browser. What if the browser doesn't support cookies? At this point, subsequent requests to the server will not have a session identifier. As a result, the JSP container considers the request to be from a new user, and it creates a HttpSession object, and the previously created HttpSession object still resides in memory, but the user's previous session information is lost.
In addition, the SERVLET/JSP container recognizes only the session identifiers it creates itself. If the same Web application is running on multiple servers on a Web farm (Web farm), you must have a mechanism in which a request from the same user is always directed to the server that handles the first request for that user.
III. Pseudo-session management mechanism
As mentioned earlier, the technology of Session management based on cookies faces various problems. Here we want to design a new session management mechanism to solve these problems. This session management mechanism, known as the Pseudo session mechanism, has the following characteristics:
· Objects and data are not saved in memory, but rather as text files. Each text file is associated with a specific user whose name is the identifier for the session. Therefore, the file name must be unique.
· The text file is saved in a dedicated directory that all Web servers can access. Therefore, pseudo sessions can be used on Web farms.
· The session identifier is not sent as a cookie, but is encoded directly into the URL. Therefore, the use of pseudo session technology requires that all hyperlinks be modified, including the action attribute of the HTML form.
In addition, we should also consider the following points when implementing the pseudo session management mechanism:
· It should be irrelevant to the application, and other developers who want to implement the same functionality should be able to easily reuse it.
· For security reasons, there should be a way to generate random numbers for session identifiers.
· To invalidate an expired session, you should set a time-out value. The same user, if he returns after a certain amount of time, he will get a new session identifier. This will prevent unauthorized users from risking other people's conversations.
· There should be a mechanism for collecting expired sessions and deleting the corresponding text files.
· If a user accesses the server again using a session identifier that has expired, the system should not allow the user to use the original session even if the text file for the session identifier has not been deleted.
· At the same time, there should be a mechanism to update the last changes in the session text file so that the session always maintains the most current and legitimate state data when the user returns before the session expiration time limit.
Iv. implementation of pseudo-session management mechanism
The project described below is called pseudosession, which is a simple implementation of the pseudo session mechanism. Considering the portability, we implement it in a JavaBean form. The complete code for Pseudosessionbean can be downloaded from the back of this article.
Pseudosessionbean has the following fields (field):
Public String path;public Long TimeOut;
Path is the directory where all session text files are saved. If the number of Web servers is more than one, this directory must allow access to all servers. However, to prevent users from accessing these text files directly, this path should not allow users to access them directly. One way to solve this problem is to use a directory other than the root of the Web site.
Timeout is the time between the last request of the user and the expiration of the session. In the Pseudosessionbean code list, the timeout is set to 20 minutes in milliseconds, which is a reasonable time-out value. For any user, if he continues to issue the request after this timeout, he will get a new session identifier.
Pseudosessionbean has 4 methods: Getsessionid,setvalue,getvalue,deleteallinvalidsessions.
4.1 GetSessionID method
The GetSessionID method is declared as follows:
Public String GetSessionID (HttpServletRequest request)
This method should be invoked at the beginning of each JSP page. It accomplishes the following tasks:
· If the user is the first time, a new session identifier is set for the user.
· Check the legality of the session identifier with the URL. If the session identifier has expired, the GetSessionID method returns a new session identifier.
Let's look at the working process of the GetSessionID method.
String sessionId = Request.getparameter ("SessionId");
Validsessionidfound is a tag that indicates whether the session identifier is legitimate. The initial value of the Validsessionidfound is false.
Boolean validsessionidfound = false;
The long now variable contains the server time at which the request occurred. This variable is used to determine the legality of a user session.
Long now = System.currenttimemillis ();
If a session identifier is found, the GetSessionID method checks its legality. The inspection process is as follows:
· A valid session identifier must have a corresponding text file of the same name.
· The last modification time of the file plus timeout should be greater than the current time.
· If there is a text file for the session, but the file has expired, the original file is deleted.
· Change the last modification date of the text file corresponding to the legal session identifier to now.
These tasks are done primarily with the file object, and the parameter that creates the file object is the path to the session text file:
if (sessionid!=null) {File f = new File (path + sessionId); if (F.exists ()) {if (f.lastmodified () + TimeOut > Now) {// When the session is valid//using setlastmodified, if the file is locked by another program, the//program does not produce any exceptions, but the file data does not change f.setlastmodified (now); validsessionidfound = true; else {//session has expired//deleted file F.delete ();}} End if (f.exists)}//End if (sessionid!=null)
If no valid session identifier exists, the GetSessionID method generates a session identifier and the corresponding text file:
if (!validsessionidfound) {sessionId = long.tostring (now);//create file ' F = new filename (path + sessionId); try {F.CREATENEWF Ile (); catch (IOException IoE) {}}//End of If!validsessionidfound
The procedure to guarantee the randomness of the file name is simple: Convert the current system time directly to the session identifier. For applications that involve sensitive data, we should consider using a more secure random number generator to generate session identifiers.
In summary, GetSessionID does not always return a new legal session identifier: It returns an identifier that is either the same as the identifier passed to it, or a newly created session identifier.
To ensure that the JSP page has a valid session identifier to invoke the SetValue, GetValue method, each JSP page must call the Getsesstionid method at the beginning.
4.2 SetValue method
The SetValue method holds the value string and the string name associated with it. This "name-value" pair can easily remind people of the Dictionary object. The SetValue method requires that a valid session identifier be provided in the first parameter, which assumes that the GetSessionID method has been executed before it is invoked, that the validated legal session identifier must exist, so it no longer verifies the validity of the incoming session identifier.
The SetValue method saves the name-value pairs as follows:
· If the name associated with the value has not been saved before, the new name-value pair is added to the end of the text file.
· If the name value associated with the value string has been previously saved, the original saved value is replaced with the new value value.
The SetValue method saves the name-value pairs in the following format, noting that the name is case sensitive:
Name-1 value-1name-2 value-2name-3 value-3...name-n value-n
The SetValue method is declared as follows:
public void SetValue (string sessionId, string name, String value)
The SetValue method first looks for the text file that corresponds to the current session. If a text file cannot be found, the SetValue method does nothing to return it directly. If a session text file is found, the SetValue method reads the lines of the text file, and then compares the read rows with name: If the line of text read is the same as name, the name is saved and the SetValue method replaces the value after the line If name cannot match the text line that is read, the line of text is copied directly to a temporary file.
The implementation code for this section of functionality is as follows:
try {FileReader fr = new FileReader (path + sessionId); BufferedReader br = new BufferedReader (FR); FileWriter FW = new FileWriter (path + sessionId + ". tmp"); BufferedWriter bw = new BufferedWriter (FW); String s; while ((s = br.readline ())!= null) if (!s.startswith (name + "")) {Bw.write (s); Bw.newline ();} Bw.write (name + "" + value); Bw.newline (); Bw.close (); Br.close (); Fw.close (); Bw.close (); . . .} catch (FileNotFoundException e) {}catch (IOException e) {System.out.println (e.tostring ());}
After all the rows in the original text file are copied to the temporary file, the SetValue method deletes the original text file and then changes the temporary file to the name of the session text file:
File F = new file (path + sessionId + ". tmp"); File Dest = new file (path + sessionId);d est.delete (); F.renameto (dest);
4.3 GetValue method
The GetValue method is used to extract data that was originally saved in a pseudo session. As with the SetValue method, the GetValue method also requires a valid session identifier to be passed in, and the GetValue method no longer checks the validity of the incoming session identifier. The second parameter of the GetValue method is the name of the data to be extracted, and the return value is the value associated with the specified name.
The GetValue method is declared as follows:
public string GetValue (string sessionId, string name)
The basic execution of the GetValue method is as follows: The session text file is first found, then read in rows until a line of text matches the name is found, and after a matching line of text is found, the GetValue method returns the value saved by the row, or null if the GetValue method is not found.
4.4 Deleteallinvalidsessions Method
The Deleteallinvalidsessions method deletes text files that are associated with sessions that have expired. The Deleteallinvalidsessions method is not a critical method because the expired session text file is deleted when the GetSessionID method is invoked. When to call this method is determined by the application itself. For example, we can write a dedicated background program that clears all expired text files at once a day by the program. The easiest way to do this is to call the Deleteallinvalidsessions method at the end of the JSP file, but if the site is busy, repeated calls to the Deleteallinvalidsessions method will reduce the responsiveness of the entire site. One sensible thing to do is to write a background program that cleans automatically when there is less traffic.
The Deleteallinvalidsessions method is declared as follows:
public void Deleteallinvalidsessions ()
It first reads the names of all session text files into the files string array:
File dir = new file (path); string[] files = dir.list ();
The Deleteallinvalidsessions method compares the last modification time of the text file (plus the timeout) and the system current time to determine whether the session has expired. The long variable now is used to save the current time of the system.
Long now = System.currenttimemillis ();
Next, the Deleteallinvalidsessions method iterates through the files array, checking the LastModified properties of each file in turn. All files associated with an expired session will be deleted:
for (int i=0; i<files.length; i++) {File f = new file (path + files[i)), if (f.lastmodified () + TimeOut > Now) f.del Ete (); Delete expired session text file}
V. Examples of application
After compiling Pseudosessionbean This javabean, we can use the pseudo session management mechanism to manage the session state information of the Web application. Because you do not have to use the server's session management mechanism, we can set the session property to false in the page directive to turn off the default Jsp/servlet sessions management feature.
<%@ page session= "false"%>
We then use the JSP <jsp:useBean> tag to tell the JSP container program to use Pseudosessionbean:
<jsp:usebean id= "Pseudosessionid" scope= "Application" class= "Pseudosession". Pseudosessionbean "/>
In the above <jsp:useBean> tag, the class attribute value is the "package. Class name" form. Of course, for different package names, the value of the class attribute should be modified accordingly. Note that the bean's scope property is "application," because we want to use this bean in all pages of the application. In this application, it is most efficient to set the bean's scope property to "application" because we only need to create the Bean object once. In addition, as mentioned earlier, the GetSessionID method must be invoked before all other code.
<% String sessionId = Pseudosessionid.getsessionid (Request);%>
To illustrate the application of Pseudosessionbean, let's look at two JSP pages, which are index.jsp and secondpage.jsp. The index.jsp page holds the user's name in the pseudo session variable, and secondpage.jsp extracts the user name.
The code for the Index.jsp page is as follows:
<%@ page session= "false" Contenttype= "text/html;charset=gb2312"%>
<jsp:usebean id= "Pseudosessionid" scope= "Application" class= "Pseudosession". Pseudosessionbean "/>
<% String sessionId = Pseudosessionid.getsessionid (Request);%>
<title> Pseudo Session </title>
<body>
<% String userName = "Bulbul"; Pseudosessionid.setvalue (SessionId, "UserName", UserName);%>
<a href=secondpage.jsp?sessionid=<%=sessionid%>> Click here </a>
<form method= "POST" action=anotherpage.jsp?sessionid=<%=sessionid%>>
Input data: <input type= "text" name= "Sample" >
<input type= "Submit" name= "submit" value= "Submit" >
</form>
</body>
<% pseudosessionid.deleteallinvalidsessions ();%>
Note that all of the hyperlinks have been overwritten, including the <form> tag's action attribute, and now contain the session identifier. Also note that the Deleteallinvalidsessions method is called at the end of the page.
The secondpage.jsp page simply returns the previously saved user name.
<%@ contenttype= "text/html;charset=gb2312" page session= "false"%>
<jsp:usebean id= "Pseudosessionid" scope= "Application" class= "Pseudosession". Pseudosessionbean "/>
<% String sessionId = Pseudosessionid.getsessionid (Request);%>
<title> 2nd Page </title>
<body>
<% String userName = Pseudosessionid.getvalue (sessionId, "userName"); Out.println ("User name is" + userName);%>
</body>