自定义MVC引用XML配置文件实现

目录

前言

自定义MVC实现

1. 导入XML配置文件

2. 导入XML解析建模

3. 优化中央控制器

3.1 修改DisPathServlet中init初始化方法

3.2 修改ActionServlet逻辑处理流程

3.3  通过反射机制实例化子控制器类

3.4 中央控制器将请求委托给子控制器处理

3.5 根据请求结果码跳转页面

4. 反射赋值

4.1 创建接口DriverModel

4.2 实现接口类

4.3  反射对象赋值

5. 完整优化中央控制器实例

5.1 完整 DisPathServlet类代码

5.2 测试JSP页面

5.3 论证反射对象赋值

6. populate方法详解


前言

       在这篇 自定义MVC框架思想 中我已详细描述了工作原理及流程,本篇主要在此基础上继续做出优化,实现步骤如下:

自定义MVC实现

1. 导入XML配置文件

<?xml version="1.0" encoding="UTF-8"?>
<config><action path="/order" type="com.ycxw.servlet.OrderAction"><forward name="success" path="/index.jsp" redirect="true" /><forward name="failed" path="/register.jsp" redirect="false" /></action><action path="/book" type="com.ycxw.servlet.BookAction"><forward name="List" path="/book.jsp" redirect="false" /><forward name="toList" path="/index.jsp" redirect="true" /></action>
</config>

 将其部署到Source Folder文件中

 

 

2. 导入XML解析建模

这里就不一一详细解说了,可以去 XML建模 中了解详细建模实例。

 

3. 优化中央控制器

3.1 修改DisPathServlet中init初始化方法

在DisPathServlet的init方法中将原有Map集合方式替换成XML建模方式  

