自定义MVC

目录

一.什么是MVC

1.1.三层架构和MVC的区别

二.自定义MVC工作原理图 

三.自定义mvc实现

3.1 创建web工程

 3.2 中央处理器

3.3 Action接口定义

3.4 实现子控制器

3.5 完善中央控制器

3.5.1 请求分发功能

3.5.2 使用配置文件配置action

3.5.3 请求参数处理

1. 定义接口

在中央处理器中加入请求参数的处理能力

 2.处理请求参数中的null及空字符串转换问题

为了更方面的处理请求参数中的null及空字符串,转换为数值型数据的问题,加入一个监听器,在应用启动时注册转换器。

3.6 完善Action

1.构建抽象类

2.自定义的Action子控制器示例:

发送请求,示例http://localhost:8080/mvc/studentAction.actionmethodName=addStudent&sid=100&age=23&addr=aabbcc

四.其他公用组件的集成

五.打jar包


一.什么是MVC

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范。用一种业务逻辑、数据、界面显示分离的方法,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。

MVC结构

  • Model:是应用程序中用于处理应用程序数据逻辑的部分,通常模型对象负责在数据库中存取数据。

  • View:是应用程序中处理数据显示的部分,通常视图是依据模型数据创建的。

  • Controller:是应用程序中处理用户交互的部分,通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

MVC是一个框架模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。最典型的MVC就是JSP + servlet + javabean的模式

  • Model:常用javabean去实现,通过各种类来对数据库的数据进行获取,并封装在对象当中。

  • View:常用JSP来实现,通过可直接观察的JSP页面来展示我们从数据库中获取的数据。

  • Controller:常用servlet来实现,通过servlet来获取经过javabean包装过的对象(已存入数据库中的数据),然后再发送数据传输到JSP界面。

1)不能跨层调用; 2)只能由上往下进行调用:View -> Controller -> Model

1.1.三层架构和MVC的区别

  1. 三层架构是基于业务逻辑来分的,而MVC是基于页面来分的;

  2. 三层是种软件架构,通过接口实现编程,MVC模式是一种复合设计模式,一种解决方案;

  3. 三层架构模式是体系结构模式,MVC是设计模式;

  4. 三层架构模式又可归于部署模式,MVC可归于表示模式。

二.自定义MVC工作原理图 

核心组件说明:

  • 中央控制器(ActionServlet): 复杂接收所有的请求,并分别给控制器具体处理。
  • 自控制器(Action):负责处理中央处理器分配的请求
  • 视图(view): jsp页面,负责显示
  • 模型(Model): 负责业务处理逻辑

三.自定义mvc实现

3.1 创建web工程

创建一个web工程,需要加入必要的依赖。

 3.2 中央处理器

通过servlet来实现一个中央控制器,负责所有请求的接收。(后续中央控制器在再将请求转发给各个子控制器,此处可以先把请求接进来,转发功能后面再加)

/*** 中央控制器,负责接收所有的请求并分别给控制器具体处理* @author Administrator*/
@WebServlet("*.action")
public class ActionDispatchServlet extends HttpServlet {@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) {doPost(request, response);}@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) {System.out.println("dopost ..... ");}}

3.3 Action接口定义

Action接口定义了每个子控制器需要遵循的行为,使得所有的子控制器都有一个同一的抽象类型,所以我们可以在中央控制器中使用Action接口类型来引用所有的子控制器。这样就为用户扩展自定义的子控制器提供了条件

/*** 每个子控制器必须实现该接口,负责处理中央处理器分配的请求* @author Administrator*/
public interface Action {/*** 处理请求* @param request  请求* @param response 响应* @return String 返回转发或重定向的jsp页面名称*/String exeute(HttpServletRequest request, HttpServletResponse response);}

3.4 实现子控制器

为方便调试,实现两个子控制器

