MVC模式的设计思想.doc_第1页
MVC模式的设计思想.doc_第2页
MVC模式的设计思想.doc_第3页
MVC模式的设计思想.doc_第4页
MVC模式的设计思想.doc_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

MVC模式的设计思想MVC模式是一种近年来使用比较广泛的为许多IT厂家和开发者所认可的一种设计模式,它和Web应用程序并没有直接的关系(事实上,它在很多非WEB应用程序中得到了使用),它不仅使得系统层次分明、职责清晰,而且使得系统更易于维护。在MVC模式中的三个关键部件及其主要功能职责是:The Model Component:主要负责业务域的业务目标的实现。The View Component:主要负责对业务域的数据展现给客户端。The Controller Component:主要负责控制系统流程和用户输入状态在基于Java技术的Web应用程序中,Model部分的主要组件是JavaBean和EJB,View部分的主要组件是HTML和JSP程序,Controller部分的主要组件是Servlet部分。下面列出了一些使用MVC模式的好处:1、 它将业务逻辑与展现分离开来,避免了将业务逻辑与展现混杂在一起带来的显示的不一致性和业务逻辑代码重复地分布在用于展现的代码中。2、 层次清晰,易于开发者对这三个部分分工与协作,易于维护者识别不同的层次实施不同的维护策略。3、 系统具有更好的重用性,包括用户界面的重用和业务逻辑处理包的重用,特别是业务逻辑处理包,如果遵循相应的java规范,它不仅可以在web应用程序中使用,而且可以在包括桌面、分布式环境下的得到重用。4、 系统更易于扩展和移植。5、 系统更易于维护。6、 采用MVC模式开发的系统更健壮。7、 对于大型的应用程序优势更为明显。谈到设计模式,可以想一下我们常用的jsp+bean和jsp+servlet+bean的模式JSP Model1JSP Model2上图中,JSP Model1即JSP+JavaBean的模式,在这种模式下,处理客户端的请求和将输出展现给客户端都是由JSP页面负责的,在模式1中,整个过程没有Servlet的参与,它将主要的业务逻辑放到JavaBean中实现,而将页面展现和请求控制交给JSP处理。不可否认jsp的开发模式简化了开发Web应用程序的复杂度,但是其缺点是显而易见的,由于jsp是在html中嵌入java代码的方式实现的,不可避免地,它也面临很多问题:如页面展现与业务逻辑混合在一起,仍然无法在开发过程中将不同的角色更清晰地区分开来;jsp页面中将会夹杂大量的java代码,维护变得困难;同时,业务逻辑的改动也将面临动一发而影响全局的窘境。JSP Model2即JSP+Servlet+JavaBean的模式,它和模式1的最大不同是它多了Servlet层,用于控制用户的请求和将JavaBean的业务输出传递给JSP来展现,这样就将数据展现、业务控制、业务逻辑实现分离开来,这就是早期的MVC(ModelViewControl)模式。显然,这种模式相对于jsp+bean的模式来说应用程序更具扩展性和灵活性,并且更易于维护。但是这种简单的MVC模式也有缺点,第一、没有成熟的MVC框架中所带有的各种强大和实用的功能,第二、配置文件不好管理,成熟的MVC框架支持多配置文件,而servlet的配置都写在web.xml中,这会导致web.xml文件难以管理。因此有必要掌握一种成熟的MVC的开发框架。对于现有较成熟的Model-View-Control(MVC)框架而言,其解决的主要问题有下面几部分:1 将Web页面中的输入元素封装为一个(请求)数据对象。2 根据请求的不同,调度相应的逻辑处理单元,并将(请求)数据对象作为参数传入。3 逻辑处理单元完成运算后,返回一个结果数据对象。4 将结果数据对象中的数据与预先设计的表现层相融合并展现给用户。数据封装和持久性 在MVC的设计思想中,数据在不同层之间的传递是以数值对象的形式进行封装的,这里的数值对象是指不同层之间传输数据的容器,在不同的层中数据的传输应该封装在数值对象中(不可能把resultSet对象用于各层数据的传递,这有背于MVC的设计思想),这样能够提高网络传输效率(减少传输次数),同时使得维护更方便。通常数值对象就是一个Bean,它对数据库中的表或视图的字段进行了封装,一个数值对象可以看成表或视图中的一条记录。 一个简单的数据对象public class Userprivate String bh; private String name; public String getName() return name; public String getBh() return bh; public void setName(String name) = name; public void setBh(String bh) this.bh = bh; public User() 通常我们会这样做,控制器在接收提交请求后将request对象中提交过来的数据封装在User的实例中User user = new User();user.setBh(request.getParameter(“bh”);user.setName(request.getParameter(“Name”);然后将该数据对象作为参数传递给逻辑Bean或直接用数据访问对象来执行业务操作,UserDAO userDAO = new UserDAO();userDAO.insertUser(user); 或 User user = userDAO.getUser(request.getParameter(“bh”); List userList = userDAO.getUserList();数据底层的访问在UserDAO中进行,打开数据连接connection,查询得到结果集resultset将数据封装在User的实例中,关闭连接返回数值对象,或者调用statement对象进行更新操作。操作完毕后由控制器将获取的数值对象发往页面。 public User getUser(String id)throws SQLException Connection conn = null; try conn = this.ds.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(select * from user where id= + id +); User user = null; if (rs.next() user = new User(); user.setBh(rs.getString(bh); user.setBh(rs.getString(name); return user; finally conn.close(); 对于单条记录用user对象实例封装,那么对于多条记录集则是以List集合的形式进行封装,List集合中的每个对象就是一个user对象实例, public List getUserList() throws SQLException Connection conn = null; try conn = this.ds.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(select * from user); List userList = new ArrayList(); while (rs.next() User user = new User(); user.setBh(rs.getString(bh); user.setBh(rs.getString(name); userList.add(user); return userList; finally conn.close(); 上面的例子只是说明了MVC模式中的数据封装的思想,如果按照上面的例子写,你会发现要写好多的数值对象来映射数据库的表,对于查询的得到的结果集都要手动进行封装,一旦数据库的表发生了变化,那么改起来将非常的繁琐,因此在实际运用中应该采取效率更高的数据封装办法,通过ap对象代替数值对象并配合合适的数据持久层的支持就可以达到数据封装的自动化,从而提高我们的开发效率。综上所述,选择合适的MVC框架和数据持久层作为我们项目中的开发模式是很有必要的,通过对现在流行的MVC框架和数据持久层的了解,Spring+Ibatis的开发模式是很适合的一种。Spring的优点Spring提供了一套成熟而全面的基础框架,站在应用开发的实际角度来说,其最大的优势在于:Spring是一个从实际项目开发经验中抽取的,可高度重用的应用框架。Spring Framework中目前最引人注目的,也就是名为控制反转(IOC Inverse Of Control)或者依赖注入(DI Dependence Injection)的设计思想。IoC,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中,实现了组件真正意义上的即插即用。这也是Spring最具价值的特性之一但是,光一个单纯的设计模式并不能使得Spring如此成功,而Spring最成功的地方也并不仅仅在于采用了IOC/DI的设计。首先,Spring涵盖了应用系统开发所涉及的大多数技术范畴,包括MVC、ORM以及RemoteInterface等,这些技术往往贯穿了大多数应用系统的开发过程。Spring从开发者的角度对这些技术内容进行了进一步的封装和抽象,使得应用开发更为简便。其次,Spring并非一个强制性框架,它提供了很多独立的组件可供选择。Spring的基本配置和基础对象使用方法略Ibatis的优点略Ibatis的基本配置和核心对象使用方法略Ibatis在Spring中的配置和运用略Jstl表现技术的运用略实例 结合于Spring和Ibatis的实际运用我写了一个例子,例子中实现了一个简单的登录过程和一个订货单的主从表形式的增、删、改、查功能,以供大家参考。 我使用了Spring中的AbstractController控制器作为整个程序的基本的控制器,之所以这样做是考虑到简单实用的目的,同时能够实现主从表形式的数据输入,对于事务管理直接用ibatis中提供的事务管理功能,jsp页面统一存放在WEB-INFview下面,这样可以防止用户直接通过地址栏来访问jsp页面,jsp页面上用到的js脚本都以js文件的形式include到页面中,对于页面上的数据都以jstl的标签来输出达到页面简洁的目的。配置文件说明/WEB-INF/web.xml文件程序运行的主要配置文件,配置了各种系统变量,对spring的加载,日志的加载等等/WEB-INF/applicationContext.xml文件启动时由spring加载系统中用到的各种bean/WEB-INF/main-config.xml文件对系统管理模块中的请求/处理单元的配置/WEB-INF/indent-config.xml文件对订货单模块中的请求/处理单元的配置/WEB-INF/sqlMapConfig.xml文件Ibatis的核心配置文件WEB-INFclassescom user.xml文件用户模块的sql语句的映射文件WEB-INFclassescom common.xml文件公用模块的sql语句的映射文件WEB-INFclassescom indent.xml文件订货单模块的映射文件对于系统中用到的控制器,我首先对AbstractController进行了抽象,编写了SimpleController类,在SimpleController类中我加入了各控制器中都要用到的公用属性和公用的bean,并抽象出AbstractController的public abstract ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception;方法其它各模块则继承自SimpleController,实现该方法,这样就可以使用SimpleController类中的各种属性和方法。程序运行的具体流程如下首先访问站点的入口web/index.jsp文件文件中首先include了对jstl标签库的引用/WEB-INF/view/inc/head.jsp文件标签是重定向标签,该标签发出请求动作/loginInit.do到web容器,web容器依据web.xml中定义的请求映射动作 main *.do 将该动作交由main所定义的系统管理模块的引擎进行调度 main org.springframework.web.servlet.DispatcherServlet contextConfigLocation /WEB-INF/main-config.xml 1 该引擎接收到请求动作后,将该动作分发至系统管理逻辑处理单元就是/WEB-INF/main-config.xml文件 loginController loginController main-config.xml文件通过urlMapping中定义的请求动作与控制器的映射loginController将动作交由loginController所定义的控制器处理 login main usercode password 该控制器引用了applicationContext.xml文件中加载的bean和sqlMap实例以及对控制器处理请求后返回的视图属性的定义loginmaincom.manage.LoginController控制器主要实现了 public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception 方法,该方法主要是对请求动作进行处理并返回一个ModelAndView对象,ModelAndView类包含了逻辑单元返回的结果数据集和表现层信息 public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception (request.getMethod(); Map model = new HashMap(); Map userForm =null; Map userInfo = null; if(isGet(request) userForm = new HashMap(); userForm.put(usercode,A1118); userForm.put(password,123); model.put(userForm,userForm); return new ModelAndView(formView,model); else userForm = (Map)bean.fillMap(mainField, request); try sqlMap.startTransaction(); userInfo = (Map)sqlMap.queryForObject(user.selectUser, userForm.get(usercode); sqlMmitTransaction(); finally sqlMap.endTransaction(); if(userInfo = null) model.put(message, 没有找到该用户); model.put(userForm, userForm); returnView = formView; else model.put(message, 登录成功); model.put(userInfo, userInfo); returnView = successView; printMap(userInfo); request.getSession().setAttribute(userInfo, userInfo); return new ModelAndView(returnView, model); 这里我是用一个控制器对登录的初始化动作和登录提交动作进行控制,通过if(isGet(request)来区分,初始化动作中将用户信息封装在model中并通过return new ModelAndView(formView,model);formView是请求动作返回的视图,在配置文件中已经定义了loginmodel是返回的结果数据集将返回的视图和数据集交由urlMapping,urlMapping会根据applicationContext.xml中定义的 org.springframework.web.servlet.view.JstlView /WEB-INF/view/ .jsp viewResolver在返回的视图的字符串加上前缀/WEB-INF/view/和后缀.jsp,即/WEB-INF/view/login.jsp,然后通过main的调度引擎返回到login页面login 用户编号:input type=text name=usercode value=/ 用户密码:input type=text name=password value=/ Login页面上使用了jstl的标签进行输出。这样一个登录初始化的过程就完成,登录提交的原理和登录初始化的运行原理一样,在登录提交过程中我也是使用的com.manage.LoginController控制器,在提交过程中我通过userForm = (Map)bean.fillMap(mainField, request);方式将页面提交过来的表单数据封装在userForm中的(订货单模块中都是用bean.fillMap和bean.fillMaps来封装请求参数的),这里的mainField是一个字符串数组,由LoginController的父类SimpleController中定义,bean也是在SimpleController定义的mainField的作用是设置表单提交过来的字段,通过在配置文件中定义,这样可以避免硬编码, usercode password Bean的作用是将请求的表单中的数据以key和value 形式封装在Map中在提交过程中我使用了ibatis中的核心组件sqlMap,也是在配置文件中定义的Sqlap的调用方法如下 try sqlMap.startTransaction();开启事务 userInfo = (Map)sqlMap.queryForObject(user.selectUser, userForm.get(usercode); sqlMmitTransaction();提交事务 finally sqlMap.endTransaction();结束事务 (Map)sqlMap.queryForObject(user.selectUser, userForm.get(usercode);方法用于查询用户的信息,”user.selectUser”是对应于user.xml映射文件中的selectUser对sql语句的映射,userForm.get(usercode)是输入的参数 Id就是调用sql的引用名,parameterClass是输入的参数resultClass是返回的结果集封装的类sqlMap.queryForObject会根据输入的sql的引用名来完成查询和数据封装工作,如果找到记录,则封装在resultClass定义的对象中返回,没有找到则返回null执行完毕后,LoginController会返回main页面或login页面。整个程序中运行的流程大致相同,下面将对ibatis的使用进行说明示例中我使用了以下几种查询和数据库的操作l 查询订货单记录查询单条记录在订货单修改时用到,类为com.indent.IndentModController订货单是主从表关系,因此需要配置主表查询语句和从表查询语句sql的映射文件为indent.xml文件 Id:程序中对sql的引用名parameterClass:输入参数,resultClass:封装每条记录的类对于查询一条记录时ibatis直接返回resultClass中定义的封装数据的对象对于查询多条记录,ibatis会将每条记录封装在resultClass定义的对象实例中然后将所有这所对象封装在List中返回 Map indent = null; List indentList = null; try sqlMap.startTransaction(); indent=(Map)sqlMap.queryForObject(indent.getIndent,sellID);订货单主表记录 indentList = sqlMap.queryForList(indent.getIndentList,sellID);订货单从表记录 sqlMmitTransaction(); finally sqlMap.endTransaction(); l 动态条件查询动态条件查询是指通过查询页面提交的动态条件来组合不同的sql语句我们以前是通过String sql =”select * from table where bh=dd”If(request. getParameter(“par”)!=null& request. getParameter(“par”). length()0) sql += “ and field = ”+ request. getParameter(“par”)+”;.这种方式来组合的考虑到这个问题,ibatis引入了动态映射机制在订货单查询就用到了这种动态条件查询,对应的类是com.indent.IndentQueryController首先我通过indentForm = (Map)bean.fillMap(mainField, request);方法将查询条件封装在ap中然后将这个查询条件的对象交给sqlMap查询partCount = (Integer) sqlMap.queryForObject(indent.getIndentQueryCount, indentForm).intValue();获得了查询的记录数indentList=sqlMap.queryForList(indent.getIndentQuery, indentForm, skipResult, PAGE_SIZE);获得了分页的记录集sql映射是 = #orderDate1#) !CDATA(orderDate = #orderDate1#) !CDATA(orderDate 对于动态映射的配置,大家可以看的31-34页里面讲得很清楚l 操作语句操作语句包括订货单的插,改,删这里只说一下订货单的插入过程,类是com.indent.IndentAddSaveController首先IndentAddSaveController在获得提交保存的请求后,将订货单主表信息封装在map,从表信息封装在list中 Map indent = (Map)bean.fillMap(mainField,request); List indentList = bean.fillMaps(childField,request);然后通过事务管理,插入订货单主表信息,循环插入订货单子表信息 try sqlMap.startTransaction(); sqlMap.insert(indent.insertIndent,indent); for (int i = 0; i indentList.size(); i+) indentPart = (Map)indentList.get(i) ; indentPart.put(sellID,sellID);

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论