文档章节

MVC模式与Struts2框架的作用

FansUnion
 FansUnion
发布于 2015/10/22 10:33
字数 2220
阅读 47
收藏 0
点赞 0
评论 0
郑重申明:包括本文在内的很多技术文章,大多出自山外高人,而非Fans。
                  Fans暂时没有能力写作优秀的技术文章,Fans只是转载、浓缩、加入部分自己的代码而已。

   MVC模式实际上是众多经典的Java开发模式中的一种。它的基本原理是通过元素分解,来处理基于“请求-响应”模式的程序中的各种问题。

    M (Model)—数据模型  V (View)—视图展现     C(Control)—控制器

 

   任何一个B/S应用,其本质实际上是一个“请求-响应”的处理过程的集合体。那么MVC模式是如何被提炼出来并成为一个模式的呢? 我们来模拟一个“请求-响应”的过程,如图2-7所示。

 
图2-7 请求-响应模式

在整个请求-响应过程中,有哪些元素是必不可少的呢?

数据模型

在图中,就是顺着箭头方向进行传输的数据,它们是程序的核心载体,也是贯穿程序运行的核心内容。

对外交互

在图中,对外交互表现为一个“头”和一个“尾”。“头”指的是请求发起的地方,没有请求,一切之后的所有内容都无从谈起。“尾”指的是逻辑执行完成后,对外展现出来的执行结果。在传统意义上,我们利用HTML扩展的技术(如JSP等)来实现对外交互,在展现结果时,我们还需要完成一定的展现逻辑,比如错误展示、分支判断,等等。

程序的执行和控制

实际上它不仅是接受请求数据的场所,也是处理请求的场所。在请求处理完毕之后,它还要负责响应跳转。这个部分可能会存在着不同的表现形式。以前,我们用JSP和Servlet,后来用Struts1或者Struts2的Action。而这一变化,实际上包含了我们不断对程序进行重构的过程。

 

上面这3大元素,在不同的年代被赋予了不同的表现形式。例如,在很久以前,我们使用Servlet或者JSP来编写程序跳转的控制过程,有了Struts1.X后,我们使用框架所定义的Action类来处理。这些不同的表现形式有的受到时代的束缚,表现形式非常落后,有的甚至已经不再使用。但是我们忽略这些外在的表现形式就可以发现,这不就是我们已经熟悉的MVC吗?

数据模型—Model

对外交互—View

程序的执行和控制—Control

 

MVC的概念就这么简单,这些概念其实早已深入我们的内心,而我们所缺乏的是将其本质挖掘出来的能力。我们来看看如图2-8所示的这幅流行了很多年的讲述MVC模型的图。

 
图2-8 MVC模型图

在这幅图中,MVC三个框框各司其职,结构清晰明朗。这也成为我们进行编程开发的最强有力的理论武器,我们需要做的,只是为这些框框赋予不同的表现形式。实际上,框架就是这么干的!而框架的高明之处,仅仅在于它不仅赋予这些元素正确而恰当的表现形式,同时解决了当元素运行起来时所碰到的各种问题。因此,我们始终应该做到:程序时时有,概念心中留。只要MVC的理念在你心中,无论程序怎么变,都能做到万变不离其宗。

 

Struts2框架的作用

        

       当表示层有了MVC模式,程序开发就会变得有章可循。至少,我们不会像无头苍蝇一样无从入手。MVC模式很直观地规定了表示层的各种元素,只要能够通过恰当的程序表现形式来实现这些元素,我们实际上已经在履行最佳实践了。

       至此,我们不妨返璞归真,忘记所谓的框架,用最简单的方式来实现一个简单的MVC雏形。在这个过程中,我们不妨回到框架的本质问题上,思考一下究竟一个框架为表示层解决了什么样的编程难题,难道框架只是实现MVC这三大元素那么简单而已?

 

        我们选择Registration(注册)作为业务场景。首先,我们需要一个JSP页面来呈现用户注册的各个字段、一个User类来表示用户实体以及一个RegistrationServlet类来处理注册请求。相关实现源码如代码清单2-6、代码清单2-7和代码清单2-8所示。

