当前位置:网站首页>简单自定义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后,我们对此进行了优化,优化后减少了代码量,缩短开发时间。
本次的内容分享到这。如有错误,还望指正。
边栏推荐
- Quick sort, cluster index, find the k-largest value in the data
- How can redis+aop customize annotations to achieve flow restriction
- What about punctuation in the first column of unity text
- Some technology sharing
- Three solutions to forced hibernation of corporate computers
- 【实战技能】如何撰写敏捷开发文档
- CMake教程系列-02-使用cmake代码生成二进制
- Idea remote debugging remote JVM debug
- Mysql表数据比较大情况下怎么修改添加字段
- Distributed file system fastdfs
猜你喜欢

Summary of PHP test sites encountered in CTF questions (I)

2.8 【 weight of complete binary tree 】

Unity3d ugui force refresh of layout components

LeetCode 3. 无重复字符的最长子串

发现mariadb数据库时间晚了12个小时

Use compose to realize the effect of selecting movie seats by panning tickets

Federal learning: dividing non IID samples by Dirichlet distribution

Some configuration details about servlet initial development

CMake教程系列-02-使用cmake代码生成二进制

Software testing skills, JMeter stress testing tutorial, transaction controller of logic controller (25)
随机推荐
What about punctuation in the first column of unity text
Recursion frog jumping steps problem
threejs 镜子案例Reflector 创建镜子+房子搭建+小球移动
PHP two-dimensional array randomly fetches a random or fixed number of one-dimensional arrays
C console format code
Add a custom button to jvxetable
Comparable和Comparator的区别
shell统计某个字符串最后一次出现的位置之前的所有字符串
Xunwei enzhipu ITop - imx6 Development Platform
[Postgres] Postgres database migration
Idea remote debugging remote JVM debug
NLP text summary: data set introduction and preprocessing [New York Times annotated corpus]
Prompt learning a blood case caused by a space
How to set password complexity and timeout exit function in Oracle
O & M (21) make winpe startup USB flash disk
What kind of foreign exchange trading platform is regulated and safe?
2. 成功解决 BUG:Exception when publishing, ...[Failed to connect and initialize SSH connection...
【微信小程序】条件渲染 列表渲染 原来这样用?
快速排序、聚簇索引、尋找數據中第k大的值
oracle怎么设置密码复杂度及超时退出的功能