Design Your Own MVC Framework

Source: Internet
Author: User
The fact is that I recently read the J2EE design patterns chapter on the expression layer patterns. There is a front-end controller + command mode workflow example in the book, I thought it would be easy to expand into an MVC framework. It took me an afternoon to rewrite the document and give a deeper understanding of the book. I think this may be helpful for people who learn and understand the design pattern and who first came into contact with Struts and other MVC frameworks. Because the entire model is similar to struts, I name it strutslet into _^. Learning nature. Do not take it seriously.

(1) The complete class diagram is as follows:

1. Frontcontroller: the front-end Controller provides a unified location for encapsulating public request processing. The task is quite simple. It executes public tasks and then forwards the requests to the corresponding controller. In strutslet, the front-end controller is also used to initialize and parse the configuration file, accept each request, and simply delegate the request to the scheduler (dispatcher ), the scheduler executes the corresponding action ). The scheduler returns the URL returned by the action to frontcontroller, which is responsible for forwarding.

2. Action interface: a good example of the command mode. It is a command interface. Every action that implements this interface encapsulates a request: Add a data record and update the model, or write a file to the disk. The command decouples the contact between the sender and the receiver. The sender calls an operation and the receiver accepts the request to execute the corresponding action. Because the command mode is used for decoupling, the sender does not need to know the receiver's interface.

3. Dispatcher: scheduler, responsible for process forwarding and calling action to execute business logic. The scheduler selects the page and action to remove the coupling between the application behavior and the front-end controller. The scheduler serves the front-end controller. It delegates model updates to action and provides the page selection to frontcontroller.

4. Actionforward: a model that encapsulates the information required for a redirection operation, including name and Redirection URL.

5. Actionmodel: after parsing the configuration file, each action is encapsulated into an actionmodel object. All actionmodels constitute a map and are stored in servletcontext for the entire framework.

(2) simple source code analysis
1. Action interface. There is only one execute method. Any action only needs to implement this interface and implement the corresponding business logic. Finally, an actionforward is returned for dispacher to call.

  1. Public InterfaceAction {
  2.  PublicActionforward execute (httpservletrequest request, servletcontext context );
  3. }

