(一)Model的产生及处理

MVC的概念其实最早可以追溯到很久很久以前,并不是WEB开发过程中所首创, 但是,MVC也适合WEB上的开发,并真正的在WEB开发领域广泛应用。MVC的第一个字母M是Model,承载着View层和Controller之间 的数据传输,是数据传输的载体,通过Model层,解偶了View层和Controller层。 解偶View层和Controller层并不代表View层和Controller层之间没有关系,而是降低复杂度。

为了便于理解Model层在开发中所起的作用,先拿一个最简单的用户录入来举个 例子。假设要从表单中录入用户时需要填写用户名和年龄,表单提交后,服务器端的Servlet需要拿到表单内填写的内容(这里用 ServletRequest来得到数据是为了说明MVC框架中M层所起到的作用),为了得到请求的数据,Servlet的代码大至这样写

Java代码

    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()));  

                //省略业务处理代码 ...   

          }
    }  

分析这几行代码,主要干了四件事情

  1. 创建User对象
  2. 得到Request的参数,
  3. 转换age参数类型,
  4. 调用User对象的setter方法,为User对象赋予相关的值

经过这四个步骤,一个具有业务含义的User对象被创建,作为业务层Bean相 关代码的输入条件。从这几行代码里可以看出,Request中的数据转换成具有业务含义的对象,中间经历了四个“必要而繁琐”的步骤。如果程序员天天写这 样的代码,岂不是要疯掉?还好,虽然代码只能一行行的写,但是思想却是可以升华的。观察一下这四个步骤,其实每个步骤都不复杂,如果写一段代码能自动创建 业务对象,并且自动装配这个对象中各属性的值,那岂不是能省很多时间和精力,让程序员解放出来。

想法可以万能,代码不可万能,在要解放程序员的时间与精力之前,对这个业务类User和表单中的参数作一些约定,以便实现自动的装配框架。约定如下:

  1. User类必须有一个不包含任何参数的默认构造函数
  2. User类中的属性名字和表单中的输入控件的名称一样
  3. User类中的各属性必须有默认的getter、setter方法

那框架代码要实现什么功能呢?以这个例子来说,框架要自动的创建User对象,拿到Request中的参数值,转换类型后,赋给User对象相对应的属性。

有了上面的三条协定后,再有Java一个非常非常重要的功能--反射,的鼎力相助,上面的自动装配的功能可以得以实现
。一个比较直观的流程是先扫瞄类中的属性,遍历所有的属性,通过属性名生成
setter方法的函数名,通过反射的方法调用这些setter方法,setter方法的参数则通过从Request中得到,并转换成需要的类型,这里的
类型转换也是需要通过反射机制来完成(目前这个流程还只能转换java数据中的基本类型,对于复合类型的Bean,为了描述这个流程,暂时不展开论述)。

现在假设框架已经能自动的装配User对象,编写服务端代码时,
就不再关心如何从Request中取参数了,
只需按照前面的三个约定编写User类。但是事情还没有结束,既然自动装配了User对象,那前面示例的Servlet代码是不是可以变成这样?

Java代码

    public class TestServlet  extends HttpServlet  

          private User user;  

          protected void doPost(ServletResponse response) throws IOException {  

                //省略业务处理代码 ...
          }  

          public void setUser(User user) {
                this.user = user;
          }
    }  

这样的代码看起来却是有些奇怪,为什么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本身的这个代码调用都可以交给框架去统一的管理,那真正要编写的服务端代码可以象是这样的

Java代码

    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类必须有

Java代码  

  1. public String execute(ModelVehicle modelVehicle)

这个方法的声明,需要显示到页面上的数据,按照约定,须在execute执行过程中放到ModelVehicle对象中去。为了编写的方便,可以继承一个声明了此方法的抽象类。

基于这样的服务端代码编写方式,需要框架再提供什么功能呢?这里就引出MVC框架中C需要关注的事情:

  1. 保证一个URI请求优先被框架先拦截,框架能根据这个URI知道哪个Action类会被创建,
  2. 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编写遵照了这三个基本的约定:

  1. 必须有一个不包含任何参数的默认构造函数
  2. 属性名字和表单中的输入控件的名称一样
  3. 各属性必须有默认的getter、setter方法

正是有了这三个约定,让MVC框架Model层实现变得简单,一个好的约定让软件开发变得简单

时间: 2024-08-11 09:51:52

(一)Model的产生及处理的相关文章

Data Model for Message Receiver

1. Physical Data Model 2. SQL Statements drop database MessageReceiver go /*==============================================================*/ /* Database: MessageReceiver */ /*==============================================================*/ create dat

springMVC:modelandview,model,controller,参数传递

转载:http://blog.csdn.net/wm5920/article/details/8173480 1.web.xml 配置: copy <> ></> ></> > >> ></> ></> > ></> </> <> ></> ></> </> 这样,所有的.htm的请求,都会被Dispatche