public class BookAction implements Action {@Overridepublic String exeute(HttpServletRequest request, HttpServletResponse response) {return "bookList";}}
public class StudentAction implements Action {@Overridepublic String exeute(HttpServletRequest request, HttpServletResponse response) {// TODO Auto-generated method stubreturn "students";}}

3.5 完善中央控制器

为了便于理解,我们可以分步骤的,循序渐进的完善中央控制器:

  • 编写简单的请求分发实现功能
  • 实现通过配置文件来配置子控制器的功能
  • 完善请求参数处理功能

3.5.1 请求分发功能

为了在中央控制器中完成请求的分发,需要在中央控制器中维护所有子控制器的实例,并且能够依据请求路径,将请求转发给与其关联的子控制器。

/*** 中央控制器,负责接收所有的请求并分别给控制器具体处理* @author Administrator*/
@WebServlet("*.action")
public class ActionDispatchServlet extends HttpServlet {//用于保存path与action子控制器的映射public static Map<String, Action> actionMap = new HashMap<>();static {actionMap.put("/studentAction", new StudentAction());actionMap.put("/bookAction", new BookAction());}@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) {doPost(request, response);}@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) {String servletPath = request.getServletPath();String path = servletPath.split("\\.")[0];Action action = actionMap.get(path);String rpath = action.exeute(request, response);System.out.println(rpath);}}

3.5.2 使用配置文件配置action

在上面的示例中,在中央控制器中直接创建action子控制器,如果新增一个子控制器需要在中央控制器中添加,这样并不实用。 为了增加灵活性,可以将action转移到配置文件中配置,中央控制器通过配置来初始化action子控制器。

1 此时需要将config.xml文件的解析和建模项目的功能集成进来。
(ConfigModel,ActionModel,ForwardModel,ConfigModelFactory)

2 在项目的src目录下加入如下配置文件(config.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE config[<!ELEMENT config (action*)><!ELEMENT action (forward*)><!ELEMENT forward EMPTY><!ATTLIST actionpath CDATA #REQUIREDtype CDATA #REQUIRED><!ATTLIST forwardname CDATA #REQUIREDpath CDATA #REQUIREDredirect (true|false) "false">
]>
<config><action path="/studentAction" type="org.lisen.mvc.action.StudentAction"><forward name="students" path="/students/studentList.jsp" redirect="false"/></action>
</config>

 完善中央处理器,通过配置文件来获取子控制器配置

@WebServlet("*.action")
public class ActionDispatchServlet extends HttpServlet {//用于保存path与action子控制器的映射//public static Map<String, Action> actionMap = new HashMap<>();private static ConfigModel configModel;static {//actionMap.put("/students", new StudentAction());//actionMap.put("/books", new BookAction());configModel  = ConfigModelFactory.getConfigModel();}@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {doPost(request, response);}@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {String servletPath = request.getServletPath();String path = servletPath.split("\\.")[0];Action action = getActionByPath(path);String name = action.exeute(request, response);ForwardModel forwardModel = getForwardModel(path, name);if (forwardModel.isRedirect()) {response.sendRedirect(request.getContextPath() + "/" + forwardModel.getPath());} else {request.getRequestDispatcher(forwardModel.getPath()).forward(request, response);}}//通过请求路径获取对应的action实例private Action getActionByPath(final String path) {ActionModel action = configModel.find(path);try {Class<?> clazz = Class.forName(action.getType());return (Action)clazz.newInstance();} catch (Exception e) {throw new RuntimeException("创建Action实例异常"+e.getMessage(), e);}}public ForwardModel getForwardModel(String path, String name) {return configModel.find(path).find(name);}}

注: 本例的实现中Action子控制器是多例模式的,及每个请求对应一个Action实例

3.5.3 请求参数处理

1. 定义接口

/*** 对于需要处理请求参数的Action可以通过实现该接口获取请求参数的* 处理能力,中央控制器将会使用该接口来获取Model对象,并统一处理* 参数* @author Administrator*/
public interface ModelDrive {Object getModel();}

在中央处理器中加入请求参数的处理能力

@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {......Action action = getActionByPath(path);//处理请求参数if(action instanceof ModelDrive) {Object model = ((ModelDrive) action).getModel();if(model != null) {try {BeanUtils.populate(model, request.getParameterMap());} catch (Exception e) {throw new RuntimeException("在中央处理器中处理请求参数时发生异常", e);}}}String name = action.exeute(request, response);......
}

 2.处理请求参数中的null及空字符串转换问题


为了更方面的处理请求参数中的null及空字符串,转换为数值型数据的问题,加入一个监听器,在应用启动时注册转换器。

/*** ServletContextListener接口为Servlet API中的接口,用于监听ServletContext对象的生命周期。* 当Servlet 容器启动或终止Web 应用时,会触发ServletContextEvent事件,该事件由* ServletContextListener来处理。* @author Administrator*/
@WebListener
public class BeanUtilsListener implements ServletContextListener {/*** 当Servlet 容器终止Web 应用时调用该方法。在调用该方法之前,* 容器会先销毁所有的Servlet和Filter 过滤器。*/@Overridepublic void contextDestroyed(ServletContextEvent arg0) {// TODO Auto-generated method stub}/*** 当Servlet 容器启动Web应用时调用该方法。* 在调用完该方法之后,容器再对Filter 初始化,* 并且对那些在Web应用启动时就需要被初始化的Servlet进行初始化。*/@Overridepublic void contextInitialized(ServletContextEvent arg0) {ConvertUtils.register(new IntegerConverter(null), Integer.class);ConvertUtils.register(new FloatConverter(null), Float.class);ConvertUtils.register(new DoubleConverter(null), Double.class);ConvertUtils.register(new LongConverter(null), Long.class);ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);}}

3.6 完善Action

每个Action只能有一个execute方法,如果处理一个模块的增删改查则需要单独编写多个Action,这样会比较麻烦。如果在一个Action实例中可以处理多个请求方法,则框架会更加灵活。

  • 规定请求参数中必须包含一个“methodName”参数,用于指定处理请求的Action中的方法
  • 构建一个抽象类,该类实现Action子控制器接口,通过反射机制调用其子类中的方法,方法名有请求参数“methodName”指定。
  • 需要开发的Action子控制器,集成上一步构建的抽象类,编写的用于处理请求的方法名要与请求参数“methodName”指定的方法名匹配,同时需要HttpServletRequest和HttpServletResponse两个参数(保留该参数主要为了方面对请求的处理)

1.构建抽象类

public abstract class AbstractDispatchAction implements Action {@Overridepublic String exeute(HttpServletRequest request, HttpServletResponse response) {String methodName = request.getParameter("methodName");Class<? extends AbstractDispatchAction> clazz = this.getClass();try {Method method = clazz.getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);return (String)method.invoke(this, request,response);} catch (Exception e) {throw new RuntimeException("在调用Action中的["+methodName+"]方法是异常", e);} }}

2.自定义的Action子控制器示例:

public class StudentAction extends AbstractDispatchAction implements ModelDrive {private Student student = new Student();@Overridepublic Object getModel() {return student;}/*@Overridepublic String exeute(HttpServletRequest request, HttpServletResponse response) {		System.out.println("StudentAction = " + student);	return "students";}*/public String getStudents(HttpServletRequest request, HttpServletResponse response) {	System.out.println("getStudents");System.out.println("StudentAction = " + student);return "students";}public String addStudent(HttpServletRequest request, HttpServletResponse response) {System.out.println("addStudent");System.out.println("add student = " + student);return "students";}}

发送请求,示例
http://localhost:8080/mvc/studentAction.actionmethodName=addStudent&sid=100&age=23&addr=aabbcc

注意:在请求中需要添加一个methodName的固定参数,该参数指定了需要调用的Action中的方法的名称。

四.其他公用组件的集成

可以将通用分页,字符编码过滤器等组件一集成到mvc框架中便于复用。

五.打jar包

将自定义mvc框架打成jar包,以便于在其他项目中使用。

项目 --(右击)-->Export

 

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

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

相关文章

DTH11 温湿度模块

文章目录 前言一、DTH11 模块介绍二、设备树设置三、驱动程序四、测试程序五、上机测试及效果总结 前言 DHT11 是一款可测量 温度 和 湿度 的传感器。比如市面上一些空气加湿器&#xff0c;会测量空气中湿度&#xff0c;再根据测量结果决定是否继续加湿。 一、DTH11 模块介绍 …

iOS 单元测试之常用框架 OCMock 详解

目录 前言&#xff1a; 一、单元测试 1.1 单元测试的必要性 1.2 单元测试的目的 - 约束条件是否通过形式参数来传送。 1.3 单元测试依赖的两个主要框架 二、OCMock 的集成与使用 2.1 OCMock 的集成方式 2.2 OCMock 的使用方法 2.3 mock 使用限制 前言&#xff1a; OC…

【unity】ShaderGraph学习笔记

【unity】ShaderGraph学习笔记 创建ShaderGraph 创建URP的shaderGraph文件 在Project面板里Create→ShaderGraph→URP→这里主要有几个选项 Lit Shader Graph&#xff1a;有光照三维着色器 Unlit Shader Graph&#xff1a;无光照三维着色器 Sprite Custom Lit Shader Gra…

CNN(卷积神经网络)的实现过程详解

概要 在图像处理领域&#xff0c;CNN(卷积神经网络)处于绝对统治地位&#xff0c;但对于CNN具体是如何用神经网络实现的&#xff0c;能找到的介绍要么是一大堆数学公式&#xff0c;要么是大段晦涩的文字说明&#xff0c;读起来很是辛苦&#xff0c;想写好一片完整的而且有深度的…

【开源项目】低代码数据可视化开发平台-Datav

Datav 基本介绍 Datav是一个Vue3搭建的低代码数据可视化开发平台&#xff0c;将图表或页面元素封装为基础组件&#xff0c;无需编写代码即可完成业务需求。 它的技术栈为&#xff1a;Vue3 TypeScript4 Vite2 ECharts5 Axios Pinia2 在线预览 账号: admin 密码: 123123预…

Spring Cloud+Spring Boot+Mybatis+uniapp+前后端分离实现知识付费平台免费搭建

Java版知识付费-轻松拥有知识付费平台 多种直播形式&#xff0c;全面满足直播场景需求 公开课、小班课、独立直播间等类型&#xff0c;满足讲师个性化直播场景需求&#xff1b;低延迟、双向视频&#xff0c;亲密互动&#xff0c;无论是互动、答疑&#xff0c;还是打赏、带货、…

RocketMq 事务消息原理

Rocketmq 事务消息API使用 使用TransactionMQProducer类。 实现TransactionListener 接口覆盖其方法executeLocalTransaction和checkLocalTransaction 即可。 其中executeLocalTransaction 执行本地方法和checkLocalTransaction 事务状态回查。 玩法 简历一张本地事务表&…

回归预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 ![6 基本介绍 1.MATLAB实现TCN-BiGRU时间卷积双向门控循…

实现基于UDP简易的英汉词典

文章目录 实现目标认识相关接口socketbzerobindrecvfromsendto 实现思路和注意事项完整代码Server.hppServer.ccClient.hppClient.cc 运行效果END 实现目标 实现一个服务端和一个客户端&#xff0c;客户端负责发送一个单词&#xff0c;服务端接收到后将翻译后的结果返回发送到…

Android 之 动画合集之帧动画

本节引言&#xff1a; 从本节开始我们来探究Android中的动画&#xff0c;毕竟在APP中添加上一些动画&#xff0c;会让我们的应用变得 很炫&#xff0c;比如最简单的关开Activity&#xff0c;当然自定义控件动画肯定必不可少啦~而Android中的动画 分为三大类&#xff0c;逐帧动画…

了解uuid

目录 一.认识 UUID 二.UUID 会耗尽吗 三.UUID 会重复吗 四.UUID 的版本 五.UUID的应用 六.java 如何生成UUID 一.认识 UUID uuid是经过特定的算法得到的. UUID 是 16 字节 128 位长的数字&#xff0c;通常以 36 字节的字符串表示&#xff0c;示例如下&#xff1a; 3F2…

boardmix AI:让工作效率翻倍的AI智能在线白板软件!

随着ChatGPT热度的飙升&#xff0c;AI逐步深入到各个领域&#xff0c;尤其在技术领域&#xff0c;引发了一场AI的新浪潮&#xff0c;人们谈论的焦点都与AI有关。 AI工具不仅帮助企业节约了成本&#xff0c;还极大提高了生产力。那些尚未融入AI的行业和产品&#xff0c;有着被AI…

OSI 和 TCP/IP 网络分层模型详解(基础)

OSI模型: 即开放式通信系统互联参考模型&#xff08;Open System Interconnection Reference Model&#xff09;&#xff0c;是国际标准化组织&#xff08;ISO&#xff09;提出的一个试图使各种计算机在世界范围内互连为网络的标准框架&#xff0c;简称OSI。 OSI 七层模型 OS…

Windows环境部署安装Chatglm2-6B-int4

chatglm2-6B是最近比较火爆的大模型&#xff0c;可以在消费级显卡上部署使用&#xff0c;适合学习。但是一般人也不一定有那么高的硬件配置&#xff0c;所以部署个int4版本应该是大多数人的最好选择。我就在家里部署起了int4版本的chatglm2-6B&#xff0c;记录一下免得忘了。 …

【AST抽象语法树】结构分析及特性

什么是AST? AST译名抽象语法树&#xff08;Abstract Syntax Tree&#xff09;&#xff0c;是一种用于表示源代码结构的数据结构。 它在编译器、解析器和静态代码分析等领域中被广泛使用。 AST结构分析 我们利用成熟的astexplorer来进行结构化的比较和分析。可以尝试登录以下网…

树 - 前缀树(Trie Tree)

树 - 前缀树(Trie Tree&#xff09; 什么是前缀树前缀树的实现节点数据结构定义插入方法●非递归方式●递归方式 查询单词方法●非递归方式●递归方式 查询前缀方法●非递归方式●递归方式 前缀树的复杂度前缀树有哪些应用前缀树的压缩&#xff1a;基数树双数组Trie树(DoubleAr…

探讨ChatGPT的强化学习:AI学习与交互的未来

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

ES6基础知识八:你是怎么理解ES6中Proxy的?使用场景?

一、介绍 定义&#xff1a; 用于定义基本操作的自定义行为 本质&#xff1a; 修改的是程序默认形为&#xff0c;就形同于在编程语言层面上做修改&#xff0c;属于元编程(meta programming) 元编程&#xff08;Metaprogramming&#xff0c;又译超编程&#xff0c;是指某类计算…

ChatGPT和搜索引擎哪个更好用

目录 ChatGPT和搜索引擎的概念 ChatGPT和搜索引擎的作用 ChatGPT的作用 搜索引擎的作用 ChatGPT和搜索引擎哪个更好用 总结 ChatGPT和搜索引擎的概念 ChatGPT是一种基于对话的人工智能技术&#xff0c;而搜索引擎则是一种用于在互联网上查找和检索信息的工具。它们各自具…

kaggle新赛:Bengali.AI 语音识别大赛赛题解析

赛题名称&#xff1a;Bengali.AI Speech Recognition 赛题链接&#xff1a;https://www.kaggle.com/competitions/bengaliai-speech 赛题背景 竞赛主办方 Bengali.AI 致力于加速孟加拉语&#xff08;当地称为孟加拉语&#xff09;的语言技术研究。Bengali.AI 通过社区驱动的…