J2EE之自定义MVC框架知识(中篇)
前言
在上期J2EE之自定义MVC框架知识(上篇)中我们了解了一些自定义MVC框架在我们开发编程中带来的一些方便,但基于上篇博客中自定义MVC框架优化的代码还有可优化之处,这期J2EE之自定义MVC框架知识(中篇)将针对上期的博客代码进行进一步优化。让我们跟着思维导图一起来学习了解一下吧。
1.优化中央控制器中的action容器,使其加载变成可配置的
1.1 编写.xml文件(config.xml)
创建一个源文件夹(Source Folder)文件路径如下
<?xml version="1.0" encoding="UTF-8"?>
<!-- config标签:可以包含0~N个action标签 -->
<!DOCTYPE config [
<!ELEMENT config (action*)>
<!ELEMENT action (forward*)>
<!ELEMENT forward EMPTY>
<!ATTLIST action
path CDATA #REQUIRED
type CDATA #REQUIRED
>
<!ATTLIST forward
name CDATA #REQUIRED
path CDATA #REQUIRED
redirect (true|false) 'true'
>
]>
<config>
<!-- action标签:可以饱含0~N个forward标签 path:以/开头的字符串,并且值必须唯一 非空 ,子控制器对应的路径 type:字符串,非空,子控制器的完整类名 -->
<action path="/book" type="com.YX.Web.BookAction">
<forward name="success" path="/index.jsp" redirect="true" />
<forward name="failed" path="/register.jsp" redirect="false" />
</action>
<action path="/order" type="com.YX.Web.OrderAction">
<forward name="a" path="/index.jsp" redirect="false" />
<forward name="b" path="/welcome.jsp" redirect="true" />
</action>
</config>
1.2 导入XML建模相关的类
文件路径展示图
ActionModel类
package com.YX.framework.model;
import java.util.HashMap;
import java.util.Map;
/**
* @author 君易--鑨
* 2023年7月2日下午8:47:58
*
*/
public class ActionModel {
private String path;
private String type;
private Map<String, ForwardModel> fMap = new HashMap<String, ForwardModel>();
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
// 将forward往action中放 压栈
public void push(ForwardModel forwardModel) {
fMap.put(forwardModel.getName(), forwardModel);
}
// 从action中通过name值取出forward
public ForwardModel pop(String name) {
return fMap.get(name);
}
}
ConfigModel类
package com.YX.framework.model;
import java.util.HashMap;
import java.util.Map;
/**
* @author 君易--鑨
* 2023年7月2日下午8:47:58
*
*/
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);
}
public static void main(String[] args) throws Exception {
ConfigModel configModel = ConfigModelFactory.build();
ActionModel actionModel = configModel.pop("/loginAction");
ForwardModel forwardModel = actionModel.pop("success");
System.out.println(forwardModel.getPath());
}
}
ConfigModelFactory类
package com.YX.framework.model;
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种设计模式--工厂模式--创建型模式
* build/newinstance
* @author 君易--鑨
* 2023年7月2日下午8:50:10
*
*/
public class ConfigModelFactory {
public static ConfigModel build(String xmlPath) throws Exception {
ConfigModel configModel = new ConfigModel();
InputStream in = ConfigModelFactory.class.getResourceAsStream(xmlPath);
SAXReader sr = new SAXReader();
Document doc = sr.read(in);
// configModel要有类容,就意味着actionmodel要有类容,然后放入到configmodel中去
List<Element> actionEles = doc.selectNodes("/config/action");
for (Element actionEle : actionEles) {
// System.out.println(actionEle.asXML());
ActionModel actionModel = new ActionModel();
actionModel.setPath(actionEle.attributeValue("path"));
actionModel.setType(actionEle.attributeValue("type"));
// actionModel要有forwardModel,就意味着forwardmodel要有类容,然后放入到actionmodel中去
List<Element> forwardEles = actionEle.selectNodes("forward");
for (Element forwardEle : forwardEles) {
System.out.println(forwardEle.asXML());
ForwardModel forwardModel = new ForwardModel();
forwardModel.setName(forwardEle.attributeValue("name"));
forwardModel.setPath(forwardEle.attributeValue("path"));
// 只有填写false才是转发,其它都为重定向
// forwardModel.setRedirect(false);
forwardModel.setRedirect(!"false".equals(forwardEle.attributeValue("redirect")));
actionModel.push(forwardModel);
}
configModel.push(actionModel);
}
return configModel;
}
public static ConfigModel build() throws Exception {
return build("/config.xml");
}
public static void main(String[] args) throws Exception {
ConfigModelFactory.build();
}
}
ForwardModel类
package com.YX.framework.model;
/**
* @author 君易--鑨
* 2023年7月2日下午8:47:58
*
*/
public class ForwardModel {
// name、path、redirect
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 isRedirect() {
return redirect;
}
public void setRedirect(boolean redirect) {
this.redirect = redirect;
}
}
1.3 创建一个OrderAction类(用于测试效果)
package com.YX.Web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.YX.framework.Action;
/**订单操作方法类
* @author 君易--鑨
* 2023年7月2日下午8:53:06
*
*/
public class OrderAction extends Action{
/**
* 新增的方法
*
* @param request
* @param response
*/
public void add(HttpServletRequest request, HttpServletResponse response) {
System.out.println("调用了OrderAction新增的方法........");
}
/**
* 删除的方法
*
* @param request
* @param response
*/
public void del(HttpServletRequest request, HttpServletResponse response) {
System.out.println("调用了OrderAction删除的方法........");
}
/**
* 修改的方法
*
* @param request
* @param response
*/
public void upd(HttpServletRequest request, HttpServletResponse response) {
System.out.println("调用了OrderAction修改的方法........");
}
/**
* 查看的方法
*
* @param request
* @param response
*/
public void list(HttpServletRequest request, HttpServletResponse response) {
System.out.println("调用了OrderAction查看的方法........");
}
}
1.4 DispatherServlet类的代码优化
package com.YX.framework;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.management.RuntimeErrorException;
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.YX.Web.BookAction;
import com.YX.Web.OrderAction;
import com.YX.framework.model.ActionModel;
import com.YX.framework.model.ConfigModel;
import com.YX.framework.model.ConfigModelFactory;
/**
* 中央控制器
*
* @author 君易--鑨 2023年6月29日下午10:20:15
*
*/
@WebServlet("*.do")
public class DispatherServlet extends HttpServlet {
// public Map<String, Action> actionMap = new HashMap<String, Action>();
// 以前所有的子控制器释放到map集合中,现在所有的子控制器在mvc.xml中,其实就是放到模型对象中
private ConfigModel configmodle;
@Override
public void init() throws ServletException {
// actionMap.put("/book", new BookAction());
// actionMap.put("/order", new OrderAction());
try {
// configmodle包含了所有的子控制器
configmodle=ConfigModelFactory.build();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 拿到访问路径
String uri = request.getRequestURI();
// 截取获取路径
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
// 获取对应的操作的方法类
// Action action = actionMap.get(uri);
// 要通过uri=/book,在configmodle对象中找
ActionModel actionModel = configmodle.pop(uri);
if (actionModel==null) {
throw new RuntimeException("action not config");
}
// com.zking.Web.BookAction
String type = actionModel.getType();
// 反射实例化对象==BookAction bookaction=new BookAction();
Action action;
try {
action = (Action) Class.forName(type).newInstance();
// 调用识别方法类的方法
action.execute(request, response);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1.5 jsp文件测试代码
<%@ 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>
<p>自定义MVCk框架02 </p>
<a href="order.do?methodname=add">订单新增</a>
<a href="order.do?methodname=del">订单删除</a>
<a href="order.do?methodname=upd">订单修改</a>
<a href="order.do?methodname=list">订单查看</a>
<a href="book.do?methodname=add">书籍新增</a>
<a href="book.do?methodname=del">书籍删除</a>
<a href="book.do?methodname=upd">书籍修改</a>
<a href="book.do?methodname=list">书籍查看</a>
</body>
</html>
页面显示
点击功能控制台模拟输出结果(以订单查看、书籍删除为例)
1.6 注意事项:
- 实现对应操作功能之前确保.xml文件配置好了。
如下图中的功能
.xml文件配置图讲解(config.xml)
2.如果实现对应操作功能时.xml文件未配置。(案例如下)
jsp文件代码
<%@ 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>
<p>自定义MVCk框架02 </p>
<a href="order.do?methodname=add">订单新增</a>
<a href="order.do?methodname=del">订单删除</a>
<a href="order.do?methodname=upd">订单修改</a>
<a href="order.do?methodname=list">订单查看</a>
<a href="book.do?methodname=add">书籍新增</a>
<a href="book.do?methodname=del">书籍删除</a>
<a href="book.do?methodname=upd">书籍修改</a>
<a href="book.do?methodname=list">书籍查看</a>
<a href="good.do?methodname=list">商品查看</a>
</body>
</html>
页面显示
如果点击商品查看功能页面显示
1.7 弊端
中央控制器中的action容器配置不能灵活配置
2.针对反射调用的业务代码,优化页面跳转代码(以BookAction为例)
2.1 优化Action类代码
package com.YX.framework;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 子控制器(真正实现功能) 各操作方法的父类
*
* @author 君易--鑨 2023年6月29日下午9:48:19
*
*/
public class Action {
protected String execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取页面传来的方法参数,用于辨别执行对应操作的方法
String methodName = request.getParameter("methodname");
// 定义一个空变量接受方法结果
String res = "";
// 反射从获取类类开始 this:代表BookServlet类
try {
// 获取当前类的方法对象
Method sclass = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,
HttpServletResponse.class);
// 打开访问权限
sclass.setAccessible(true);
// 执行对应方法名对象的方法
// 变量接受方法结果
res = (String) sclass.invoke(this, request, response);
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
}
2.2 优化BookAction类代码
package com.YX.Web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.YX.framework.Action;
/**对应表的操作方法类
* @author 君易--鑨
* 2023年6月29日下午10:40:48
*
*/
public class BookAction extends Action{
//tolist:代表重定向;list:代表转发。
/**
* 新增的方法
*
* @param request
* @param response
*/
public String add(HttpServletRequest request, HttpServletResponse response) {
System.out.println("调用了BookAction新增的方法........");
request.setAttribute("content", "君易--鑨");
return "tolist";
}
/**
* 删除的方法
*
* @param request
* @param response
*/
public String del(HttpServletRequest request, HttpServletResponse response) {
System.out.println("调用了BookAction删除的方法........");
request.setAttribute("content", "君易--鑨");
return "tolist";
}
/**
* 修改的方法
*
* @param request
* @param response
*/
public String upd(HttpServletRequest request, HttpServletResponse response) {
System.out.println("调用了BookAction修改的方法........");
request.setAttribute("content", "君易--鑨");
return "tolist";
}
/**
* 查看的方法
*
* @param request
* @param response
*/
public String list(HttpServletRequest request, HttpServletResponse response) {
System.out.println("调用了BookAction查看的方法........");
request.setAttribute("content", "君易--鑨");
return "list";
}
}
2.3 修改.xml文件(config.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!-- config标签:可以包含0~N个action标签 -->
<!DOCTYPE config [
<!ELEMENT config (action*)>
<!ELEMENT action (forward*)>
<!ELEMENT forward EMPTY>
<!ATTLIST action
path CDATA #REQUIRED
type CDATA #REQUIRED
>
<!ATTLIST forward
name CDATA #REQUIRED
path CDATA #REQUIRED
redirect (true|false) 'true'
>
]>
<config>
<!-- action标签:可以饱含0~N个forward标签 path:以/开头的字符串,并且值必须唯一 非空 ,子控制器对应的路径 type:字符串,非空,子控制器的完整类名 -->
<action path="/book" type="com.YX.Web.BookAction">
<forward name="list" path="/res.jsp" redirect="false" />
<forward name="tolist" path="/res.jsp" redirect="true" />
</action>
<action path="/order" type="com.YX.Web.OrderAction">
</action>
</config>
2.4 创建重定向和转发的jsp页面
<%@ 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>
跳转成功,携带数据:${content }
</body>
</html>
2.5 优化DispatherServlet代码
package com.YX.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 com.YX.framework.model.ActionModel;
import com.YX.framework.model.ConfigModel;
import com.YX.framework.model.ConfigModelFactory;
import com.YX.framework.model.ForwardModel;
/**
* 中央控制器
*
* @author 君易--鑨 2023年6月29日下午10:20:15
*
*/
@WebServlet("*.do")
public class DispatherServlet extends HttpServlet {
// public Map<String, Action> actionMap = new HashMap<String, Action>();
// 以前所有的子控制器释放到map集合中,现在所有的子控制器在mvc.xml中,其实就是放到模型对象中
private ConfigModel configmodle;
@Override
public void init() throws ServletException {
// actionMap.put("/book", new BookAction());
// actionMap.put("/order", new OrderAction());
try {
// configmodle包含了所有的子控制器
configmodle=ConfigModelFactory.build();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 拿到访问路径
String uri = request.getRequestURI();
// 截取获取路径
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
// 获取对应的操作的方法类
// Action action = actionMap.get(uri);
// 要通过uri=/book,在configmodle对象中找
ActionModel actionModel = configmodle.pop(uri);
if (actionModel==null) {
throw new RuntimeException("action not config");
}
// com.zking.Web.BookAction
String type = actionModel.getType();
// 反射实例化对象==BookAction bookaction=new BookAction();
Action action;
try {
action = (Action) Class.forName(type).newInstance();
// 调用识别方法类的方法
// 具体业务代码执行后的返回值add/del/upd/list的返回值==》list/tolist
String res = action.execute(request, response);
// 通过返回值拿到,该方法结果是重定向还是转发那个页面
ForwardModel forwardModel = actionModel.pop(res);
if (forwardModel!=null) {
boolean redirect = forwardModel.isRedirect();
System.out.println(redirect);
String path=forwardModel.getPath();
if (redirect) {
response.sendRedirect(request.getContextPath()+"/"+path);
}else {
request.getRequestDispatcher(path).forward(request, response);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2.6 测试结果
增删改是重定向,查看是转发。
重定向页面输出结果和控制台输出结果
转发页面输出结果和控制台输出结果
2.7 弊端:
jsp传递到后台,封装到实体类的代码过多
2.8 注意事项:
如果画横线的代码是下面这样拼接的话
response.sendRedirect(path);
再jsp页面上实现增删改是跳转页面会出现下面这种情况
3.优化jsp页面参数传递后台的代码
3.1创建一个对应表的实体类(以Book类为例)
Book类代码
package com.YX.entity;
/**
* 实体类:书籍类
*
* @author 君易--鑨 2023年7月3日上午12:30:00
*
*/
public class Book {
// 定义属性
private int bid;
private int bname;
private float price;
/**
* 无参构造
*/
public Book() {
// TODO Auto-generated constructor stub
}
// 获取属性对应的get、set方法
public int getBid() {
return bid;
}
public void setBid(int bid) {
this.bid = bid;
}
public int getBname() {
return bname;
}
public void setBname(int bname) {
this.bname = bname;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
/**
* 有参构造
*
* @param bid
* @param bname
* @param price
*/
public Book(int bid, int bname, float price) {
super();
this.bid = bid;
this.bname = bname;
this.price = price;
}
// 实体对象信息输出语句体
@Override
public String toString() {
return "Book [bid=" + bid + ", bname=" + bname + ", price=" + price + "]";
}
}
3.2 创建一个接口类(所有的子控制器通用)
ModelDriver类
package com.YX.framework;
/**模型驱动接口
* @author 君易--鑨
* 2023年7月3日上午12:54:36
*
*/
public interface ModelDriver<T> {
T getModel();
}
3.3 优化子控制器代码(BookAction为例)
BookAction类
package com.YX.Web;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.YX.entity.Book;
import com.YX.framework.Action;
import com.YX.framework.ModelDriver;
/**对应表的操作方法类
* @author 君易--鑨
* 2023年6月29日下午10:40:48
*
*/
public class BookAction extends Action implements ModelDriver<Book>{
//tolist:代表重定向;list:代表转发。
/**
* 新增的方法
*
* @param request
* @param response
*/
// 实例化实体类
private Book book=new Book();
public String add(HttpServletRequest request, HttpServletResponse response) {
/*
* 1.要有表的内属性对象
* 2.获取到所有的参数及参数getParameterMap()
* 3.将参数值封装到表对应的对象中
* 4.实现通用
*/
// 获取到所有的请求参数值
Map<String, String[]> parameterMap = request.getParameterMap();
System.out.println("调用了BookAction新增的方法........");
request.setAttribute("content", "君易--鑨");
return "tolist";
}
/**
* 删除的方法
*
* @param request
* @param response
*/
public String del(HttpServletRequest request, HttpServletResponse response) {
System.out.println("调用了BookAction删除的方法........");
request.setAttribute("content", "君易--鑨");
return "tolist";
}
/**
* 修改的方法
*
* @param request
* @param response
*/
public String upd(HttpServletRequest request, HttpServletResponse response) {
System.out.println("调用了BookAction修改的方法........");
request.setAttribute("content", "君易--鑨");
return "tolist";
}
/**
* 查看的方法
*
* @param request
* @param response
*/
public String list(HttpServletRequest request, HttpServletResponse response) {
System.out.println("调用了BookAction查看的方法........");
request.setAttribute("content", "君易--鑨");
return "list";
}
@Override
public Book getModel() {
return book;
}
}
3.4 优化中央控制器的代码
DispatherServlet类
package com.YX.framework;
import java.io.IOException;
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.YX.framework.model.ActionModel;
import com.YX.framework.model.ConfigModel;
import com.YX.framework.model.ConfigModelFactory;
import com.YX.framework.model.ForwardModel;
/**
* 中央控制器
*
* @author 君易--鑨 2023年6月29日下午10:20:15
*
*/
@WebServlet("*.do")
public class DispatherServlet extends HttpServlet {
// public Map<String, Action> actionMap = new HashMap<String, Action>();
// 以前所有的子控制器释放到map集合中,现在所有的子控制器在mvc.xml中,其实就是放到模型对象中
private ConfigModel configmodle;
@Override
public void init() throws ServletException {
try {
// configmodle包含了所有的子控制器
configmodle=ConfigModelFactory.build();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 拿到访问路径
String uri = request.getRequestURI();
// 截取获取路径
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
// 获取对应的操作的方法类
// Action action = actionMap.get(uri);
// 要通过uri=/book,在configmodle对象中找
ActionModel actionModel = configmodle.pop(uri);
if (actionModel==null) {
throw new RuntimeException("action not config");
}
// com.zking.Web.BookAction
String type = actionModel.getType();
// 反射实例化对象==BookAction bookaction=new BookAction();
Action action;
try {
action = (Action) Class.forName(type).newInstance();
if (action instanceof ModelDriver) {//判断子控制器是否实现模型驱动接口
ModelDriver md=(ModelDriver) action;
// 获取对应实体对象
Object model = md.getModel();
Map<String, String[]> map = request.getParameterMap();
// 对应的对象的属性赋值
BeanUtils.populate(model, map);
}
// 调用识别方法类的方法
// 具体业务代码执行后的返回值add/del/upd/list的返回值==》list/tolist
String res = action.execute(request, response);
// 通过返回值拿到,该方法结果是重定向还是转发那个页面
ForwardModel forwardModel = actionModel.pop(res);
if (forwardModel!=null) {
boolean redirect = forwardModel.isRedirect();
System.out.println(redirect);
String path=forwardModel.getPath();
if (redirect) {
//重定向
response.sendRedirect(request.getContextPath()+"/"+path);
// response.sendRedirect(path);
}else {
//转发
request.getRequestDispatcher(path).forward(request, response);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.5 jsp页面测试代码
<%@ 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>
<p>自定义MVCk框架02 最终</p>
<a href="book.do?methodname=add&bid=1&bname=junyi&price=9.9">书籍新增</a>
<a href="book.do?methodname=del">书籍删除</a>
<a href="book.do?methodname=upd">书籍修改</a>
<a href="book.do?methodname=list">书籍查看</a>
</body>
</html>
3.6 项目文件架构
3.7 测试优化jsp页面参数传递后台的代码
当我们点击书籍新增时将参数传入后台
结束语
这期博客分享J2EE之自定义MVC框架知识如何去优化上期博客代码就到这里了,如果有老铁想继续学习了解关于J2EE之自定义MVC框架知识请关注我,注意后期博客发表。