For example, to implement a login System (Demo example), loginaction verifies the username and password. If the username and password are correct, the success page is returned. If the login fails, the Fail page is returned:

  1. Public ClassLoginactionImplementsAction {
  2.  Private StringName = "";
  3.  PublicActionforward execute (httpservletrequest request,
  4. Servletcontext context ){
  5. StringUsername = request. getparameter ("username ");
  6. StringPassword = request. getparameter ("password ");
  7. If(Username. Equals ("Dennis") & password. Equals ("123 ")){
  8. Request. setattribute ("name", name );
  9. ReturnActionforward. success;// If the logon succeeds, success is returned.
  10. }Else
  11. ReturnActionforward. fail;// Otherwise, return fail
  12. }

2. Let's take a look at two models: actionforward and actionmodel. There is nothing, attributes, and the corresponding getter and setter methods:

  1. /**
  2. * Class description: Steering Model
  3. * @ Author Dennis
  4. *
  5. **/
  6. Public ClassActionforward {
  7.  Private StringName;// Forward name
  8.  Private StringViewurl;// Forward URL
  9.  Public Static FinalActionforward success =NewActionforward ("success ");
  10.  Public Static FinalActionforward fail =NewActionforward ("fail ");
  11.  PublicActionforward (StringName ){
  12. This. Name = Name;
  13. }
  14.  PublicActionforward (StringName,StringViewurl ){
  15. Super();
  16. This. Name = Name;
  17. This. Viewurl = viewurl;
  18. }
  19.  // Getter and setter methods of... Name and viewurl
  20. }

We can see that actionforward encapsulates success and fail objects in advance.

  1. Public ClassActionmodel {
  2.  Private StringPath;// Action path
  3.  Private StringClassname;// Action class
  4.  PrivateMap <String, Actionforward> forwards;// Action forward
  5.  PublicActionmodel (){}
  6.  PublicActionmodel (StringPath,StringClassname,
  7. Map <String, Actionforward> forwards ){
  8. Super();
  9. This. Path = path;
  10. This. Classname = classname;
  11. This. Forwards = forwards;
  12. }
  13.  //... Corresponding getter and setter Methods
  14. }

3. Knowing what the two models are, we should be able to guess what our configuration file is like, similar to the struts configuration file format:

  1. <? XML version = "1.0" encoding = "UTF-8"?>
  2. <Actions>
  3. <Action Path = "/login"
  4. Class= "Com. strutslet. Demo. loginaction">
  5. <Forward name = "success" url = "Hello. jsp"/>
  6. <Forward name = "fail" url = "fail. jsp"/>
  7. </Action>
  8. </Actions>

The path is the path to be called in the application. The class specifies the action to be called, and the forward element specifies the redirection. For example, if success is used, we will switch to hello. JSP. If it fails, it turns to fail. JSP. The loginaction used in the demo is configured here.

4. The dispacher interface is mainly the getnextpage method, which is used to obtain the next page direction and forward it to the front-end controller.

  1. Public InterfaceDispatcher {
  2.  Public VoidSetservletcontext (servletcontext context );
  3.  Public StringGetnextpage (httpservletrequest request, servletcontext context );
  4. }

5. 5. In the original book, a workflow dispatcher is implemented to call the action in order to call the workflow. What we need is to call the corresponding action according to the Request Path, execute the action execute method to return an actionforward, then get the viewurl of actionforward, and provide this viewurl to the front-end controller for forwarding, let's take a look at its getnextpage method:

  1. Public StringGetnextpage (httpservletrequest request, servletcontext context ){
  2. Setservletcontext (context );
  3. Map <String, Actionmodel> actions = (Map <String, Actionmodel>) Context
  4. . Getattribute (constant. actions_attr );// Obtain all action information from servletcontext
  5. StringReqpath = (String) Request. getattribute (constant. request_attr );// The Request Path
  6. Actionmodel = actions. Get (reqpath );// Obtain the corresponding action based on the path.
  7. StringForward_name = "";
  8. Actionforward;
  9. Try{
  10. ClassC =Class. Forname (actionmodel. getclassname ());// Each request corresponds to an action instance
  11. Action action = (Action) C. newinstance ();
  12. Actionforward = action.exe cute (request, context );// Execute Method for executing action
  13. Forward_name = actionforward. getname ();
  14. }Catch(ExceptionE ){
  15. Log. Error ("can not find action" + actionmodel. getclassname ());
  16. E. printstacktrace ();
  17. }
  18. Actionforward = actionmodel. getforwards (). Get (forward_name );
  19. If(Actionforward =Null){
  20. Log. Error ("can not find page for forward" + forward_name );
  21. Return Null;
  22. }Else
  23. ReturnActionforward. getviewurl ();// Return the viewurl of actionforward
  24. }

6. Front-end controller (frontcontroller), whose tasks are clear, initialize the configuration file, store all actions to the servletcontext for use by the entire framework, and obtain the Request Path, call dispatcher and run the getnextpage method to get the URL of the next page:

  1. Public VoidInit ()ThrowsServletexception {
  2. // Initialize the configuration file
  3. Servletcontext context = getservletcontext ();
  4. StringConfig_file = getservletconfig (). getinitparameter ("Config ");
  5. StringDispatcher_name = getservletconfig (). getinitparameter ("dispatcher ");
  6. If(Config_file =Null| Config_file.equals (""))
  7. Config_file = "/WEB-INF/strutslet-config.xml ";// The default is/WEB-INF/strutslet-config below
  8. If(Dispatcher_name =Null| Dispatcher_name.equals (""))
  9. Dispatcher_name = constant. default_dispatcher;
  10. Try{
  11. Map <String, Actionmodel> resources = configutil. newinstance ()// Tool-class parsing configuration file
  12. . Parse (config_file, context );
  13. Context. setattribute (constant. actions_attr, resources );// Stored in servletcontext
  14. Log.info ("The strutslet configuration file has been initialized successfully ");
  15. }Catch(ExceptionE ){
  16. Log. Error ("failed to initialize the strutslet configuration file ");
  17. E. printstacktrace ();
  18. }
  19. // Instantiate dispacher
  20. Try{
  21. ClassC =Class. Forname (dispatcher_name );
  22. Dispatcher dispatcher = (dispatcher) C. newinstance ();
  23. Context. setattribute (constant. dispatcher_attr, dispatcher );// Put it in servletcontext
  24. Log.info ("dispatcher initialization succeeded ");
  25. }Catch(ExceptionE ){
  26. Log. Error ("dispatcher initialization failed ");
  27. E. printstacktrace ();
  28. }
  29. .....

The doget () and dopost Methods let it call the process method:

  1. Protected VoidProcess (httpservletrequest request,
  2. Httpservletresponse response)ThrowsServletexception, ioexception {
  3. Servletcontext context = getservletcontext ();
  4. // Obtain the action path
  5. StringRequri = request. getrequesturi ();
  6. IntI = requri. lastindexof (".");
  7. StringContextpath = request. getcontextpath ();
  8. StringPath = requri. substring (contextpath.Length(), I );
  9. Request. setattribute (constant. request_attr, PATH );
  10. Dispatcher dispatcher = (dispatcher) Context. getattribute (constant. dispatcher_attr );
  11. // Make sure we don't cache dynamic data
  12. Response. setheader ("cache-control", "No-Cache ");
  13. Response. setheader ("Pragma", "No-Cache ");
  14. // Use the dispatcher to find the next page
  15. StringNextpage = dispatcher. getnextpage (request, context );// Call the getnextpage of dispatcher.
  16. // Forward control to the view
  17. Requestdispatcher forwarder = request. getrequestdispatcher ("/"
  18. + Nextpage );
  19. Forwarder. Forward (request, response );// Forwarding page
  20. }

7. Finally, Web. xml configuration is very simple, configure the front-end controller, provide startup parameters (configuration file location, empty search/WEB-INF/below the strutslet-config.xml file ), we send all requests ending with an action to frontcontroller for processing:

  1. <Servlet>
  2. <Servlet-Name> strutsletcontroller </servlet-Name>
  3. <Servlet-Class> Com. strutslet. Core. frontcontroller </servlet-Class>
  4. <! --
  5. <Init-param>
  6. <Param-Name> config </param-Name>
  7. <Param-value>/WEB-INFstrutslet-config.xml </param-value>
  8. </Init-param>
  9. -->
  10. <Load-on-startup> 0 </load-on-startup>
  11. </Servlet>
  12. <Servlet-mapping>
  13. <Servlet-Name> strutsletcontroller </servlet-Name>
  14. <URL-pattern> *. Action </url-pattern>
  15. </Servlet-mapping>

Finally, let's look at the entire framework:
 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.