代码清单2-6 registration.jsp


   
  1. <form method="post" action="/struts2_example/registration"> 
  2.   user name: <input type="text" name="user.name" value="downpour" /> 
  3.   birthday: <input type="text" name="user.birthday" value="1982-04-15" /> 
  4.   <input type="submit" value="submit" /> 
  5. </form> 

代码清单2-7 User.java


   
  1. public class User {  
  2.  
  3.     private String name;  
  4.  
  5.     private Date birthday;  
  6.  
  7.     public User() {  
  8.  
  9.     }  
  10.  
  11.     // 此处省略setter与getter方法  

代码清单2-8 RegistrationServlet.java


   
  1. public class RegistrationServlet extends HttpServlet {  
  2.  
  3.     @Override  
  4.     protected void doPost(HttpServletRequest req, HttpServletResponse  
  5. resp) throws ServletException, IOException {  
  6.  
  7.         // 从request获取参数  
  8.  
  9.         String name = req.getParameter("name");  
  10.         String birthdayString = req.getParameter("birthday");  
  11.  
  12.         // 做必要的类型转化  
  13.  
  14.         Date birthday = null;  
  15.         try {  
  16.              birthday = new SmpleDateFormat("yyyy-MM-dd").  
  17. parse(birthdayString);  
  18.         } catch (ParseException e) {  
  19.         e.printStackTrace();  
  20.         }  
  21.  
  22.         // 初始化User类,并设置字段到user对象中去  
  23.  
  24.         User user = new User();  
  25.         user.setName(name);  
  26.         user.setBirthday(birthday);  
  27.  
  28.         // 调用业务逻辑代码完成注册  
  29.  
  30.         UserService userService = new UserService();  
  31.         userService.register(user);  
  32.  
  33.         req.getRequestDispatcher("/success.jsp").forward(req, resp);  
  34.     }  

除了上述这3段源代码外,我们还需要建立起JSP页面中的form请求与Servlet类的响应之间的关系。这一关系,是在web.xml中维护的,如代码清单2-9所示。

代码清单2-9 web.xml

  1. <servlet> 
  2.  <servlet-name>Register</servlet-name> 
  3.  <servlet-class>example.RegistrationServlet</servlet-class> 
  4. </servlet> 
  5. <servlet-mapping> 
  6.  <servlet-name>Register</servlet-name> 
  7.  <url-pattern>/struts2_example/registration</url-pattern> 
  8. </servlet-mapping> 
 

我们来看看上面的这4段代码是如何构成MVC的雏形的。

Model(数据模型)—User.java

View(对外交互)—registration.jsp

Control(程序执行和控制)—RegistrationServlet.java

URL Mapping(请求转化)—web.xml

 

我们可以看到MVC的实现似乎并不复杂。在不借助额外的框架帮助的前提下,只要基本知晓JSP和Servlet标准(它们是使用Java进行Web开发的规范和标准),任何程序员都可以像模像样地实现MVC模式,因为从原理上讲,MVC只是一个概念,我们只需要把这个概念中的各个元素赋予相应的程序实现即可。

不过程序终究是一个动态的执行过程。一旦程序开始运行,上面的这些程序实现就会开始遭遇种种困境。这些困境主要来源于两个方面:其一,出于程序自身的可读性和可维护性考虑,需要通过重构来解决程序的复杂性困境。其二,出于业务扩展的需求,需要通过框架级别的功能增强来解决可扩展性困境。

 

具体来说,上面的这些程序实现有如下不太好的地方:

 

1.RegistrationServlet 和很多其它的Servlet有着非常相似的执行步骤:接受参数--进行类型转换--调度业务逻辑接口执行逻辑--返回处理结果。

 

2.在上面的例子中,我们可以看到负责视图层跳转的RegistrationServlet 是通过硬编码的方式完成程序执行跳转的。这种方式不但不能无法支持多种新的视图技术,比如Flash、Stream数据流,同时也无法使我们从复杂的视图跳转的硬编码中释放出来。


3.类型转换 多种多样,如何做到 复用、可扩展。

4.Web容器是一个典型的多线程环境,针对每个Http请求,Web容器的线程池会分配一个特定的线程进行处理。那么如何保证在多线程环境下,处理请求的Java类是线程安全的对象?如何保证数据的流转和访问都是线程安全的?
在上面的例子中,我们使用的是基于Servlet标准的方式进行编程,扩展Servlet用于处理Http请求。然而恰恰就是这种编程模型,是一种非线程安全的编程模型,因为Servlet对象是一个非线程安全的对象。也就是说,如果我们在doPost方法中访问RegistrationServlet中所定义的局部变量,就会产生线程安全问题。
不好的地方还有很多,就不再举例子了。
Struts2框架的作用:接收参数、参数校验、流程控制、页面展现等很多功能,减轻了我们的开发负担,提高了开发效率。

© 著作权归作者所有

共有 人打赏支持
FansUnion
粉丝 56
博文 857
码字总数 825464
作品 0
丰台
高级程序员

暂无相关文章

从 Confluence 5.3 及其早期版本中恢复空间

如果你需要从 Confluence 5.3 及其早期版本中的导出文件恢复到晚于 Confluence 5.3 的 Confluence 中的话。你可以使用临时的 Confluence 空间安装,然后将这个 Confluence 安装实例升级到你现...

honeymose ⋅ 今天 ⋅ 0

用ZBLOG2.3博客写读书笔记网站能创造今日头条的辉煌吗?

最近两年,著名的自媒体网站今日头条可以说是火得一塌糊涂,虽然从目前来看也遇到了一点瓶颈,毕竟发展到了一定的规模,继续增长就更加难了,但如今的今日头条规模和流量已经非常大了。 我们...

原创小博客 ⋅ 今天 ⋅ 0

MyBatis四大核心概念

本文讲解 MyBatis 四大核心概念(SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper)。 MyBatis 作为互联网数据库映射工具界的“上古神器”,训有四大“神兽”,谓之:Sql...

waylau ⋅ 今天 ⋅ 0

以太坊java开发包web3j简介

web3j(org.web3j)是Java版本的以太坊JSON RPC接口协议封装实现,如果需要将你的Java应用或安卓应用接入以太坊,或者希望用java开发一个钱包应用,那么用web3j就对了。 web3j的功能相当完整...

汇智网教程 ⋅ 今天 ⋅ 0

2个线程交替打印100以内的数字

重点提示: 线程的本质上只是一个壳子,真正的逻辑其实在“竞态条件”中。 举个例子,比如本题中的打印,那么在竞态条件中,我只需要一个方法即可; 假如我的需求是2个线程,一个+1,一个-1,...

Germmy ⋅ 今天 ⋅ 0

Springboot2 之 Spring Data Redis 实现消息队列——发布/订阅模式

一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式,这里利用redis消息“发布/订阅”来简单实现订阅者模式。 实现之前先过过 redis 发布订阅的一些基础概念和操...

Simonton ⋅ 今天 ⋅ 0

error:Could not find gradle

一.更新Android Studio后打开Project,报如下错误: Error: Could not find com.android.tools.build:gradle:2.2.1. Searched in the following locations: file:/D:/software/android/andro......

Yao--靠自己 ⋅ 昨天 ⋅ 0

Spring boot 项目打包及引入本地jar包

Spring Boot 项目打包以及引入本地Jar包 [TOC] 上篇文章提到 Maven 项目添加本地jar包的三种方式 ,本篇文章记录下在实际项目中的应用。 spring boot 打包方式 我们知道,传统应用可以将程序...

Os_yxguang ⋅ 昨天 ⋅ 0

常见数据结构(二)-树(二叉树,红黑树,B树)

本文介绍数据结构中几种常见的树:二分查找树,2-3树,红黑树,B树 写在前面 本文所有图片均截图自coursera上普林斯顿的课程《Algorithms, Part I》中的Slides 相关命题的证明可参考《算法(第...

浮躁的码农 ⋅ 昨天 ⋅ 0

android -------- 混淆打包报错 (warning - InnerClass ...)

最近做Android混淆打包遇到一些问题,Android Sdutio 3.1 版本打包的 错误如下: Android studio warning - InnerClass annotations are missing corresponding EnclosingMember annotation......

切切歆语 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部