Recently, I saw an article titled "Beyond MVC: a new look at the servlet Infrastructure" written by N. Alex Rupp on the Internet" Article It means that MVC is mistakenly applied to the servlet architecture by struts and other frameworks. I think that only when I have a good understanding of struts and a deep understanding of MVC can I dare to make such remarks. I don't often hear people say that the people who are most familiar with me are your enemies. My skill is not strong, I have no ability to lead the trend, and I have to continue my life. I can only familiarize myself with Struts first. Statement:We strongly recommend that you read the article about N. Alex Rupp before reading this article. If you agree with him, you may feel that it is meaningless to study struts. Note:The struts Knowledge mentioned in this article is based on Struts 1.1. Unless otherwise specified, Struts 1.1 in this article is used. Directory: Detail 1: prerequisites for "using token to solve repeated submissions" Detail 2: Assignment of duties in page Flow Control Detail 1: prerequisites for "using token to solve repeated submissions" We know that the synchronization token mechanism can be used to solve the problem of repeated submission in Web applications. Struts also provides a reference implementation. Before processing the incoming request, the server compares the token value contained in the request with the token value saved in the current user session to see if it matches. After the request is processed and the reply is sent to the client, a new token will be generated. In addition to sending the token to the client, the old token saved in the user session is also replaced. In this way, if the user goes back to the submission page and submits the request again, the token sent from the client is inconsistent with the token sent from the server, effectively preventing repeated submission. Corresponding to this section, you may have such a section in your action subclass.Code:
If (istokenvalid (request, true) {// your code herereturn mapping. findforward ("success");} else {savetoken (request); Return Mapping. findforward ("submitagain ");} |
Here, both istokenvalid () and savetoken () are Org. apache. struts. action. action class, and the specific token processing logic is in org. apache. struts. util. tokenprocessor class. Struts generates a unique (for each session) token based on the user session ID and the current system time. For details, refer to the generatetoken () method in the tokenprocessor class. I wonder if you have noticed this problem, because struts stores the token in a session attribute, that is to say, each session server only saves and can only save one latest token value. My colleague raised a question: If I open two pages in the same session, the page submitted later cannot be submitted successfully. He also gave a practical example: for example, if you want to change the addresses of both Customer A and Customer B to a specific value, then the user may open two pages at the same time, modify a, modify B, submit a and submit B. According to the processing logic in struts, the modification commit of B is certainly not successful, but this commit operation does not mean that the operation is incorrect. Here, someone may ask: how can we open two pages in the same session? Didn't I start a new session when I re-open an IE browser? Yes. In this case, there are two sessions and there is no problem. However, you can also copy the current window by selecting "file"> "new"> "window" (or pressing CTRL + n, at this time, you will find that the page is in the same session as the original page. In fact, I was able to find this problem thanks to my colleague's habitual approach to IE. My colleague was not satisfied. He began to modify the implementation method in struts to store a unique token value on the server side for each page (at least some page. In this way, the restrictions that customers A and B Modify at the same time will not exist. But soon, my colleague began to realize that he was on a dangerous road. First, if each page stores a token value on the server, the data volume stored on the server will increase. In addition, if you consider opening multiple pages in the same session, it is like opening Pandora box, which will bring endless troubles to you. For example, first open page P1, and then use Ctrl + n to get the page P2, P1 submit, P2 submit, so far everything is normal. However, if you click "back" in P1 and P2 and submit P1 and P2 again, what will happen? What if I perform other operations after submitting in P2 and submit after rolling back in P1? If P1, P2, and P3 exist, what is the situation? It's too complicated! I think you will share the same feelings with us. You need to consider many possible combinations, and sometimes the results are not as simple as you think. This cannot be done. You have to come back and check out struts. As a matter of fact, we can find that the token mechanism in struts hides the premise that you (client) are not allowed to open multiple pages in the same session. Note that the session is the same. If you open two ie browsers, there are already two sessions. In fact, this seemingly unreasonable provision has its own principle: first, it greatly simplifies token implementation, and the two restrictions also conform to the usage habits of most people. Detail 2: Assignment of duties in page Flow Control We know that the execution process of Struts is roughly as follows: first, the Controller receives client requests, maps these requests to corresponding actions, and calls the execute method of action, this may also involve the creation and filling of actionform. After the execute method of action is executed, an actionforward object is returned. The controller forwards the request to the next action or JSP object based on the actionforward object. Finally, a view is generated to respond to the customer. On a large scale, Struts adopts the MVC Architecture, which is nothing special. But from some small points, we can still see some considerations of Craig R. McClanahan. We can see that the actionforward object is passed between the action and the controller. Because the action execute method requires that an actionforward object be returned, you will often see the following statement in the Action subclass:
Return (New actionforward (mapping. getinput ())); |
Or
Return (mapping. findforward ("success ")); |
In fact, an actionforward object is returned. In the actionProgramDifferent execution situations determine the next page (for example, return to the input page or go to the next page), and save the information in the actionforward object. Then, the controller can directly use this actionforward object to transfer pages. The following is an excerpt from the processforwardconfig () method of the org. Apache. Struts. Action. requestprocessor class. This method is called after the action instance is called.
Protected void processforwardconfig (httpservletrequest request, httpservletresponse response, forwardconfig forward) throws ioexception, servletexception {... String forwardpath = forward. getpath (); string uri = NULL; // paths not starting with/shocould be passed through without any processing // (ie. they're absolute) if (forwardpath. startswith ("/") {uri = requestutils. forwardurl (request, forward); // get module relative URI} else {uri = forwardpath;} If (forward. getredirect () {// only prepend context path for relative URI if (URI. startswith ("/") {uri = request. getcontextpath () + URI;} response. sendredirect (response. encoderedirecturl (URI);} else {doforward (Uri, request, response );}} |
Note:Forwardconfig is the parent class of actionforward. This method first calls the getpath () method of forwardconfig to obtain the path for the next flow. In some conditions, you also need to assemble the method to obtain the correct Uri, and finally perform page Jump Based on the URI. It can be seen that the processforwardconfig () method only performs some "technical" Processing on actionforward without any business-related content. In this way, the Controller (actionservlet) and action are completely separated, the two are independent of each other, achieving the goal of loose coupling between functional modules. Loose coupling between modules (between systems) has always been the pursuit of OO design, but it is not so easy to implement such loose coupling. The design in struts gives us some inspiration: the transmission of Inter-module correlated influencing factors can be packaged in the form of objects. In fact, I think the practice in struts can be slightly improved, that is, it is better to provide a geturi () method in actionforward to give the final Uri? Refer: 1. Beyond MVC: a new look at the servlet infrastructure 2. Allen Holub's build user interfaces for object-oriented systems series articles can learn a lot about object-oriented design from this article, although the author does not think that MVC is an object-oriented method, our MVC practitioners can still learn the object-oriented knowledge. 3. Struts 1.1 introductory article: go deep into Struts 1.1 4. Apache struts website 5. For details about repeated submission and solutions, refer to core J2EE patterns (Chinese Version of J2EE Core Model). Deepak Alur, John crupi, Dan malks: Core J2EE patterns-Best Practices and design strategies
|