// 通过xml建模方法进行储存
    private ConfigModel configModel;

    @Override
    public void init() throws ServletException {
        /**
         * 初始化存值就是给每个施工员根据施工证进行存档:
         */
        try {
            // configModel包含了所有的子控制器
            configModel = ConfigModelFactory.build();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

3.2 修改ActionServlet逻辑处理流程

根据请求路径名获取ActionModel

这里如果查不到指定对象,请认真检查xml文件的配置,以及截取的内容是否与xml配置相同

/*** 获取请求路径*/String uri = request.getRequestURI();// 截取bookuri = 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.ycxw.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 ;}}

3.4 中央控制器将请求委托给子控制器处理

Action instance = (Action) Class.forName(type).newInstance();

// 业务代码执行后返回值

String execute = instance.execute(request, response);

3.5 根据请求结果码跳转页面

        // 通过返回值拿到,该方法结果是重定向还是转发,还是跳转哪个页面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);}}

 

4. 反射赋值

4.1 创建接口DriverModel<T>

package com.ycxw.framework;/*** 模型驱动接口* Book book = new Book();* @author 云村小威** @param <T>*/
public interface ModelDriver<T> {T getModel();
}

 

4.2 实现接口类

针对需要进行反射赋值的具体子控制器类,实现该接口DriverModel。

package com.ycxw.servlet;import java.io.IOException;
import java.util.Map;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import com.ycxw.entity.Book;
import com.ycxw.framework.Action;
import com.ycxw.framework.ModelDriver;/*** 施工类 继承子控制器* * @author 云村小威** @2023年6月29日 下午8:32:59*/
public class BookAction extends Action implements ModelDriver<Book>{//创建表对应的属性对象Book book = new Book();@Overridepublic Book getModel() {// TODO Auto-generated method stubreturn book;}public String load(HttpServletRequest req, HttpServletResponse resp) {//获取所有的参数Map<String, String[]> 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()方法中返回实例化后的对象。

 

4.3  反射对象赋值

再次修改ActionServlet中的业务逻辑处理流程,在反射调用方法之前,请先进行反射参数赋值操作。

/*** 获取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());}

5. 完整优化中央控制器实例

5.1 完整 DisPathServlet类代码

package com.ycxw.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;import com.ycxw.framework.model.ActionModel;
import com.ycxw.framework.model.ConfigModel;
import com.ycxw.framework.model.ConfigModelFactory;
import com.ycxw.framework.model.ForwardModel;/*** 中央控制器(ActionServlet)* * @author 云村小威** @2023年6月29日 下午8:14:38*/
@WebServlet("*.action")
public class DisPathServlet extends HttpServlet {private static final long serialVersionUID = 1L;// 通过xml建模方法进行储存private ConfigModel configModel;@Overridepublic void init() throws ServletException {/*** 初始化存值就是给每个施工员根据施工证进行存档:*/try {// configModel包含了所有的子控制器configModel = ConfigModelFactory.build();} catch (Exception e) {e.printStackTrace();}}protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// http://localhost:8080/MVC_project/book.action?methodName=delete.../*** 获取请求路径*/String uri = request.getRequestURI();// 截取bookuri = 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();// 通过反射创建对象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());}// 业务代码执行后返回值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);}}} catch (Exception e) {e.printStackTrace();}}}

5.2 测试JSP页面

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试</title>
</head>
<body><a href="${pageContext.request.contextPath }/book.action?methodName=add&bid=1&bname=aa&price=13">增加</a><a href="${pageContext.request.contextPath }/book.action?methodName=delete">删除</a><a href="${pageContext.request.contextPath }/book.action?methodName=edit">修改</a><a href="${pageContext.request.contextPath }/book.action?methodName=query">查询</a><a href="${pageContext.request.contextPath }/book.action?methodName=load">回显</a>
</body>
</html>

5.3 论证反射对象赋值

1. 通过debug调试,运行到当前通过反射拿到指定对象时为空

 

 2. 执行完populate方法后将自定赋值等效于遍历对象一个个赋值

BeanUtils.populate(bean, request.getParameterMap());

 

最后在讲解一下populate方法的解释:

6. populate方法详解

 

BeanUtils.populate(Object bean, Map properties)

BeanUtils位于org.apache.commons.beanutils.BeanUtils下,populate是BeanUtils工具类的一个方法。

作用:

        这个方法会遍历map<key, value>中的key,如果bean中有这个属性,就把这个key对应的value值赋给bean的属性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/8134.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

electron报错Error: Object has been destroyed

问题描述 在 Electron 中&#xff0c;当一个窗口被销毁后&#xff0c;与该窗口相关联的 JavaScript 对象也会被销毁&#xff0c;再次访问已被销毁的窗口对象时&#xff0c;会导致 Error: Object has been destroyed 错误。 例如之前在写多窗口pinia状态同步 / 多窗口样式同步的…

【PHP语言-PDO接口】PDO接口执行脚本操作数据库

目录 前言&#xff1a; 一、 PDO简介 二、 PDO对象方法 前言&#xff1a; PDO&#xff1a;数据库抽象层 简介&#xff1a;PDO扩展为PHP访问数据库定义了一个轻量级的、一致性的接口&#xff0c;PDO解决了数据库连接不统一的问题。 一、 PDO简介 1、PDO简介 &#xff08;1…

趣谈MySQL 多个%等模糊查询

一、建表并插入数据 1、创建一个people表 DROP TABLE IF EXISTS people; CREATE TABLE people (id int NOT NULL COMMENT 主键,name varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 姓名,sex tinyint NOT NULL COMMENT 性别,age int NOT N…

matlab——制作箱线图

在数据分析中&#xff0c;如果不知道数据分布的情况下很难判断中位数是否有效或者存在离群点。 离群点指偏离大多数点规律的点。 为了更有效对整体数据进行划分&#xff0c;提出四分位点的概念。即选取概念下界、0.25位点、0.75位点、概念上界。 有一种专门表现四分位点的图像叫…

2023年7月2日leetcode每日一题打卡——125.验证回文串

一、题目描述与要求 125. 验证回文串 - 力扣&#xff08;LeetCode&#xff09; 题目描述 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给…

Android仿淘宝、京东、拼多多搜索历史

详情见代码 &#xff1a;https://github.com/yixiaolunhui/FSearchHistory

ECShop 权限管理

如何增加一个新的权限 1、配置菜单所对应的权限code admin/includes/inc_priv.php $purview[02_cost_list] cost_list; 2、配置菜单的语言 languages/zh_cn/admincommon.php $_LANG[02_cost_list] 成本明细; 3、配置权限code的语言 languages/zh_cn/admin/priv_action.p…

【C++】类型转换和IO流

C完结 文章目录 前言一、C的四种类型转换二、IO流总结 前言 首先我们看看C语言中的类型转换&#xff1a; 在 C 语言中&#xff0c;如果 赋值运算符左右两侧类型不同&#xff0c;或者形参与实参类型不匹配&#xff0c;或者返回值类型与 接收返回值类型不一致时&#xff0c;就需…

[Android Studio]1.2计数器

所有要改的代码如下&#xff1a; MainActivity代码&#xff1a; package com.example.code02;import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; imp…

完全背包问题(二维数组 / 一维数组实现)

完全背包 完全背包的一维和二维dp数组 有 N 件物品和容量为 W 的背包&#xff0c;第 i 件物品的重量是 weight[i]&#xff0c;价值是 value[i] 每件物品都有无限个&#xff0c;即同一物品能够放入背包多次&#xff0c;求背包所能装入物品的最大价值总和 完全背包和 0-1 背包不…

微服务:Springboot集成Hystrix实现熔断、降级、隔离

文章目录 前言知识积累Springboot集成Hystrix1、maven依赖引入2、application开启feign的hystrix支持&#xff08;客户端配置限流降级熔断&#xff09;3、入口类增加EnableFeignClients EnableHystrix 开启feign与hystrix4、feign调用增加降级方法服务端配置限流降级熔断(选择使…

NSS [MoeCTF 2022]ezphp

NSS [MoeCTF 2022]ezphp 先看题目&#xff0c;看到这个就想到了BUU的mark love cat。但是完全不一样&#xff0c;这道题exit()在foreach()之前 法一且唯一&#xff1a; echo回显flag 如果要echo&#xff0c;那么不能exit&#xff0c;那么必须传flag&#xff08;get或者post&a…