Customize MVC Framework

1. What is MVC?

Full MVC name: Model View Controller

Abbreviations for Model (Model Layer), View (View Layer), Controller (Control Layer)

It is a software design paradigm for separation of business logic processing, data, and interface display

 

2. Purpose of using MVC?

Separate M (Business Model) from V (User Interface) so that a program can use different representations, M (Controller) ensures M and V are synchronized, M changes, V updates accordingly

Common patterns:
model1: jsp+jdbc
model2: mvc
Achieving high cohesion Low coupling  Attend to each one's own duties 

Note: 1) Method cannot be invoked by a jumper

           2) Calls can only be made from top to bottom;View -> Controller -> Model

3. The structure and working principle of MVC

V (View Layer): JSP, HTML, freemarker

C (Control Layer): Servlet, Action, Controller

M (Model layer): entity, dao

Custom MVC working principle diagram

 

 Give an example:

When we wrote Add, Delete, and Change checks before, every method we wrote had a corresponding servlet to call the method and get the data, and then pass the value to the jsp interface, but this would result in a lot of duplicate code and reduce development efficiency.

<a href="index.do?Name=add">increase</a>
<a href="index.do?Name=delete">Delete</a>
<a href="index.do?Name=upd">modify</a>
<a href="index.do?Name=sele">query</a>

Method invocation depends on name. We can put all methods in one servlet and invoke the value control method by getting name, but if new methods are added, we will continue to change the original code to make it redundant.

So we can do that by reading the name without changing the logic, using reflection

package com.ltf.mvc.Servlet;
 
import java.io.IOException;
import java.lang.reflect.Method;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/index.do")
public class indexServlet extends HttpServlet{
 
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
		doPost(req, resp);
	}
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
		String a=req.getParameter("a");
//		if("add".equals(a)) {
//			add();
//		}else if("del".equals(a)) {
//			del();
//		}else if("upd".equals(a)) {
//			upd();
//		}else if("find".equals(a)) {
//			find();
//			
//		}
		try {
			Method m = this.getClass().getDeclaredMethod(a, HttpServletRequest.class,HttpServletResponse.class);
		    m.setAccessible(true);
		    m.invoke(this,req,resp);
		    
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
	}
	private void find(HttpServletRequest req, HttpServletResponse resp) {
		// TODO Auto-generated method stub
		System.out.println("Query...");
	}
	private void upd(HttpServletRequest req, HttpServletResponse resp) {
		// TODO Auto-generated method stub
		System.out.println("Modify........");
	}
	private void del(HttpServletRequest req, HttpServletResponse resp) {
		// TODO Auto-generated method stub
		System.out.println("Delete........");
	}
	private void add(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("Add........");
	}
	private void ref(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("ref(). . . . . . . . . ");
	}
}

Radiation solves the bug of altering code

Reflect this code as a central controller and does not process browser requests directly

Subcontrollers handle browser requests

So let's think about a question: for example, if a book is going to be checked for additions and deletions, and goods is going to be checked for additions and deletions, then both bookServlet s and goodsServlet s need to write reflections. Once there is more demand, the reflective code will become more repetitive, but it is necessary. We can adjust the location of this code, that is, we need to further optimize it

Action is an interface for abstract methods of up-extraction for add and del

package com.ltf.framework;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * Subcontroller
 * Processing browser requests
 * Extract up, abstract for add/ref/other	Abstract
 */
public interface Action {
	public String execute(HttpServletRequest req, HttpServletResponse resp);
	
}

 ActionSupport 

Implement the Action override execte method, get the corresponding method through reflection (process all requests)

Role: When more needs arise, only inheritance is required ActionSupport Class is sufficient

package com.ltf.framework;

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

import java.lang.reflect.Method;

/**
 * Role: Ability to handle all browser requests.Include add/ref/other...
 */
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;
	}

}

 DispatchServlet (Central Controller) 

