目录
前言
自定义MVC实现
1. 导入XML配置文件
2. 导入XML解析建模
3. 优化中央控制器
3.1 修改DisPathServlet中init初始化方法
3.2 修改ActionServlet逻辑处理流程
3.4 中央控制器将请求委托给子控制器处理
3.5 根据请求结果码跳转页面
4. 反射赋值
4.1 创建接口DriverModel
4.2 实现接口类
4.3 反射对象赋值
在这篇 自定义MVC框架思想 中我已详细描述了工作原理及流程,本篇主要在此基础上继续做出优化,实现步骤如下:
将其部署到Source Folder文件中
这里就不一一详细解说了,可以去 XML建模 中了解详细建模实例。
在DisPathServlet的init方法中将原有Map集合方式替换成XML建模方式
// 通过xml建模方法进行储存
private ConfigModel configModel;
@Override
public void init() throws ServletException {
/**
* 初始化存值就是给每个施工员根据施工证进行存档:
*/
try {
// configModel包含了所有的子控制器
configModel = ConfigModelFactory.build();
} catch (Exception e) {
e.printStackTrace();
}
}
根据请求路径名获取ActionModel
这里如果查不到指定对象,请认真检查xml文件的配置,以及截取的内容是否与xml配置相同
/**
* 获取请求路径
*/
String uri = request.getRequestURI();
// 截取book
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
// 要通过uri->> /book,在configModel对象中找
ActionModel actionModel = configModel.pop(uri);
// 判断没找对象等于空就抛出异常
if (actionModel == null)
throw new RuntimeException("action not config");
/**
* 获取config文件中action标签的type属性值
* type指java类
* com.ycxw.servlet.BookAction
*/
String type = actionModel.getType();
3.3 通过反射机制实例化子控制器类
package com.xzs.framework;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 子控制器(action) 处理浏览器请求的类
*
* @author
*
* 2023年6月29日 下午8:30:32
*/
public class Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 获取methodName值,这里指前端点击功能传来的方法名
String methodName = request.getParameter("methodName");
//定义一个变量来保存返回值
String res = "";
/**
* this--->BookAction/BlogAction/PermissionAction...可能是很多对象
* 所以需要通过反射找到对象带request,response参数的methidName方法
*/
Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
m.setAccessible(true);
// 动态调用其方法
res = (String) m.invoke(this, request, response);
return res ;
}
}
Action instance = (Action) Class.forName(type).newInstance();
// 业务代码执行后返回值
String execute = instance.execute(request, response);
// 通过返回值拿到,该方法结果是重定向还是转发,还是跳转哪个页面
ForwardModel forwardModel = actionModel.pop(execute);
if (forwardModel != null) {
// 获取forwardModel是否从定向值
boolean redirect = forwardModel.isRedirect();
/**
* 获取xml元素path值
*/
String path = forwardModel.getPath();
// 判断是否为重定向
if (redirect) {
response.sendRedirect(request.getContextPath() + "/" + path);
} else {
request.getRequestDispatcher(path).forward(request, response);
}
}
package com.xzs.framework;
/**
* 模型驱动接口
* Book book = new Book();
* @author
*
* @param
*/
public interface ModelDriver {
T getModel();
}
针对需要进行反射赋值的具体子控制器类,实现该接口DriverModel。
package com.xzs.servlet;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.xzs.entity.Book;
import com.xzs.framework.Action;
import com.xzs.framework.ModelDriver;
/**
* 施工类 继承子控制器
*
* @author
*
* @2023年6月29日 下午8:32:59
*/
public class BookAction extends Action implements ModelDriver{
//创建表对应的属性对象
Book book = new Book();
@Override
public Book getModel() {
// TODO Auto-generated method stub
return book;
}
public String load(HttpServletRequest req, HttpServletResponse resp) {
//获取所有的参数
Map map = req.getParameterMap();
System.out.println("Book查询的业务逻辑");
try {
resp.sendRedirect("index.jsp");
} catch (IOException e) {
e.printStackTrace();
}
return "List";
}
public String query(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("Book查询的业务逻辑");
try {
resp.sendRedirect("index.jsp");
} catch (IOException e) {
e.printStackTrace();
}
return "List";
}
public String edit(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("Book修改的业务逻辑");
try {
resp.sendRedirect("index.jsp");
} catch (IOException e) {
e.printStackTrace();
}
return "toList";
}
public String delete(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("Book删除的业务逻辑");
try {
resp.sendRedirect("index.jsp");
} catch (IOException e) {
e.printStackTrace();
}
return "toList";
}
public String add(HttpServletRequest req, HttpServletResponse resp) throws Exception {
System.out.println("Book新增的业务逻辑");
req.getRequestDispatcher("index.jsp").forward(req, resp);
return "toList";
}
}
只要实现了DriverModel接口,则必须要对实体类进行初始化,并在getModel()方法中返回实例化后的对象。
/**
* 获取config文件中action标签的type属性值
* type指java类
* com.ycxw.servlet.BookAction
*/
String type = actionModel.getType();
// 通过反射创建对象
Action instance;
try {
instance = (Action) Class.forName(type).newInstance();
// 判断bookAction有没有实现ModelDriver接口
if (instance instanceof ModelDriver) {
// 向下转型获取接口方法
ModelDriver md = (ModelDriver) instance;
Object bean = md.getModel();
// 把获取的参数保存到该对象中
BeanUtils.populate(bean, request.getParameterMap());
}