(一)Model的产生及处理
MVC的概念其实最早可以追溯到很久很久以前,并不是WEB开发过程中所首创, 但是,MVC也适合WEB上的开发,并真正的在WEB开发领域广泛应用。MVC的第一个字母M是Model,承载着View层和Controller之间 的数据传输,是数据传输的载体,通过Model层,解偶了View层和Controller层。 解偶View层和Controller层并不代表View层和Controller层之间没有关系,而是降低复杂度。
为了便于理解Model层在开发中所起的作用,先拿一个最简单的用户录入来举个 例子。假设要从表单中录入用户时需要填写用户名和年龄,表单提交后,服务器端的Servlet需要拿到表单内填写的内容(这里用 ServletRequest来得到数据是为了说明MVC框架中M层所起到的作用),为了得到请求的数据,Servlet的代码大至这样写
public class TestServlet extends HttpServlet
protected void doPost(ServletRequest request, ServletResponse response) throws IOException {
User user = new User();
user.setName(request.getParameter("name"));
user.setAge(Integer.parseInt(request.getParameter("age").toString())); //省略业务处理代码 ... }
}
分析这几行代码,主要干了四件事情
- 创建User对象
- 得到Request的参数,
- 转换age参数类型,
- 调用User对象的setter方法,为User对象赋予相关的值
经过这四个步骤,一个具有业务含义的User对象被创建,作为业务层Bean相 关代码的输入条件。从这几行代码里可以看出,Request中的数据转换成具有业务含义的对象,中间经历了四个“必要而繁琐”的步骤。如果程序员天天写这 样的代码,岂不是要疯掉?还好,虽然代码只能一行行的写,但是思想却是可以升华的。观察一下这四个步骤,其实每个步骤都不复杂,如果写一段代码能自动创建 业务对象,并且自动装配这个对象中各属性的值,那岂不是能省很多时间和精力,让程序员解放出来。
想法可以万能,代码不可万能,在要解放程序员的时间与精力之前,对这个业务类User和表单中的参数作一些约定,以便实现自动的装配框架。约定如下:
- User类必须有一个不包含任何参数的默认构造函数
- User类中的属性名字和表单中的输入控件的名称一样
- User类中的各属性必须有默认的getter、setter方法
那框架代码要实现什么功能呢?以这个例子来说,框架要自动的创建User对象,拿到Request中的参数值,转换类型后,赋给User对象相对应的属性。
有了上面的三条协定后,再有Java一个非常非常重要的功能--反射,的鼎力相助,上面的自动装配的功能可以得以实现
。一个比较直观的流程是先扫瞄类中的属性,遍历所有的属性,通过属性名生成
setter方法的函数名,通过反射的方法调用这些setter方法,setter方法的参数则通过从Request中得到,并转换成需要的类型,这里的
类型转换也是需要通过反射机制来完成(目前这个流程还只能转换java数据中的基本类型,对于复合类型的Bean,为了描述这个流程,暂时不展开论述)。
现在假设框架已经能自动的装配User对象,编写服务端代码时,
就不再关心如何从Request中取参数了,
只需按照前面的三个约定编写User类。但是事情还没有结束,既然自动装配了User对象,那前面示例的Servlet代码是不是可以变成这样?
这样的代码看起来却是有些奇怪,为什么doPost方法声明中只有一个ServletResponse参数,而没有ServletRequest参数?因为有框架的自动装配User对象,对于代码的编写者而言,就根本不需要关心ServletRequest这个对象
。
现在进行更大胆的一步假设,且约定所有的Servlet的执行会把
Request,Response运送(forward)到一个JSP页面,那么,服务端代码编写时,也不再需要考虑Response对象了,除了前面所
说的User类外,再加上一个,这个Servlet的doPost方法执行完后,要把Request,Response运送到那个页面,假如用
show_user.jsp这个页面显示被输入的用户信息。这个时候,回头再审视一下刚刚做出的假设,会自然的得出下面的结论,可以编写一个与
Request、Response无关的类,只关注User类如何编写,返回一个代表要forward的JSP页面,User对象的装配工作,以及
forward本身的这个代码调用都可以交给框架去统一的管理,那真正要编写的服务端代码可以象是这样的
。
public class TestAction { private User user; public void setUser(User user){
this.user = user;
} public String execute(ModelVehicle modelVehicle) {
//业务代码实现
.... .... ....
modelVehicle.add("user", user);
return "show_user.jsp";
}
}
是不是很像Spring
MVC的controller类?为了避免和MVC术语中的Controller这个词冲突,仍然叫它Action吧。这个类已经完全和
Request,Response无关,当它被框架激活执行的时候,它首选需要框架为它准备好User对象,并且调用setUser方法,赋予
TestServlet对象user这个属性,然后execute方法被执行,执行了真正的业务逻辑,同时,把需要在show_user.jsp页面上显
示的数据放到ModelVehicle对象中去,TestAction这个对象执行完execute方法后,需要委托框架把ModelVehicle对象
中的数据forward到show_user.jsp这个页面上。
注意,这里有两个非常重要的约定,就是Action类必须有
- public String execute(ModelVehicle modelVehicle)
这个方法的声明,需要显示到页面上的数据,按照约定,须在execute执行过程中放到ModelVehicle对象中去。为了编写的方便,可以继承一个声明了此方法的抽象类。
基于这样的服务端代码编写方式,需要框架再提供什么功能呢?这里就引出MVC框架中C需要关注的事情:
- 保证一个URI请求优先被框架先拦截,框架能根据这个URI知道哪个Action类会被创建,
- Action类的execute方法被执行,需要把ModelVehicle中的数据一并forward到Action类execute方法返回的JSP页面。
因为这里还是重点介绍Model层的事,Controller层的事会在后面继续介绍,其实,Controller是MVC框架中一个枢纽,需要花点篇幅去探讨。
从探讨Model层的过程中,我们发现在Action类中向JSP页面输出数据
时,也是采用了Model方式。但是这个Model在处理起来相对简单的多,JSP
2.0规范中的JSTL标签库很容易的将Request中的属性在页面上显示出来,而且还能做一些简单的运算。因此,MVC框架中Model层的主要关注
点是如何把请求的数据自动装配成Action所需要的bean,除此外,框架Model层还可以提供复合bean自动装配、输入校验、本地化及国际化、字
符集编码转换、多重输出等功能。但是一切的起点是Model层的java bean编写遵照了这三个基本的约定:
- 必须有一个不包含任何参数的默认构造函数
- 属性名字和表单中的输入控件的名称一样
- 各属性必须有默认的getter、setter方法
正是有了这三个约定,让MVC框架Model层实现变得简单,一个好的约定让软件开发变得简单
(一)Model的产生及处理的更多相关文章
- Spring Boot笔记一
Spring Boot 入门 Spring Boot 简介 > 简化Spring应用开发的一个框架:> 整个Spring技术栈的一个大整合:> J2EE开发的一站式解决方案: 微服务 ...
- 【疯狂造轮子-iOS】JSON转Model系列之二
[疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...
- 【疯狂造轮子-iOS】JSON转Model系列之一
[疯狂造轮子-iOS]JSON转Model系列之一 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 之前一直看别人的源码,虽然对自己提升比较大,但毕竟不是自己写的,很容易遗 ...
- 详解树莓派Model B+控制蜂鸣器演奏乐曲
步进电机以及无源蜂鸣器这些都需要脉冲信号才能够驱动,这里将用GPIO的PWM接口驱动无源蜂鸣器弹奏乐曲,本文基于树莓派Mode B+,其他版本树莓派实现时需参照相关资料进行修改! 1 预备知识 1.1 ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(上)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- 拨开迷雾,找回自我:DDD 应对具体业务场景,Domain Model 到底如何设计?
写在前面 除了博文内容之外,和 netfocus 兄的讨论,也可以让你学到很多(至少我是这样),不要错过哦. 阅读目录: 迷雾森林 找回自我 开源地址 后记 毫无疑问,领域驱动设计的核心是领域模型,领 ...
- 使用mybatis-generator在自动生成Model类和Mapper文件
使用mybatis-generator插件可以很轻松的实现mybatis的逆向工程,即,能通过表结构自动生成对应的java类及mapper文件,可以大大提高工作效率,并且它提供了很多自定义的设置可以应 ...
- “RazorEngine.Templating.TemplateParsingException”类型的异常在 RazorEngine.NET4.0.dll 中发生,但未在用户代码中进行处理 其他信息: Expected model identifier.
这个问题是由于在cshtml中 引用了model这个单词 它可能和Model在解析时有冲突. 解决方法:把model换成别的单词就可以了.
- QT内省机制、自定义Model、数据库
本文将介绍自定义Model过程中数据库数据源的获取方法,我使用过以下三种方式获取数据库数据源: 创建 存储对应数据库所有字段的 结构体,将结构体置于容器中返回,然后根据索引值(QModelIndex) ...
- iOS自定义model排序
在开发过程中,可能需要按照model的某种属性排序. 1.自定义model @interface Person : NSObject @property (nonatomic,copy) NSStri ...
随机推荐
- react路由配置(未完)
React路由 React推了两个版本 一个是react-router 一个是react-router-dom 个人建议使用第二个 因为他多了一个Link组件 Npm install react-ro ...
- vue的实例
vue的实例 创建一个vue实例的写法和创建一个变量一样 var vm = new Vue{{ //我们一般用vm来接收vue的实例,vm是 ViewModel的缩写 }} 然后,我们就可以给vue实 ...
- Case Helper
using System; using Microsoft.Xrm.Sdk; using Microsoft.Crm.Sdk.Messages; using Microsoft.Xrm.Sdk.Que ...
- 献给初学者:小白该如何学习Linux操作系统
一. 选择适合自己的Linux发行版 谈到linux的发行版别,太多了,可能谁也不能给出一个准确的数字,但是有一点是能够必定的,linux正在变得越来越盛行, 面临这么多的Linux 发行版,打算从别 ...
- 通过devmem访问物理地址
目录 1.写在前面 2.devmem使用 3.应用层 4.内核层 1.写在前面 最近在调试时需要在用户层访问物理内存,发现应用层可以使用devmem工具访问物理地址.查看源码,实际上是对/dev/me ...
- js闭包的理解-目前网上分析的最透彻文章
js的闭包对于大家实际上并不陌生,但是真正敢说自己完全理解的人并不多.笔者在网上看到分析闭包的文章非常多,篇幅用的非常多,但是实际上分析的并不到位,或者根本就是不正确的.我有时候都在想,写这些文章的人 ...
- 【机器学习笔记】自组织映射网络(SOM)
什么是自组织映射? 一个特别有趣的无监督系统是基于竞争性学习,其中输出神经元之间竞争激活,结果是在任意时间只有一个神经元被激活.这个激活的神经元被称为胜者神经元(winner-takes-all ne ...
- 在ubuntu trusty下安装python的rasterio库
就这些吧.. apt-get update -y apt-get install -y software-properties-common add-apt-repository ppa:ubuntu ...
- android学习八 多用途碎片
碎片设计初衷:帮助开发人员管理应用程序功能. 特点:1.大量重用 2.可用性强 3.适应多种布局 碎片 1.包含一个视图层次结构和具有相应 ...
- uvaoj455Periodic Strings(枚举)
A character string is said to have period k if it can be formed by concatenating one or more repetit ...