package com.ltf.framework;

import java.io.IOException;

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;

/**
 * The central controller
 */
@WebServlet("*.action")
public class DispathServlet extends HttpServlet {
	// There must be a collection of all subcontrollers in the current central controller
	// Defect: If there are additions or deletions to the product --> means code changes --> code design is not flexible enough
	// Think: Without changing the code, the central controller can also find corresponding subcontrollers to handle browser requests
	// Scenario: Put the logic/actions with subcontrollers in the configuration file to complete (Dbutil change connection information is done in code/is now done in Properties file)
	// The benefit of placing it in a configuration file is that the code is more flexible, and you don't have to use it to modify information
	// private Map<String, ActionSupport> actions = new HashMap<>();
	// The configModel object reads all the configuration information through the knowledge of modeling
	private ConfigModel configModel = null;

	/**
	 * Initialize all subcontrollers into 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 GoodsAction());
		// actions.put("/order", new OrderAction());
		// ...
		try {
			configModel = ConfigModelFactory.build();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// Associate subcontrollers with browser requests, and find subcontrollers that can handle requests
		// http://localhost:8080/book.action?methodName=add-->BookAction.add();
		/*
		 * Idea 1. url-->/book 2. Find BookAction in actions using the/book string
		 * 3.Call add of BookAction, want to call add, actually just call execute uniformly
		 */
		// Get the browser's request address
		String url = req.getRequestURI();
		// url-->/book
		url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
		// Find BookAction in actions via the / book string
		// ActionSupport actrion = actions.get(url);
		// Find Subcontrollers in Map-->Find Subcontrollers in Configuration File
		/*
		 * 1.Find the corresponding ActionModel object through/book 2. Get the full path name of the class through the ActionModel object com.zking.web.BookAction
		 * 3.Reflect instantiated objects
		 */
		ActionModel actionModel = configModel.pop(url);
		// Full path name of class
		String type = actionModel.getType();
		ActionSupport action = null;
		try {
			// BookAction/GoodsAction/..
			action = (ActionSupport) Class.forName(type).newInstance();
			// Complete encapsulation of entity class parameters
			if (action instanceof ModelDriver) {
				// Current subcontroller implements model driven interface
				ModelDriver m = (ModelDriver) action;
				// Book/Goods/..
				Object bean = m.getModel();
				// All request parameters are here and all request parameters need to be encapsulated in Book/Goods/..
				BeanUtils.populate(bean, req.getParameterMap());
				// PropertyUtils.getProperty(bean, name)
			}
			// Return value "list" from executing business logic bookAction.add method
			/*
			 * 1.BookList.jsp forwarding for book display page as new to books 2.BookEdit.jsp redirection for book editing jump editing interface
			 */
			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();
		}
	}
}

Central Controller Role: 1. Get browser request URL 2. Find sub-controllers that can handle requests

There must be a collection of all the subcontrollers stored in the central controller
Initialize all subcontrollers into the central controller
We found that the set of subcontrollers is in the central controller. When new requirements arise, we need to add subcontrollers to the set.

That means code that needs to be changed.Then we put the subcontrollers in the configuration file, and at initialization, use xml modeling to set up the configuration file

Subcontrollers are read out so that no matter how many requirements there are, we only need to configure it in the configuration file.
 

Entity class parameters accept code redundancy (req.getparameter("))

Optimizing methods:

Model Driven Interface  Effect:

Help Central Controller complete parameter packaging project

Skip interface optimization:

Cong file:

<action path="book" type="com.ltf.web.BookAction">
        <forward name="list" path="booklist.jsp" redirect="false" />
        <forward name="toEdit" path="toEdit.jsp" redirect="true" />
    </action>

Path is a jump path, name is a call method, redirect=false is a forward, and vice versa

Modify execute method to have returns

Tags: html mvc

Posted on Fri, 03 Sep 2021 16:28:13 -0400 by Jasp182