Custom MVC framework (J2EE Lesson 11)

catalogue

1, What is custom MVC

2, Custom MVC principle (including deductive process)

1, What is custom MVC

MVC, the full name of Model View Controller, is the abbreviation of Model View Controller. It is a software design idea. MVC can improve development efficiency and code reuse, which is of great benefit to later updates and upgrades.

Model: handles most of the business logic and data operations

View: responsible for page design and presentation to users in the form of html

Controller: handles user requests, reads data from the view, controls user input, and sends data to the model for processing

Schematic diagram of custom MVC framework    Framework: Reflection + design pattern (greatly reduces the amount of code, and the repetitive code is handed over to the framework for completion)

 

Benefits: 1. General pagination + general addition, deletion and modification   2. Code reduction of each layer (mc), data dao layer and control layer   3. Increase and decrease optimization of foreground code

2, Custom MVC principle (including deductive process)

When we write projects, most of us have a common problem, that is, there are a lot of repeated code and ideas (servlet s, dao packages, etc.). In order to solve this problem, we can use a framework to complete it.

Deduction process page:  

 

Deductive process (I) (processing servlets) (four servlets) (where doGet method is not useful)

  Operation results: (method: print on console)

Deductive process (2) (create a bootservlet to write four methods)

  Operation results:

  Deductive process (III) (reflection optimization)

	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String methodName = req.getParameter("methodName");
		try {
			Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
			m.setAccessible(true);
			m.invoke(this ,req, resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void load(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookdao.load()...Echo method called");
	}

	private void list(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookdao.list()...The query method was called");
	}

	private void delete(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookdao.delete()...The delete method was called");	
	}

	private void edit(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookdao.edit()...Modified method called");
	}

	private void add(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookdao.add()...New method called");
	}
	
	private void ref(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookdao.ref()...The association query method was called");
	}
	
	private void other(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookdao.other()...Another method was called");
	}

   Operation results:

  Deductive process (IV) (optimization of central controller and sub controller)  )

Action sub controller (extract all the methods that handle the request as the parent class)

ActionSupport     ( Implement Action, override the execte method, and obtain the corresponding method through reflection)

BookAction     ( Handle requests from browsers)

Optimize sub controller (Action)

package com.lgs.framework;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*
 * Sub controller (which handles browser requests)
 * Extract methods (such as add) upward and abstract
 */
public interface Action {
	
//	This is an abstract method that extracts methods (such as add) upward
//	Function: be able to process "all" requests of the browser( (e.g. add)
//	The return value determines which page to jump to (as for redirection / forwarding, it is determined by the central controller)
	public String execute(HttpServletRequest req, HttpServletResponse resp);
	
    }

(ActionSupport)

package com.lgs.framework;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*
 * Function: it can handle "all" requests of the browser (such as add)
 */
public class ActionSupport implements Action{

	public String execute(HttpServletRequest req, HttpServletResponse resp) {
		String methodName = req.getParameter("methodName");
		String res = null;
		try {
			Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
			m.setAccessible(true);
			res = (String) m.invoke(this ,req, resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return res;
	}
}

(BookAction)

package com.lgs.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.lgs.entity.Book;
import com.lgs.framework.ActionSupport;
import com.lgs.framework.ModelDriver;

public class BookAction extends ActionSupport implements ModelDriver<Book>{

//	If you inherit the execute method from the parent class, you inherit the method that reflects the dynamic call
//	BookAction-->BookServlet
//	Where is the current sub controller called? Associate sub controllers with browsers
	
	public Book book = new Book();
	
	private String add(HttpServletRequest req, HttpServletResponse resp) {
		
//		book.setBid(req.getParameter("bid"));
//		book.setBname(req.getParameter("bname"));
//		book.setPrice(req.getParameter("price"));
//		book.setAthor(req.getParameter("athor"));
//		book.setPublish(req.getParameter("publish"));
//		System.out.println(book);
		
	System.out.println("bookdao.add(book)...New method called"+"===="+"book");
	return "list";
	}

	private void list(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookdao.list()...The query method was called");
	}
	
	private String toEdit(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookdao.list()...The query method was called");
		return "toEdit";
	}

	private void delete(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookdao.delete()...The delete method was called");	
	}

	public Book getModel() {
		// TODO Auto-generated method stub
		return book;
	}
	
}

 

DispatchServlet central controller (there must be a collection of all sub controllers in the current central controller)

 

  Optimize central controller  ( DispatchServlet)

package com.lgs.framework;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;

import com.lgs.util.StringUtils;
import com.lgs.web.BookAction;

/*
 * The central controller
 * jsp: /book.action
 */
//@WebServlet("*.action")
public class DispatchServlet extends HttpServlet{

//	In the current central controller, there must be a set of all sub controllers
//	Defect: how to add, delete, modify and check new entity classes, which means to change the code, and the code design is not flexible enough
//	private Map<String, ActionSupport> actions = new HashMap<>();
//	The sub controller can be obtained without changing the code
//	Scheme: I put the logic of adding sub controllers into the code (the code is more flexible)
//	configModel has read all the configuration information with the knowledge of modeling
	private ConfigModel configModel = null;
	
//	Initialize all sub controllers to the current central controller
		public void init() throws ServletException {
//			There is a sub controller in the set
//			actions.put("/book", new BookAction());
//			actions.put("/goods", new BookAction());
			try {
//				String configurationLocation = "/luo.xml";
				String configurationLocation = this.getInitParameter("configurationLocation");
//				Configuration in web.xml
				if(StringUtils.isNotBlank(configurationLocation)) {
					configModel = ConfigModelFactory.build(configurationLocation);
				}else {//No configuration
					configModel = ConfigModelFactory.build();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
		
		public static void main(String[] args) throws Exception {
			ConfigModel build = ConfigModelFactory.build("/luo.xml");
			System.out.println(build);
		}
	
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}
	
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//		Associate the sub controller with the browser request, and the sub controller can process the request
//		http://localhost:8080/book.action?methodName=add-->BookAction.add();
		/*
		 * 1,url-->book
		 * 2,Find BookAction in action through the book string
		 * 3,Call the add of BookAction. If you want to call add, you can actually call the execute method uniformly
		 */
//		Get the requested address of the browser
		String url = req.getRequestURI();
//		1,url-->book
		url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
//		2. Find BookAction in action through the book string
//		ActionSupport action = actions.get(url);
//		We used to look for sub controllers in the map, but now we look for sub controllers in the configuration file
		/*
		 * 1,Find the corresponding ActionModel object through / book
		 * 2,Get the full path of the class through the ActionModel object
		 * 3,Reflect instanced objects
		 */
		ActionModel actionModel = configModel.pop(url);
//		The full pathname of the class
		String type = actionModel.getType();
		ActionSupport action;
		try {
//			BookAction/...
			action = (ActionSupport) Class.forName(type).newInstance();
//			Complete the encapsulation of entity class parameters
			if(action instanceof ModelDriver) {
//				The current sub controller implements the model driven interface
				ModelDriver m = (ModelDriver) action;
//				Book/Goods/...
				Object bean = m.getModel();
//				All request parameters are here. All request parameters need to be encapsulated in Book/Goods /
				BeanUtils.populate(bean, req.getParameterMap());
//				PropertyUtils.getProperty(bean, name);
			}
//			Execute the return value "list" of the business logic bookAction.add method
			
			String res = action.execute(req, resp);
			ForwardModel forwardModel = actionModel.pop(res);
			String path = forwardModel.getPath();
			boolean isRedirect = forwardModel.isRedirect();
			if(isRedirect) {
				resp.sendRedirect(req.getContextPath()+path);
			}else {
				req.getRequestDispatcher(path).forward(req, resp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

(the central controller is equivalent to the front desk. If you need a waiter to contact the background, you need to connect with the browser)

@WebServlet("*.action")

Connection idea: (detailed in the above code)

Associate the sub controller with the browser request, and the sub controller can process the request
http://localhost:8080/book.action?methodName=add-->BookAction.add();
1,url-->book           2. Find BookAction in action through the book string
3. Call the add of BookAction. If you want to call add, you can actually call the execute method uniformly

Operation results:  

  Conclusion: (when there are new requirements, the sub controller needs to be added to the set, that is, the code that needs to be changed is not flexible enough)

Solution: I put the logic of adding sub controllers into the code (the code is more flexible). configModel reads all the configuration information through the modeling knowledge (the modeling code is available in the CSDN home page)

luo.xml file

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<!-- 
	Each additional configuration here is equivalent to actions.put("/book", new BookAction());
	This solves the problem of code flexibility   false Forwarding on behalf of  true Represents redirection(Avoid repeated price increases)  
 	-->
	 <action path="/book" type="com.lgs.web.BookAction">
		<forward name="list" path="/BookList.jsp" redirect="false" />
		<forward name="toEdit" path="/BookEdit.jsp" redirect="true" />
	</action> 
	
</config>

Main controller code modification  

/**
		 * 1,Find the corresponding action object in the config file through the url
		 * 2,Then get the path name servlet.BookAction through this object
		 * 3,Then find the corresponding method to execute
		 */
		String url = req.getRequestURI();
		url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
		ActionModel actionmodel=configModel.pop(url);
		String type = actionmodel.getType();
		ActionSupport action=null;
	    try {
			action = (ActionSupport) Class.forName(type).newInstance();
			action.excute(req, resp);
		} catch (Exception e) {
			e.printStackTrace();
		}

  There are still remaining problems in the above optimization

1. Code redundancy   req.getparameter("") (too many parameters, laborious)  

2. Page Jump problem (avoid repeated typing of garbage code)

Problem 1: code redundancy

ModelDriver  ( Help the central controller to complete the project of parameter encapsulation)

package com.lgs.framework;

/*
 * Model driven interface
 * Function: help the central controller to complete the parameter packaging project
    book.setBid(req.getParameter("bid"));
	book.setBname(req.getParameter("bname"));
	book.setPrice(req.getParameter("price"));
	book.setAthor(req.getParameter("athor"));
 */
public interface ModelDriver<T> {

	T getModel();
	
}

Note: (BookAction does not implement the ModelDriver interface when the ModelDriver class is not written)  

Question 2: page Jump

<forward name="list" path="/BookList.jsp" redirect="false" />

<forward name="toEdit" path="/BookEdit.jsp" redirect="true" />

name: received return value   Path: jump path   redicect: jump mode

false represents forwarding   true for redirection (avoid duplicate submissions)

Idea:

1. When clicking the operation, enter the central controller, obtain the url and obtain the entity class to jump to

2. Enter the sub controller implementation class to obtain the method to be implemented

3. Find the corresponding return value from the BookAction class

4. Finally, get the content through the xml file to judge and jump

  DispatchServlet (central controller)

Note: resp.sendRedirect(req.getContextPath()+path);    req.getContextPath() remember to add the forwarding path, otherwise an error will be reported

			String res = action.execute(req, resp);
			ForwardModel forwardModel = actionModel.pop(res);
			String path = forwardModel.getPath();
			boolean isRedirect = forwardModel.isRedirect();
			if(isRedirect) {
				resp.sendRedirect(req.getContextPath()+path);
			}else {
				req.getRequestDispatcher(path).forward(req, resp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

Actionsupplier (sub controller interface implementation class)

package com.lgs.framework;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*
 * Function: it can handle "all" requests of the browser (such as add)
 */
public class ActionSupport implements Action{

	@Override
	public String execute(HttpServletRequest req, HttpServletResponse resp) {
		String methodName = req.getParameter("methodName");
		String res = null;
		try {
			Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
			m.setAccessible(true);
			res = (String) m.invoke(this ,req, resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return res;
	}
}

Bookaction (return value at tag)

luo.xml file

  Operation result: (jump succeeded)

  5, The storage path of the configuration file can be modified

  After importing the file into a jar package, we can't open it outside. At this time, we need to modify the storage path

//@WebServlet("*.action")   Note contact

Create a new xml file for configuration

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
 
  <display-name>T269-lgs_mvc</display-name>
  
  <servlet>
 	 <servlet-name>mvc</servlet-name>
     <servlet-class>com.lgs.framework.DispatchServlet</servlet-class>
  <init-param>
  	 <param-name>configurationLocation</param-name>
  	 <param-value>/luo.xml</param-value>
  </init-param>
  </servlet>
  
  <servlet-mapping>
  	  <servlet-name>mvc</servlet-name>
  	  <url-pattern>*.action</url-pattern>
  </servlet-mapping>
</web-app>

 < Param name > configurationlocation < / param name > receive the file name passed from the master controller, which can be obtained from the master controller
 < Param value > / Luo. XML < / param value > the main controller can get what files are built here

DispatchServlet (master controller)

  Test + run result: (jump successful)  

OK! It's over now. I hope I can help you!!!

Tags: Java Eclipse html mvc

Posted on Wed, 01 Sep 2021 17:51:59 -0400 by tappy