目录
本章将介绍 MVC 模式,MVC 模式的核心思想是将“模型”“视图”和“控制器”进行有效组合,该模式对于设计合理的 Web 应用以及学习使用某些流行的 Web 框架,如 Spring、Struts 等。
7.1 MVC 模式介绍
模型-视图-控制器,简称为 MVC。MVC 已经成为软件设计这必须熟练使用的开发模式。MVC 是一种通过三部分构造一份软件或组件的理想方法。
- 模型(model):用户存储数据的对象。
- 视图(view):向控制器提交所需数据、显示模型中的数据。
- 控制器(controller):负责具体的业务逻辑操作,即控制器根据视图提出的要求对数据做出处理,将有关结果存储到模型中,并负责让模型和视图进行必要的交互,当模型中的数据变化时,让视图更新显示。
7.2 JSP 中的 MVC 模式
我们已经知道,JSP 页面擅长数据的显示,即适合作为用户的视图,例如,JSP 页面里可以有 HTML 标记、JavaScript、CSS、JAVA 表达式等。在 JSP 页面中可以使用 HTML 标记、JSP 指令或 JAVA 程序片、JAVA 表达式来为用户显示数据,避免使用大量的 JAVA 程序片来进行数据的逻辑处理。servlet 擅长数据的处理,应当尽量避免在 servlet 中使用 out 流输出大量的 HTML 标记来显示数据,否则一旦要修改显示外观就要重新编译 servlet。
在 JSP 中,MVC 模式的实现如下:
- 模型(Model):一个或多个 JavaBean 对象,用于存储数据。JavaBean 主要提供简单的 setXxx 方法和 getXxx 方法,在这些方法中不涉及对数据的具体处理细节,一边增强模型的通用性。
- 视图(View):一个或多个 JSP 页面,其作用是向控制器提交必要的数据和显示数据。JSP 页面可以使用 HTML 标记、JavaBean 标记以及 JAVA 程序片或 JAVA 表达式来显示数据。视图的主要工作就是显示数据,对数据的逻辑操作由控制器负责。
- 控制器(Controller):一个或多个 servlet 对象,根据视图提交的要求进行数据处理操作,并将有关的结果存储到 JavaBean 中,然后 servlet 使用转发或重定向的方式请求视图中的某个 JSP 页面显示数据。例如让某个 JSP 页面通过使用 JavaBean 标记、JAVA 程序片或 JAVA 表达式显示控制器存储在 JavaBean 中的数据。
7.3 模型的生命周期与视图更新
使用 MVC 模式和前面学习的 JSP + JavaBean 模式有很大的不同。在 JSP + JavaBean 模式中,由 JSP 页面通过使用 useBean 标记:
<jsp:useBean id = "名字" class = "创建 bean 的类" scope = "生命周期"/>
创建 bean。而在 MVC 模式中,由控制器 servlet 创建 bean,并将有关数据存储到所创建的 bean 中,然后 servlet 请求某个 JSP 页面使用 getProperty 动作标记:
<jsp:getProperty name = "名字" property = "bean 的属性"/>
显示 bean 中的数据。
在 MVC 模式中,当用控制器 servlet 创建 bean 时,就可以使用 bean 类的带参数的构造方法。类中的方法的命名继续保留 getXxx 规则,但可以不遵守 setXxx 规则。其理由是:我们不希望 JSP 页面修改 JavaBean 中的数据,只需要它显示 bean 中的数据。
7.3.1 request bean
1、bean 的创建
servlet 创建 request bean 的步骤如下:
(1)用 BeanClass 类的某个构造方法创建 bean 对象,例如:
BeanClass bean = new BeanClass();
(2)将所创建的 bean 对象存放到 HttpServletRequest 对象 request 中,并指定查找该 bean 的 id。该步骤决定了 bean 为 request bean。例如:
request.setAttribute("keyWord",bean);
执行上述操作,就会把 bean 存放到 Tomcat 服务器管理的内置对象 pageContext 中,该 bean 被指定的 id 是 keyWord,生命周期是 pageContext.REQUEST_SCOPE(request)。
2、视图更新
在 MVC 模式中,由 servlet 负责根据模型中数据的变化通知 JSP 页面更新,其手段是使用转发,即使用 RequestDispatcher 对象向某个 JSP 页面发出请求,让所请求的 JSP 页面显示 bean 中的数据。
servlet 请求一个 JSP 页面,例如以下代码:
RequestDispatcher dispatcher = request.getRequestDispatcher("show.jsp");
dispatcher.forward(request,response);
servlet 所请求的 JSP 页面可以使用如下标记获得 servlet 所创建的 request bean:
<jsp:useBean id = "keyWord" class = "save.data.BeabClass" scope = "request"/>
id 的值是 servlet 创建 request bean 时,为 bean 指定的关键字。然后 JSP 页面可以使用相应的标记或 JAVA 程序片显示该 request bean 中的数据,例如使用:
<jsp:getProperty name = "keyWord" property = "bean 的变量"/>
标记显示 request bean 中的数据。如果上述代码执行成功,用户就看到了 show.jsp 页面显示 request bean 中的数据的效果。
7.3.2 session bean
1、 bean 的创建
servlet 创建 session bean 的步骤如下:
(1)用 BeanClass 类的某个构造方法创建 bean 对象,例如:
BeanClass bean = new BeanClass();
(2)将所创建的 bean 对象存放到 HttpServletSession 对象 session 中,并指定查找该 bean 的 id。该步骤决定了 bean 为 session bean。例如:
HttpSession session = request.getSession(true);
session.setAttribute("keyWord",bean);
内置对象执行上述操作,就会把 bean 存放到 Tomcat 服务器管理的内置对象 pageContext 中,该 bean 被指定的 id 是 keyWord,生命周期是 PageContext.SESSION_SCOPE(session)。
2、视图更新
servlet 创建 bean 步骤决定了 bean 为 session bean,只要用户的 session 没有消失,该 session bean 就一直存在。Web 服务目录的各个 JSP 都可以使用
<jsp:useBean id = "keyWord" class = "save.data.BeanClass" scope = "session"/>
标记获得 servlet 所创建的 session bean,然后使用相应的标记或程序片显示该 session bean 中的数据,例如使用
<jsp:getProperty name = "keyWord" property = "bean 的变量"/>
标记显示该 session bean 中的数据。
对于 session bean,如果 servlet 希望某个 JSP 显示器中的数据,可以使用 RequestDispatcher 对象转发到该页面,也可以使用 HttpServletResponse 类中的重定向方法定向到该页面。
7.3.3 application bean
1、bean 的创建
servlet 创建 application bean 的步骤如下:
(1)用 BeanClass 类的某个构造方法创建 bean 对象,例如:
BeanClass bean = new BeanClass();
(2)servlet 使用 getServletContext()方法返回服务器的 ServletContext 中,将所创建的 bean 对象存放到服务器这个 ServletContext 内置对象中,并指定查找该 bean 的关键字。该步骤决定了 bean 的生命周期为 application。例如:
getServletContext().setAttribute("keyWord",bean);
这样就会把 bean 存放到 Tomcat 服务器管理的内置对象 pageContext 中,该 bean 被指定的 id 是 keyWord,生命周期是 PageContext.APPLICATION_SCOPE(application)。
2、视图更新
servlet 创建 bean 的步骤决定了 bean 为 application bean。当 servlet 创建 application bean 后,只要 Tomcat 服务器不关闭,该 bean 就一直存在。一个用户在访问 Web 服务目录的各个 JSP 中都可以使用
<jsp:useBean id = "keyWord" class = "save.data.BeanClass" scope = "application"/>
标记获得 servlet 所创建的 application bean,然后使用相应的标记或程序片显示该 application bean 中的数据,例如使用
<jsp:getProperty name = "keyWord" property = "bean 的变量"/>
标记显示该 application bean 中的数据。
对于 application bean,如果 servlet 希望某个 JSP 显示其中的数据,可以使用 RequestDispatcher 对象向该 JSP 页面发出请求,也可以使用 HttpServletResponse 类中的重定向方法。