当前位置:网站首页>简单自定义MVC优化
简单自定义MVC优化
2022-06-30 02:58:00 【安离九歌】
前言
这篇文章接上一篇文章,上一篇文章分享了简单的自定义了MVC。本片文章就来分享自定义MVC优化。
一、中央控制器动态加载储存子控制器
我们自定义MVC最后要将它导出成jar包,那如果我们要加的子控制器怎么办,都导成jar包。
这里我们就要用到之前分享的内容XML。
通过之前的建模我们可以知道,configModel对象会包含config.xml中的所有子控制器信息
同时为了解决中央控制器能够动态的加载保存子控制器的信息,我们只需要引入configModel对象即可
DispatcherServlet
package com.zhw.framework;
import java.io.IOException;
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 com.zhw.web.BookAction;
import com.zhw.xml.ActionModel;
import com.zhw.xml.ConfigModel;
import com.zhw.xml.ConfigModelFactory;
//@WebServlet("*.action")
public class DispatcherServlet extends HttpServlet{
// private Map<String,Action> actions = new HashMap<String,Action>();
private ConfigModel configModel;
/*
* 通过之前的建模我们可以知道,configModel对象会包含config.xml中的所有子控制器信息
* 同时为了解决中央控制器能够动态的加载保存子控制器的信息,我们只需要引入configModel对象即可
*/
@Override
public void init() throws ServletException {
// actions.put("/book",new BookAction());
// actions.put("/order",new BookAction());
try {
configModel = ConfigModelFactory.bulid();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//http://localhost:8080/mvc/book.action?methodName=list
String uri = req.getRequestURI();
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
// Action action = actions.get(uri);
// action.execute(req, resp);
//
ActionModel actionModel = configModel.pop(uri);
if(actionModel == null) {
throw new RuntimeException("action 配置错误 ");
}
//是action子控制器的全路径名
String type = actionModel.getType();
try {
//类类是反射的开始,通过子控制器的全路径名用newInstance方法得到子控制器。
Action action = (Action) Class.forName(type).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
}
config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<action path="/book" type="com.zhw.web.BookAction">
<forward name="failed" path="/login.jsp" redirect="false" />
<forward name="success" path="/main.jsp" redirect="true" />
</action>
</config>ConfigModel
package com.zhw.xml;
import java.util.HashMap;
import java.util.Map;
/**
* 对应标签
* @author zhw
*
*/
public class ConfigModel {
private Map<String,ActionModel> aMap = new HashMap<String,ActionModel>();
public void push(ActionModel actionModel) {
aMap.put(actionModel.getPath(), actionModel);
}
public ActionModel pop(String path) {
return aMap.get(path);
}
}
ConfigModelFactory
package com.zhw.xml;
import java.io.InputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* 23种设计模式之工厂模式
* sessionfactory
*
* @author zhw
*
*/
public class ConfigModelFactory {
public static ConfigModel bulid() throws Exception {
String defaultPath = "/config.xml";
InputStream in = ConfigModelFactory.class.getResourceAsStream(defaultPath);
SAXReader s = new SAXReader();
Document doc = s.read(in);
ConfigModel configModel = new ConfigModel();
List<Element> actionEles = doc.selectNodes("/config/action");
for (Element ele : actionEles) {
ActionModel actionModel = new ActionModel();
actionModel.setPath(ele.attributeValue("path"));
actionModel.setType(ele.attributeValue("type"));
//将forwardModel 赋值并添加到ActionModel
List<Element> forwardEles = ele.selectNodes("forward");
for (Element fele : forwardEles) {
ForwardModel forwardModel = new ForwardModel();
forwardModel.setName(fele.attributeValue("name"));
forwardModel.setPath(fele.attributeValue("path"));
forwardModel.setRedirect("true".equals(fele.attributeValue("redirect")));
actionModel.push(forwardModel);
}
configModel.push(actionModel);
}
return configModel;
}
}
优化后运行:


二、参数传递封装
假设我们需要新增一本书籍,需要传的为书籍编号,书籍名称,书籍价格。三个参数,很方便,但是如果需要传三十个参数呢?为了这个问题,对参数传递封装
未优化前:
Demo
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>目前增删改查的方法</h3>
<a href="${pageContext.request.contextPath }/book/add">增加</a>
<a href="${pageContext.request.contextPath }/book/del">删除</a>
<a href="${pageContext.request.contextPath }/book/edit">修改</a>
<a href="${pageContext.request.contextPath }/book/list">查询</a>
<!-- r
上述问题:
1、关于单个实体/表操作场景越多,需要新建的类也就越多,造成了项目中类的数量过于庞大
2、当新增了业务,除了要添加该业务对应的方法(load),同时还要改动原有的方法
3、反射相关代码、在每一个实体类对应的Servlet中都存在
4、每一个Servlets中都有doget、dopost
-->
<h3>类数量过多问题的优化</h3>
<a href="${pageContext.request.contextPath }/book.action?methodName=add">增加</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=del">删除</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=edit">修改</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=list">查询</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=load">回显</a>
<h3>订单类CRUD</h3>
<a href="${pageContext.request.contextPath }/order.action?methodName=add">增加</a>
<a href="${pageContext.request.contextPath }/order.action?methodName=del">删除</a>
<a href="${pageContext.request.contextPath }/order.action?methodName=edit">修改</a>
<a href="${pageContext.request.contextPath }/order.action?methodName=list">查询</a>
<a href="${pageContext.request.contextPath }/order.action?methodName=load">回显</a>
<h3>xx</h3>
<a href="${pageContext.request.contextPath }/book.action?methodName=add&bid=123&bname=logo&price=99">增加</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=del">删除</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=edit">修改</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=list">查询</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=load">回显</a>
</body>
</html>BookAction
package com.zhw.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhw.entity.Book;
import com.zhw.framework.ActionSupport;
public class BookAction extends ActionSupport{
private void list(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("在同样一个Servlet中调用list方法");
}
private void edit(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("在同样一个Servlet中调用edit方法");
}
private void del(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("在同样一个Servlet中调用del方法");
}
private void add(HttpServletRequest req, HttpServletResponse resp) {
String bid = req.getParameter("bid");
String bname = req.getParameter("bname");
String price = req.getParameter("price");
Book book = new Book();
book.setBid(Integer.valueOf(bid));
book.setBname(bname);
book.setPrice(Float.valueOf(price));
System.out.println("在同样一个Servlet中调用add方法");
}
private void load(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("在同样一个Servlet中调用load方法");
}
}
Book
package com.zhw.entity;
public class Book {
private int bid;
private String bname;
private float price;
public int getBid() {
return bid;
}
public void setBid(int bid) {
this.bid = bid;
}
public String getBname() {
return bname;
}
public void setBname(String bname) {
this.bname = bname;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public Book() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Book [bid=" + bid + ", bname=" + bname + ", price=" + price + "]";
}
}
优化后:
DispatcherServlet
package com.zhw.framework;
import java.io.IOException;
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 com.zhw.web.BookAction;
import com.zhw.xml.ActionModel;
import com.zhw.xml.ConfigModel;
import com.zhw.xml.ConfigModelFactory;
import com.zhw.xml.ForwardModel;
//@WebServlet("*.action")
public class DispatcherServlet extends HttpServlet{
// private Map<String,Action> actions = new HashMap<String,Action>();
private ConfigModel configModel;
/*
* 通过之前的建模我们可以知道,configModel对象会包含config.xml中的所有子控制器信息
* 同时为了解决中央控制器能够动态的加载保存子控制器的信息,我们只需要引入configModel对象即可
*/
@Override
public void init() throws ServletException {
// actions.put("/book",new BookAction());
// actions.put("/order",new BookAction());
try {
String configLocation = this.getInitParameter("configLocation");
if(configLocation == null ||"".equals(configLocation)) {
}
configModel = ConfigModelFactory.bulid();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//http://localhost:8080/mvc/book.action?methodName=list
String uri = req.getRequestURI();
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
// Action action = actions.get(uri);
// action.execute(req, resp);
//
ActionModel actionModel = configModel.pop(uri);
if(actionModel == null) {
throw new RuntimeException("action 配置错误 ");
}
//是action子控制器的全路径名
String type = actionModel.getType();
try {
//类类是反射的开始,通过子控制器的全路径名用newInstance方法得到子控制器。
Action action = (Action) Class.forName(type).newInstance();
if(action instanceof ModelDriven) {
ModelDriven md = (ModelDriven)action;
Object model = md.getModel();
//将前端所有参数值封装进实体类
BeanUtils.populate(model, req.getParameterMap());
}
// 正式调用放法,book中的属性要被赋值
// action.execute(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Demo
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>参数传递封装的优化</h3>
<a href="${pageContext.request.contextPath }/book.action?methodName=add&bid=989898&bname=laoliu&price=89">增加</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=del">删除</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=edit">修改</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=list">查询</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=load">回显</a>
</body>
</html>BookAction
package com.zhw.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhw.entity.Book;
import com.zhw.framework.ActionSupport;
import com.zhw.framework.ModelDriven;
public class BookAction extends ActionSupport implements ModelDriven<Book>{
private Book book = new Book();
private String list(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("在同样一个Servlet中调用list方法");
return "success";
}
private void edit(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("在同样一个Servlet中调用edit方法");
}
private void del(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("在同样一个Servlet中调用del方法");
}
private String add(HttpServletRequest req, HttpServletResponse resp) {
// String bid = req.getParameter("bid");
// String bname = req.getParameter("bname");
// String price = req.getParameter("price");
// Book book = new Book();
// book.setBid(Integer.valueOf(bid));
// book.setBname(bname);
// book.setPrice(Float.valueOf(price));
System.out.println("在同样一个Servlet中调用add方法");
return "failed";
}
private void load(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("在同样一个Servlet中调用load方法");
}
@Override
public Book getModel() {
return book;
}
}
三、方法执行结果优化
对方法的执行结果进行优化,如果增加成功就用转发,失败就用重定向。
DispatcherServlet
package com.zhw.framework;
import java.io.IOException;
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 com.zhw.web.BookAction;
import com.zhw.xml.ActionModel;
import com.zhw.xml.ConfigModel;
import com.zhw.xml.ConfigModelFactory;
import com.zhw.xml.ForwardModel;
//@WebServlet("*.action")
public class DispatcherServlet extends HttpServlet{
// private Map<String,Action> actions = new HashMap<String,Action>();
private ConfigModel configModel;
/*
* 通过之前的建模我们可以知道,configModel对象会包含config.xml中的所有子控制器信息
* 同时为了解决中央控制器能够动态的加载保存子控制器的信息,我们只需要引入configModel对象即可
*/
@Override
public void init() throws ServletException {
// actions.put("/book",new BookAction());
// actions.put("/order",new BookAction());
try {
String configLocation = this.getInitParameter("configLocation");
if(configLocation == null ||"".equals(configLocation)) {
}
configModel = ConfigModelFactory.bulid();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//http://localhost:8080/mvc/book.action?methodName=list
String uri = req.getRequestURI();
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
// Action action = actions.get(uri);
// action.execute(req, resp);
//
ActionModel actionModel = configModel.pop(uri);
if(actionModel == null) {
throw new RuntimeException("action 配置错误 ");
}
//是action子控制器的全路径名
String type = actionModel.getType();
try {
//类类是反射的开始,通过子控制器的全路径名用newInstance方法得到子控制器。
Action action = (Action) Class.forName(type).newInstance();
if(action instanceof ModelDriven) {
ModelDriven md = (ModelDriven)action;
Object model = md.getModel();
//将前端所有参数值封装进实体类
BeanUtils.populate(model, req.getParameterMap());
}
// 正式调用放法,book中的属性要被赋值
action.execute(req, resp);
String result = action.execute(req, resp);
ForwardModel forwardModel = actionModel.pop(result);
boolean redirect = forwardModel.isRedirect();
if(forwardModel == null) {
throw new RuntimeException("forward config error");
}
String path = forwardModel.getPath();
if(redirect)
resp.sendRedirect(req.getServletContext().getContextPath()+path);
else
req.getRequestDispatcher(path).forward(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<action path="/book" type="com.zhw.web.BookAction">
<forward name="success" path="/Demo2.jsp" redirect="false" />
<forward name="failed" path="/Demo3.jsp" redirect="true" />
</action>
</config>forwardModel
package com.zhw.xml;
/**
* @author zhw
*
*/
public class ForwardModel {
// <forward name="failed" path="/reg.jsp" redirect="false" />
private String name;
private String path;
private Boolean redirect;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Boolean getRedirect() {
return redirect;
}
public void setRedirect(Boolean redirect) {
this.redirect = redirect;
}
public boolean isRedirect() {
return redirect;
}
}


四、框架配置文件可变
DispatcherServlet
package com.zhw.framework;
import java.io.IOException;
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 com.zhw.web.BookAction;
import com.zhw.xml.ActionModel;
import com.zhw.xml.ConfigModel;
import com.zhw.xml.ConfigModelFactory;
import com.zhw.xml.ForwardModel;
//@WebServlet("*.action")
public class DispatcherServlet extends HttpServlet{
// private Map<String,Action> actions = new HashMap<String,Action>();
private ConfigModel configModel;
/*
* 通过之前的建模我们可以知道,configModel对象会包含config.xml中的所有子控制器信息
* 同时为了解决中央控制器能够动态的加载保存子控制器的信息,我们只需要引入configModel对象即可
*/
@Override
public void init() throws ServletException {
// actions.put("/book",new BookAction());
// actions.put("/order",new BookAction());
try {
String configLocation = this.getInitParameter("configLocation");
if(configLocation == null ||"".equals(configLocation)) {
}
configModel = ConfigModelFactory.bulid();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//http://localhost:8080/mvc/book.action?methodName=list
String uri = req.getRequestURI();
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
// Action action = actions.get(uri);
// action.execute(req, resp);
//
ActionModel actionModel = configModel.pop(uri);
if(actionModel == null) {
throw new RuntimeException("action 配置错误 ");
}
//是action子控制器的全路径名
String type = actionModel.getType();
try {
//类类是反射的开始,通过子控制器的全路径名用newInstance方法得到子控制器。
Action action = (Action) Class.forName(type).newInstance();
if(action instanceof ModelDriven) {
ModelDriven md = (ModelDriven)action;
Object model = md.getModel();
//将前端所有参数值封装进实体类
BeanUtils.populate(model, req.getParameterMap());
}
// 正式调用放法,book中的属性要被赋值
action.execute(req, resp);
String result = action.execute(req, resp);
ForwardModel forwardModel = actionModel.pop(result);
boolean redirect = forwardModel.isRedirect();
if(forwardModel == null) {
throw new RuntimeException("forward config error");
}
String path = forwardModel.getPath();
if(redirect)
resp.sendRedirect(req.getServletContext().getContextPath()+path);
else
req.getRequestDispatcher(path).forward(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>ss</display-name>
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>com.zhw.framework.DispatcherServlet</servlet-class>
<init-param>
<param-name>configLocation</param-name>
<param-value>laoliu</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>将config.xml改为laoliu.xml
总结
在上一次的简单的自定义mvc后,我们对此进行了优化,优化后减少了代码量,缩短开发时间。
本次的内容分享到这。如有错误,还望指正。
边栏推荐
- 如何在 JupyterLab 中把 ipykernel 切换到不同的 conda 虚拟环境?
- 2. successfully solved bug:exception when publishing [Failed to connect and initialize SSH connection...
- 发现mariadb数据库时间晚了12个小时
- CMake教程系列-01-最小配置示例
- Note the use of export/import and class inheritance in ES6
- 三层交换机和二层交换机区别是什么
- Summary of PHP test sites encountered in CTF questions (I)
- The Oracle main program is deleted, but the data is on another hard disk. Can I import the data again?
- Wechat applet page Jump and parameter transfer
- Distributed file system fastdfs
猜你喜欢

Pytoch learning (II)

Uniapp address translation latitude and longitude

C # basic learning (XIII) | breakpoint debugging

LeetCode 3. Longest substring without duplicate characters

Visual HTA form designer htamaker interface introduction and usage, Download | HTA VBS visual script writing

2. 成功解决 BUG:Exception when publishing, ...[Failed to connect and initialize SSH connection...

Time complexity analysis

How to prevent duplicate submission under concurrent requests

The MariaDB database was found 12 hours late

三层交换机和二层交换机区别是什么
随机推荐
Mysql提取表字段中的字符串
The rigorous judgment of ID number is accurate to the last place in the team
Distributed file storage system fastdfs hands on how to do it
怎么使用Vant实现数据分页和下拉加载
Summary of PHP test sites encountered in CTF questions (I)
Intel hex, Motorola S-Record format detailed analysis
Intel-Hex , Motorola S-Record 格式详细解析
CMake教程系列-05-选项及变量
Use of Arthas
IDEA 远程调试 Remote JVM Debug
zabbix 触发器详解
Implementation of Sanzi chess with C language
公司电脑强制休眠的3种解决方案
Global and Chinese market of subscription revenue management software 2022-2028: Research Report on technology, participants, trends, market size and share
What about punctuation in the first column of unity text
How to prevent duplicate submission under concurrent requests
JvxeTable子表记录加载完毕事件
Global and Chinese market of relay lens 2022-2028: Research Report on technology, participants, trends, market size and share
Quick sort, cluster index, find the k-largest value in the data
How to set password complexity and timeout exit function in Oracle