NHibernate框架与BLL+DAL+Model+Controller+UI 多层架构十分相似--『Spring.NET+NHibernate+泛型』概述、知识准备及介绍(一)

原文://http://blog.csdn.net/wb09100310/article/details/47271555 1. 概述 搭建了Spring.NET+NHibernate的一个数据查询系统.之前没用过这两个框架,也算是先学现买,在做完设计之 后花了一周搭建成功了.其中,还加上了我的一些改进思想,把DAO和BLL之中相似且常用的增删改查通过泛型T抽象到了DAO和BLL的父类中,其DAO 和BLL子类只需继承父类就拥有了这些方法.和之前的一个数据库表(视图)对应一个实体,一个实体对应一

asp.net mvc 提交model 接收不了

[HttpPost]        //[ValidateInput(false)]        public ActionResult AddNews1(_54Young_News_Model.model.gou54contentall contentmodel, _54Young_News_Model.model.gou54user usermodel)        {} 发现用一些特殊符号提交不了, 然后以为说前端问题,把model去掉就可以了. 后面觉得是因为有特殊符号影响到转mod

Django操作model时,报错:AttributeError:’ProgrammingError’ object has no attribute ‘__traceback__’

原因:在Django项目下相应的应用下面的models.py配置的model(也就是class)没有创建成相应的表. 这是怎么回事呢? 首先,将models.py里面的model创建成对应的数据库表的执行命令(DOS命令)为:manage.py syncdb. 但是我自己的电脑上执行该命令时,显示.Unknown command:syncdb.执行,manage.py help后的确没有发现这个子命令.最后网上搜索发现这个命令已经在Django1.9里面取消了.并且stackoverflow里面

使用AutoMapper实现Dto和Model的自由转换(上)

在实际的软件开发项目中,我们的"业务逻辑"常常需要我们对同样的数据进行各种变换.例如,一个Web应用通过前端收集用户的输入成为Dto,然后将Dto转换成领域模型并持久化到数据库中.另一方面,当用户请求数据时,我们又需要做相反的工作:将从数据库中查询出来的领域模型以相反的方式转换成Dto再呈现给用户.有时候我们还会面临更多的数据使用需求,例如有多个数据使用的客户端,每个客户端都有自己对数据结构的不同需求,而这也需要我们进行更多的数据转换. 频繁的数据转换琐碎而又凌乱,很多时候我们不得不:

使用AutoMapper实现Dto和Model的自由转换(中)

在上一篇文章中我们构造出了完整的应用场景,包括我们的Model.Dto以及它们之间的转换规则.下面就可以卷起袖子,开始我们的AutoMapper之旅了. [二]以Convention方式实现零配置的对象映射 我们的AddressDto和Address结构完全一致,且字段名也完全相同.对于这样的类型转换,AutoMapper为我们提供了Convention,正如它的官网上所说的: 引用 AutoMapper uses a convention-based matching algorithm to

使用AutoMapper实现Dto和Model的自由转换(下)

书接上文.在上一篇文章中我们讨论了使用AutoMapper实现类型间1-1映射的两种方式--Convention和Configuration,知道了如何进行简单的OO Mapping.在这个系列的最后一篇文章我想基于我们的需求讨论一些中级别的话题,包括:如何实现类型体型之间的映射,以及如何为两个类型实现多个映射规则. [四]将一个类型映射为类型体系 先回顾一下我们的Dto和Model.我们有BookDto,我们有Author,每个Author有自己的ContactInfo.现在提一个问题:如何从

棋盘的多米诺覆盖:Dimer Lattice Model,Pfaff 多项式,Kasteleyn 定理

这次来介绍计数组合学里面一个经典的问题:Dimer Lattice Model.问题是这样的:一个有 64 个方格的国际象棋棋盘,有多少种不同的多米诺骨牌覆盖?这里的覆盖是指不重复不遗漏地盖住整个棋盘. 下图是一种可能的覆盖方式(图片来自 Wiki 百科): 这个问题的答案是 12988816,非常大的一个数字,绝对不是一个一个数出来的.1961 年德国物理学家 Kasteleyn 借助于线性代数中的一个结论首先解决了这个问题,我们接下来就介绍他的方法. ~~~~~~~~~~~~~~~~~~~~

RailsCast26 Hackers Love Mass Assignment rails中按params创建、更新model时存在的安全隐患

Mass assignment是rails中常用的将表单数据存储起来的一种方式.不幸的是,它的简洁性成了黑客攻击的目标.下面将解释为什么及如何解决. 上述表单为一个简单的注册表单.当用户填入name,点击提交时,一个新用户被创建.用户模型被如下定义: ruby create_table :users do |t| t.string :name t.boolean :admin, :default => false, :null => false end 当用户点击提交时,如下的action被执