Before learning Strust2, we should understand the purpose of using STRUTS2? What benefits can it bring to us?
Design goals
The first goal of Strust design is to apply the MVC pattern to Web programming.
Technical advantages
STRUTS2 has two technical advantages.
One is that all STRUTS2 applications are based on the Client/server HTTP exchange protocol, the Java Servlet API reveals that Java servlet is just a small subset of the Java API, This allows us to program in the Business logic section using the powerful Java language.
The second is to provide a clear implementation of MVC, which contains a lot of key components involved in the processing of requests, such as: interceptors, OGNL expression language, stacks.
Because STRUTS2 has this goal, and has such an advantage, so this is our reason to learn struts2, below, we are in-depth analysis of how struts works.
Working principle
Struts2 's working principle can be described in the following diagram, below we step through the core content of each step.
The processing of a request in the STRUSTS2 framework is roughly divided into the following steps
1. The client initializes a request to a servlet container (for example, tomact)
2. This request passes through a series of filters (filter) with an optional filter called Actioncontextclenup, which is useful for integration of Struts2 and other frameworks, e.g. Sitemesh Plugin)
3, then Filterdispatcher is called, Filterdispatcher asks Actionmapper to decide whether the request needs to invoke an action. Filterdispatcher is the core of the controller, the core of the C control layer in MVC. The following is a rough analysis of the Filterdispatcher workflow and principles I understand: Filterdispathcer to initialize and enable core Dofilter
class { Public voidDoFilter (servletrequest req, servletresponse Res, filterchain chain)throwsioexception,servletexception{httpservletrequest Request=(httpservletrequest) req; HttpServletResponse Response=(HttpServletResponse) res; ServletContext ServletContext=Filterconfig.getservletcontext (); //HttpServletRequest and HttpServletResponse are handled here.Dispatcherutils du =dispatcherutils.getinstance (); Du.prepare (request,response);//as the name of this method, the locale, encoding, and special request parameters Settings Try{Request= Du.wraprequest (Request,servletcontext);//Packaging the request}Catch(IOException e) {String message= "Could not wrap servlet request with multipartrequestwrapper!"; Log.error (message,e); Throw Newservletexception (message, E); } Actionmapperif Mapper= Actionmapperfactory.getmapper ();//get the Action mapperactionmapping mapping = mapper.getmapping (Request);//get the action mapping if(Mapping = =NULL){ //There is no action on this request, should we look for a static resource?String ResourcePath =Requestutils.getservletpath (Request); if("". Equals (ResourcePath) &&NULL!=Request.getpathinfo ()) {ResourcePath=Request.getpathinfo (); } if("true". Equals (Configuration.get (webworkcontants.webwork_serve_static_content) &&resourcepath.startwith ("/webwork")) {String name= Resourcepath.substring ("/webwork". Length ()); Findstaticresource (Name,response); }Else{ //This was a normal request, let it pass throughChain.dofilter (Request,reponse); } //WW Didi its job here return; } Object o=NULL; Try{o=beforeactioninvocation (Request,servletcontext); Du.serviceaction (request,response,servletcontext,mapping); //The most central approach to the entire framework//the above method asks if Actionmapper needs to invoke an action to process the request.//if Actionmapper decides to call one of the action,filterdispatcher to give Actionproxy the request processing}finally{afteractioninvovation (request,servletcontext,o); Actioncontext.setconext (NULL); } } Public voidserviceaction (httpservletrequest request,httpservletresponse response, String namespace,string Actionname,map Requestmap,map parametermap) {HashMap Extracontext=Ctratecontextmap (Request,parametermap,sessionmap,applicationmap,request,response,getservletconfig ()); //instantiate the map request and ask Actionmapper if it needs to invoke an action to process the requestExtracontext.put (Servlet_dispatcher, This); Ognlvaluestack Stack=(Ognlvaluestack) Request.getattribute (Servletactioncontext.webwork_valuestack_key); if(stack!=NULL) {extracontext.put (Actioncontext.value_stack,Newognlvaluestack (stack)); } Try{ //here ActionName is resolved through two getactionname, filterdispatcher the processing of the request to Actionproxy,Actionproxy proxy =actionproxyfactory (). Createactionproxy (Namespace,actionname,extracontext); //Here's Servletdispatcher's Todo.Request.setattribute (Servletactioncontext.webwork_valuestck_key,proxy.getinvovation (). GetStack ()); Proxy.execute (); //executing actionproxy through proxy mode if(stack!=NULL) {Request.setattribute (servletactioncontext.webwork_valuestack_key,stack); } }Catch(Configuration e) {log.error ("Could not find action", E); Senderror (request,response,httpservletresponse.sc_not_found,e); }Catch(Exception e) {log.error ("Could Not execute action", E); Senderror (request,response,httpservletresponse.sc_internal_server_error,e); } }}
4. If Actionmapper decides to call one of the action,filterdispatcher to give actionproxy the processing of the request
5, Actionproxy through ConfigurationManager Ask the framework configuration file, find the action class that need to call, here, we generally read from the Struts.xml configuration.
6. Actionproxy create an instance of Actioninvocation.
7. The Actioninvocation instance is invoked using a naming pattern, which involves a call to the relevant interceptor (Intercepter) before and after the action is invoked.
Let's take a look at how Actioninvocation works:
Actioninvocation is the core of action scheduling in Xworks. And the dispatch of Interceptor, is also the responsibility of actioninvocation. Actioninvocation is an interface, and defaultactioninvocation is the default implementation of WebWork for Actioninvocation.
The Interceptor scheduling process is as follows:
When 1.ActionInvocation is initialized, all interceptor associated with the action are loaded according to the configuration.
2. When the action implementation is invoked by the Actioninvocation.invoke method, the interceptor is executed.
Interceptor has a lot of functionality from our action, which reduces the code of our action, and the behavior of independence is very good reusability. Many of the features of Xwork and WebWork are interceptor implemented, and you can assemble the interceptor that the action uses in the configuration file, which runs before and after the action in the order you specify.
Here, let's briefly introduce interceptor
With a lot of interceptors in the struts2, we can find in the Struts-default.xml under the Struts2-core-2.1.6.jar package:
<interceptors> <interceptor name= "Alias"class= "Com.opensymphony.xwork2.interceptor.AliasInterceptor"/> <interceptor name= "autowiring"class= "Com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/> <interceptor name= "Chain"class= "Com.opensymphony.xwork2.interceptor.ChainingInterceptor"/> <interceptor name= "Conversionerror"class= "Org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/> <interceptor name= "Clearsession"class= "Org.apache.struts2.interceptor.ClearSessionInterceptor"/> <interceptor name= "CreateSession"class= "Org.apache.struts2.interceptor.CreateSessionInterceptor"/> <interceptor name= "debugging"class= "Org.apache.struts2.interceptor.debugging.DebuggingInterceptor"/> <interceptor name= "Externalref"class= "Com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/> <interceptor name= "execandwait"class= "Org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/> <interceptor name= "Exception"class= "Com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/> <interceptor name= "FileUpload"class= "Org.apache.struts2.interceptor.FileUploadInterceptor"/> <interceptor name= "i18n"class= "Com.opensymphony.xwork2.interceptor.I18nInterceptor"/> <interceptor name= "Logger"class= "Com.opensymphony.xwork2.interceptor.LoggingInterceptor"/> <interceptor name= "Modeldriven"class= "Com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> <interceptor name= "Scopedmodeldriven"class= "Com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/> <interceptor name= "params"class= "Com.opensymphony.xwork2.interceptor.ParametersInterceptor"/> <interceptor name= "Actionmappingparams"class= "Org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/> <interceptor name= "Prepare"class= "Com.opensymphony.xwork2.interceptor.PrepareInterceptor"/> <interceptor name= "Staticparams"class= "Com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/> <interceptor name= "Scope"class= "Org.apache.struts2.interceptor.ScopeInterceptor"/> <interceptor name= "ServletConfig"class= "Org.apache.struts2.interceptor.ServletConfigInterceptor"/> <interceptor name= "sessionautowiring"class= "Org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/> <interceptor name= "Timer"class= "Com.opensymphony.xwork2.interceptor.TimerInterceptor"/> <interceptor name= "token"class= "Org.apache.struts2.interceptor.TokenInterceptor"/> <interceptor name= "Tokensession"class= "Org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/> <interceptor name= "Validation"class= "Org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/> <interceptor name= "workflow "class= "Com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/> <interceptor name= "Store"class= "Org.apache.struts2.interceptor.MessageStoreInterceptor"/> <interceptor name= "checkbox"class= "Org.apache.struts2.interceptor.CheckboxInterceptor"/> <interceptor name= "Profiling"class= "Org.apache.struts2.interceptor.ProfilingActivationInterceptor"/> <interceptor name= "Roles"class= "Org.apache.struts2.interceptor.RolesInterceptor"/> <interceptor name= "Jsonvalidation"class= "Org.apache.struts2.interceptor.validation.JSONValidationInterceptor"/> <interceptorname= "annotationwork Flowclass= "Com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor"/>
For sturts2 with the interceptor, it is relatively convenient to use, we only need to add the Struts.xml action tag <interceptor-ref name= " logger "/> And Struts.xml expands Struts-default, it can be used,
If you are customizing the Interceptor, you first need to write an interceptor class:
Package Ceshi; Import com.opensymphony.xwork2.ActionInvocation; Import extends abstractinterceptor { @Override public stringintercept ( Actioninvocation ai)throws Exception { System.out.println ("abc"); return Ai.invoke (); } }
and configured in Struts.xml
<! doctypestruts public "-//apache softwarefoundation//dtd Struts Configuration 2.0//en "Http://struts.apache.org/dtds/struts-2.0.dtd" > <struts> < Package name= "test" extends = "Struts-default" > <interceptors> <interceptor name= "abc" class = "Ceshi. Authorizationinterceptor "/> </interceptors> <action name=" Testlogger "c Lass = "Vaannila. Testloggeraction "> <interceptor-refname=" abc "/> <result name=" Success ">/success.jsp< /result> </action> </package ></struts>
8. Once the action is executed, Actioninvocation is responsible for finding the corresponding return result according to the configuration in the Struts.xml. The return result is usually (but not always, possibly another action chain) a JSP or freemarker template that needs to be represented. The tags inherited in the STRUTS2 framework can be used in the representation process. Need to involve actionmapper in this process
All objects (action,results,interceptors, etc.) are created through objectfactory in the above process.
comparison of Struts2 and Struts1
Struts2 is a lot simpler and more powerful than struts1, and we can see it in several ways:
from an architecture perspective:The struts2 uses interceptors to come out of the request, allowing the separation of the business logic controller from the SERVLET-API, avoiding intrusion, and struts1.x in action with the obvious intrusion Servlet-api.
from thread safety analysis:struts2.x is thread-safe, each object produces an instance, avoids thread-safety issues, and struts1.x is single-threaded in action.
performance:The struts2.x test can be detached from the Web container, and struts1.x relies on SERVLET-API, and the test relies on the Web container.
Request Parameter Package comparison:struts2.x uses Modeldriven mode so that we directly encapsulate the model object without having to inherit any struts2 base class, avoiding intrusion.
Tag Advantages: The tag library can almost completely replace the JSTL tag library, and struts2.x supports powerful OGNL expressions.
Of course, compared to struts2 and Struts1, in the file upload, data verification and other aspects also convenient a lot. There's no talking about it here.
A better framework can help us more efficient, stable development of qualified products, but we also do not rely on the framework, as long as we understand the idea, design patterns, we can expand their own functions, or we will always let others lead the walk!
The core and working principle of STRUST2