Web组件的三种关联关系
存在以上关联关系的Web组件可以是JSP或Servlet,对于Struts应用,则还包括Action。这些Web组件都可以访问HttpServletRequest和HttpServletResponse对象,具有处理请求、生成响应结果的功能。
1、请求转发
请求转发的代码:
request.getRequestDispatcher(“hello.jsp”).forward(request, response);
之所以要将request和response当做forward方法的参数,正说明转发与被转发的Web组件之间使用的是同一个request对象.
在JSP页面中, 可以使用<jsp:forward>标签来转发请求, 例如:
<jsp:forward page=”hello.jsp”/>
对于请求转发, 转发的源组件和目标组件共享request范围内的共享数据.
2、URL重定向
URL重定向与请求转发相似, 但也有着本质的不同
如果当前应用的Servlet组件要把请求转发给URL “http://localhost:8080/asp1.1”,可以在Servlet的service()方法中执行以下代码:
response.sendRedirect(“http://localhost:8080/asp1.1”);
3、包含
包含关系允许一个Web组件聚集来自同一个应用中其他Web组件的输出数据,并使用被聚集的数据来创建响应结果. 包含关系的源组件和目标组件共用同一个HttpServletRequest对象, 因此它们共享request范围内的共享数据.
Servlet类使用javax.servlet.RequestDispatcher.include()方法包含其他的Web组件. 例如, 如果当前的Servlet组件包含了三个JSP文件: header.jsp、main.jsp和footer.jsp, 则可以在Servlet的service()方法中执行以下代码:
RequestDispatcher rd;
rd = req.getRequestDispatcher(“/header.jsp”);
rd.include(req, res);
rd = req.getRequestDispatcher(“/main.jsp”);
rd.include(req, res);
rd = req.getRequestsDispatcher(“/footer.jsp”);
rd.include(req, res);
在JSP文件中, 可以通过<include>指令来包含其他的Web资源, 例如:
<%@ include file=”header.jsp”%> <%@ include file=”mainjsp”%> <%@ include file=”footer.jsp”%>
图4、MVC Model 1
图5、MVC Model 2
Model 1 与 Model 2 的区别,Model 2 下 JSP 不再承担控制器的责任,它仅仅是表现层角色,仅仅用于将结果呈现给用户,JSP页面的请求与Servlet(控制器)交互,而Servlet负责与后台的JavaBean通信。在Model 2 模式下,模型(Model)由JavaBean充当.
Struts,MVC 2 的一种实现
图6 Struts 实现的MVC框架
版权所有:(xiaodaoxiaodao)蓝小刀 [email protected]
http://www.blogjava.net/xiaodaoxiaodao/archive/2007/03/26/106522.html
转载请注明来源/作者
struts 学习笔记之MVC模式
struts 中的MVC架构如下:
View :由JSP、Struts自定义标记库、资源文件(MessageResources.properties)共同组成,通过ActionForm实现JSP表单的封装,并映射到Model部分中JavaBean的相应属性中,完成用户数据的封装。
注意:关于ActionForm,有些人认为它属于Model层(仁者见仁,智者见智)。
事实上它不是Model,真正的Model应该是一个封装了业务逻辑的的对象。
而ActionForm仅仅是一个form-bean,封装了用户提交的表单数据(物理View),可以在其中进行一些非业务逻辑的验证,并没有真正的映射到模型数据,因为与层的关系比较密切,所以实际上它应该算是View层(逻辑View)。
Action 处理器对象可以直接对ActionForm进行读写,而不再需要和request、response对象进行数据交互。通过ActionForm组件对象实现了对View和Model之间交互的支持。M模型层,原则上来说和业务逻辑有关的东西都在这里处理。
Controller :接收客户端的request,进行业务逻辑处理,response到客户端。在Struts中Controller功能由图中ActionServlet和ActionMapping对象构成:核心是一个Servlet类型的对象ActionServlet(在struts-config.xml中配置),实际上是一个前端控制器(Front Controller)。ActionServlet根据ActionMapping对象的定义跳转到不同的Action,每个ActionMapping对象实现了一个request到Action对象之间的映射。
注 :Controller层负责流程的控制,在处理Model层与View层之间的交互的同时,又将两者分离开来,从而实现了MVC模式。Model层包含了应用的核心部分,业务逻辑和数据存取。View层负责应用的界面。
在上面的图中看到Action位于Controller层,但也有很多人把它归于Model层,实际上 Action 仅仅描述"做什么",与"如何做"(Model)关系不大,把它归于 Controller 层比较合适。
Model :一般Model层可以划分为三部分:公共入口,业务逻辑(Bussiness Logic),数据持久化(DAO+JavaBean)。
在Spring+Hibernate的架构中,M可以用 Spring (Bussiness Interface + Bussiness Implement)表示业务逻辑,Hibernate实现数据持久化。
附 :PO/POJO/BO/DTO/VO的区别
---------------------------------------------------------
PO :persistent object持久对象
1 .有时也被称为Data对象,对应数据库中的entity,可以简单认为一个PO对应数据库中的一条记录。
2 .在hibernate持久化框架中与insert/delet操作密切相关。
3 .PO中不应该包含任何对数据库的操作。
---------------------------------------------------------
POJO :plain ordinary java object 无规则简单java对象
一个中间对象,可以转化为PO、DTO、VO。
1 .POJO持久化之后==〉PO
(在运行期,由Hibernate中的cglib动态把POJO转换为PO,PO相对于POJO会增加一些用来管理数据库entity状态的属性和方法。PO对于programmer来说完全透明,由于是运行期生成PO,所以可以支持增量编译,增量调试。)
2 .POJO传输过程中==〉DTO
3 .POJO用作表示层==〉VO
PO 和VO都应该属于它。
----------------------------------------------------------
BO :business object 业务对象
封装业务逻辑为一个对象(可以包括多个PO,通常需要将BO转化成PO,才能进行数据的持久化,反之,从DB中得到的PO,需要转化成BO才能在业务层使用)。
关于BO主要有三种概念
1 、只包含业务对象的属性;
2 、只包含业务方法;
3 、两者都包含。
在实际使用中,认为哪一种概念正确并不重要,关键是实际应用中适合自己项目的需要。
----------------------------------------------------------
VO :value object值对象 / view object表现层对象
1 .主要对应页面显示(web页面/swt、swing界面)的数据对象。
2 .可以和表对应,也可以不,这根据业务的需要。
注 :在struts中,用ActionForm做VO,需要做一个转换,因为PO是面向对象的,而ActionForm是和view对应的,要将几个PO要显示的属性合成一个ActionForm,可以使用BeanUtils的copy方法。
----------------------------------------------------------
DTO (TO) :Data Transfer Object数据传输对象
1 .用在需要跨进程或远程传输时,它不应该包含业务逻辑。
2 .比如一张表有100个字段,那么对应的PO就有100个属性(大多数情况下,DTO 内的数据来自多个表)。但view层只需显示10个字段,没有必要把整个PO对象传递到client,这时我们就可以用只有这10个属性的DTO来传输数据到client,这样也不会暴露server端表结构。到达客户端以后,如果用这个对象来对应界面显示,那此时它的身份就转为VO。
----------------------------------------------------------
DAO :data access object数据访问对象
1 .主要用来封装对DB的访问(CRUD操作)。
2 .通过接收Business层的数据,把POJO持久化为PO。
Struts概览
视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并能接收用户的输入数据,但是它并不进行任何实际的业务处理。视图可以像模型查询业务状态,但不能改变模型。视图还能接受模型发出的数据更新事件,从而对用户界面进行同步更新。
Web工程中,视图就是一组JSP文件。在这些JSP文件中没有业务逻辑,也没有模型信息,只有标签。
此外,通常把Struts框架中的ActionForm Bean 也划分到视图模块中。ActionForm Bean 也是一种JavaBean,Struts框架把用户输入的表单数据保存在ActionForm Bean 中,把它传递给控制器,控制器可以对ActionForm Bean中的数据进行修改,JSP文件使用Struts标签读取修改后的ActionForm Bean的信息,重新设置HTML表单。
图7 ActionForm Bean 的作用
模型是应用程序的主体部分。模型表示业务数据和业务逻辑。一个模型能为多个视图提供数据。由于同一个模型可以被多个视图重用,所以提高了应用的可重用性。大型应用中,业务逻辑通常由JavaBean或EJB组件来实现。
控制器接手用户的输入并调用模型和视图去完成用户的需求。当Web用户单击Web页面中的提交按钮来发送HTML表单时,控制器接收请求并调用相应的模型组件去处理请求,然后调用相应的视图来显示模型返回的数据。
Struts控制器由ActionServlet类和Action类来实现。ActionServlet类是Struts框架中的核心组件。ActionServlet继承了javax.servlet.http.HttpServlet类,它在MVC模型中扮演中央控制器的角色。ActionServlet主要负责接收HTTP请求信息,根据配置文件struts-config.xml的配置信息,把请求转发给适当的Action对象。如果该Action对象不存在,ActionServlet会先创建这个Acton对象。
Action类负责调用模型的方法,更新模型的状态,并帮助控制应用程序的流程。
上面讲到一个用户请求是通过ActionServlet来处理和转发的。那么,ActionServlet如何决定把用户请求转发给哪个Action对象呢?在Struts中,这些配置信息都存储在特定的XML文件struts-config.xml中,在该配置文件中,每一个Acton的映射信息都通过一个<action>元素来配置。
这些配置信息在系统启动时被读入内存,供Struts在运行期间使用。在内存中,每一个<action>元素都对应一个org.apache.struts.action.ActionMapping类的实例。
Struts的工作流程
对于采用Struts框架的Web应用,在Web应用启动时就会加载并初始化ActionServlet,ActionServlet从struts-config.xml文件中读取配置信息,把它们存放到各种配置对象中,例如Action的映射信息存放在ActionMapping对象中。
当ActionServlet接收到一个客户请求时,将执行如下流程。
(1)检索和用户请求匹配的ActionMapping实例,如果不存在,就返回用户请求路径无效的信息
(2)如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm对象中。
(3)根据配置信息决定是否需要表单验证。如果需要验证,就调用ActionForm的validate()方法。
(4)如果ActionForm的validate()方法返回null或返回一个不包含ActionMessage的ActionErrors对象,就表示表单验证成功。
(5)ActionServlet根据ActionMapping实例包含的映射信息决定将请求转发给哪个Action。如果相应的Action实例不存在,就先创建这个实例,然后调用Action的execute()方法。
(6)Action的execute()方法返回一个ActionForward对象,ActionServlet再把客户请求转发ActionForward对象指向的JSP组件。
(7)ActionForward对象指向的JSP组件动态生成网页,返回给客户。
对于以上流程(4)、如果ActionForm的validate()方法返回一个包含一个或多个ActionMessage的ActionErrors对象,就表示表单验证失败,此时ActionServlet将直接把请求转发给包含用户提交表单的JSP组件。在这种情况下,不会在创建Action对象并调用Action的execute()方法。
图8 Struts响应用户请求的工作流程
第一个实例:helloapp
1、创建视图组件
hello.jsp
<%@ page language="java" pageEncoding="utf-8"%> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %> <%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html:html lang="true"> <head> <html:base /> <title><bean:message key="hello.jsp.title"/></title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body bgcolor="white"> <h2><bean:message key="hello.jsp.page.heading"/></h2><p> <html:errors/><p> <logic:present name="personbean" scope="request"> <h2> <bean:message key="hello.jsp.page.hello"/> <bean:write name="personbean" property="userName"/>!<p> </h2> </logic:present> <html:form action="/HelloWorld.do" focus="userName"> <bean:message key="hello.jsp.prompt.person"/> <html:text property="userName" size="16" maxlength="16"></html:text><br> <html:submit property="submit" value="Submit"></html:submit> </html:form><br> <html:image page="/struts-power,gif" alt="Powered by Struts"></html:image> </body> </html:html>
2、创建消息资源文件
hello.jsp使用<bean:message>标签来输出文本内容。这些文本来自于Resource Bundle,每个Resource Bundle都对应一个或多个本地的消息资源文件,本例中的资源文件为application.properties,
#Application Resources for the "Hello" sample application #Application Resources that are specific to the hello.jsp file hello.jsp.title=Hello - A first Struts program hello.jsp.page.heading=Hello World! A first Struts application hello.jsp.prompt.person=Please enter a UserName to say hello to : hello.jsp.page.hello=Hello #Validation and error messages for HelloForm.java and HelloAction.java hello.dont.talk.to.monster=We don't want to say hello to Monster!!! hello.no.username.error=Please enter a <i>UserName</i> to say hello to!
3、创建ActionForm Bean
Struts框架中定义的ActionForm类是抽象的,必须在应用中创建它的子类,来放具体的HTML表单数据。
HelloForm.java
package hello; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; public final class HelloForm extends ActionForm { private String userName = null; public String getUserName() { return (this.userName); } public void setUserName(String userName) { this.userName = userName; } /** * Reset all properties to their default values. */ public void reset(ActionMapping mapping, HttpServletRequest request) { this.userName = null; } /** * Validate the properties posted in this request. If validation errors are * found, return an <code>ActionErrors</code> object containing the errors. * If no validation errors occur, return <code>null</code> or an empty * <code>ActionErrors</code> object. */ public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if ((userName == null) || (userName.length() < 1)) errors.add("username", new ActionMessage("hello.no.username.error")); return errors; } }
从以上代码可以看出,ActionForm Bean 实质上是一种JavaBean,不过它除了具有JavaBean的常规方法,还有两种特殊方法:
4、数据验证
Struts框架中的数据验证分为两种类型:表单验证和业务逻辑验证
(1)表单验证,HelloForm中的validate()方法
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if ((userName == null) || (userName.length() < 1)) { errors.add("username", new ActionMessage("hello.no.username.error")); } return errors; }
当用户提交了HTML表单后,Struts框架将自动把表单数据组装到ActionForm Bean中。接下来Struts框架会自动调用ActionForm Bean的validate()方法进行表单验证。如果validate()方法返回的ActionErrors对象为null,或者不包含任何ActionMessage对象,就表示没有错误,数据验证通过。如果ActionErrors中包含ActionMessage对象,就表示发生了验证错误,Struts框架会把ActionErrors对象保存到request范围内,然后把请求转发到恰当的视图组件,视图组件通过<html:errors>标签把request范围内的ActionErrors对象中包含的错误消息显示出来,提示用户修改错误。
(2)业务逻辑验证,业务逻辑验证由Action负责处理。
5、创建控制器组件
控制器组件包括ActionServlet类和Action类。ActionServlet类是Struts框架自带的,它是整个Struts框架的控制枢纽。Struts框架提供了可扩展的Action类,它用来处理特定的HTTP请求。
HelloAction.java
package hello; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; import org.apache.struts.util.MessageResources; public final class HelloAction extends Action { /** * Process the specified HTTP request, and create the corresponding HTTP * response (or forward to another web component that will create it). * Return an <code>ActionForward</code> instance describing where and how * control should be forwarded, or <code>null</code> if the response has * already been completed. */ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // These "messages" come from the ApplicationResources.properties file MessageResources messages = getResources(request); /* * Validate the request parameters specified by the user * Note: Basic field validation done in HelloForm.java * Business logic validation done in HelloAction.java */ ActionMessages errors = new ActionMessages(); String userName = (String)((HelloForm) form).getUserName(); String badUserName = "Monster"; if (userName.equalsIgnoreCase(badUserName)) { errors.add("username", new ActionMessage("hello.dont.talk.to.monster", badUserName )); saveErrors(request, errors); return (new ActionForward(mapping.getInput())); } /* * Having received and validated the data submitted * from the View, we now update the model */ PersonBean pb = new PersonBean(); pb.setUserName(userName); pb.saveToPersistentStore(); /* * If there was a choice of View components that depended on the model * (or some other) status, we'd make the decision here as to which * to display. In this case, there is only one View component. * * We pass data to the View components by setting them as attributes * in the page, request, session or servlet context. In this case, the * most appropriate scoping is the "request" context since the data * will not be neaded after the View is generated. * * Constants.PERSON_KEY provides a key accessible by both the * Controller component (i.e. this class) and the View component * (i.e. the jsp file we forward to). */ request.setAttribute( Constants.PERSON_KEY, pb); // Remove the Form Bean - don't need to carry values forward request.removeAttribute(mapping.getAttribute()); // Forward control to the specified success URI return (mapping.findForward("SayHello")); } }
Action 的工作机制
所有的Action类都是org.apache.struts.action.Action的子类。Action子类应该覆盖父类的execute()方法。当ActionForm Bean被创建,并且表单验证通过后,Struts框架就会调用ActionForm类的execute()方法。
访问封装在MessageResources中的本地化文本
在本例中,Action类的execute()方法首先获得MessageResources对象:
MessageResources message = getResources(request);
在Action类中定义了getResources(HttpServletRequest request)方法,该方法返回当前默认的MessageResources对象,它封装了Resource Bundle中的文本内容。接下来Action类就可以通过MessageResources对象访问文本内容。例如,如果要读取消息key为“hello.jsp.title”对应的文本内容,可以调用MessageResources类的getMessage(String key)方法:
String title = messages.getMessage("hello.jsp.title");
业务逻辑验证
ActionMessages errors = new ActionMessages(); String userName = (String)((HelloForm) form).getUserName(); String badUserName = "Monster"; if (userName.equalsIgnoreCase(badUserName)) { errors.add("username", new ActionMessage("hello.dont.talk.to.monster", badUserName )); saveErrors(request, errors); return (new ActionForward(mapping.getInput())); }
6、访问模型组件
HelloAction类创建了一个模型组件PersonBean对象,并调用它的saveToPersistentStore()方法保存userName属性:
PersonBean pb = new PersonBean(); pb.setUserName(userName); pb.saveToPersistentStore();
7、向视图组件传递数据
Action类把数据存放在request或session范围内,以便向视图组件传递信息。
request.setAttribute( Constants.PERSON_KEY, pb); // Remove the Form Bean - don't need to carry values forward request.removeAttribute(mapping.getAttribute());
以上代码完成两件事:
8、把HTTP请求转发给合适的视图组件
// Forward control to the specified success URI return (mapping.findForward("SayHello"));
9、服务器端装载 hello.jsp 的流程
(1)<bean:message>标签从Resource Bundle 中读取文本, 把它输出到网页上。
(2)<html:form>标签在 request 范围中查找 HelloForm Bean。如果存在这样的实例,就把 HelloForm 对象中的 UserName 属性赋值给 HTML 表单的 userName 文本框。由于页面首次加载时还不存在 HelloForm 对象,所以忽略这项操作。
(3)把hello.jsp的视图呈现给客户
10、表单验证的流程
在hello.jsp网页上,不输入姓名,直接单击【Submit】按钮,会看到下图中的网页:
图9、表单验证失败的hello.jsp
当客户提交 HelloForm 表单时,请求路径为“、HelloWorld.do”;
<html:form action="/HelloWorld.do" focus="userName">
那么服务器端执行表单验证的流程如下:
(1)Servlet容器在web.xml文件中寻找<url-pattern>属性为“*.do”的<servlet-mapping>元素:
<servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
(2)Servlet容器依据以上<servlet-mapping>元素的<servlet-name>属性“action”,在web.xml文件中寻找匹配的<servlet>元素:
<servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet>
(3)Servlet容器把请求转发给以上<servlet>元素指定的ActionServlet,ActionServlet依据用户请求路径“、HelloWorld.do”,在Struts配置文件中检索path属性为“、HelloWorld”的<action>元素:
<action path = "/HelloWorld" type = "hello.HelloAction" name = "HelloForm" scope = "request" validate = "true" input = "/hello.jsp"> <forward name="SayHello" path="/hello.jsp" /> </action>
更确切的说,ActionServlet此时检索的是ActionMapping对象,而不是直接访问Struts配置文件中的<action>元素。因为在ActionServlet初始化的时候,会加载Struts配置文件,把各种配置信息保存在相应的配置类的实例中,例如<action>元素的配置信息放在ActionMapping对象中。
(4)ActionServlet根据<action>元素的name属性,创建一个HelloForm对象,把客户提交的表单数据传给HelloForm对象,再把HelloForm对象保存在保存在<action>元素的scope属性指定的request范围内。
(5)由于<action>元素的validate属性为true,ActionServlet调用HelloForm对象的validate()方法执行表单验证:
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if ((userName == null) || (userName.length() < 1)) errors.add("username", new ActionMessage("hello.no.username.error")); return errors; }
(6)HelloForm对象的validate()方法返回一个ActionErrors对象,里面包含一个ActionMessage对象,这个ActionMessage对象封装了错误信息,消息key为“hello.no.username.error”,在Resource Bundle中与之匹配的消息文本为:
Please enter a <i>UserName</i> to say hello to!
(7)ActionServlet把HelloForm的validate()方法返回的ActionErrors对象保存在request范围内,然后根据<action>元素的input属性,把客户请求转发给hello.jsp。
(8)hello.jsp 的 <html:errors> 标签从 request 范围内读取 ActionErrors 对象, 再从ActionErrors 对象中读取 ActionMessage 对象, 把它包含的错误消息显示在网页上。
11、逻辑验证失败的流程
(1)重复上面(1)~(4)
(2)ActionServlet调用HelloForm对象的validate()方法,这次validate()方法返回的ActionErrors对象中不包含任何ActionMessage对象,表示表单验证成功。
(3)ActionServlet查找HelloAction实例是否存在,如果不存在就创建一个实例。然后调用HelloAction 的 execute() 方法。
(4)HelloAction 的 execute()方法先进行逻辑验证,由于没有通过逻辑验证,就创建一个 ActionMessage 对象,这个ActionMessages errors = new ActionMessages();
execute()方法把 ActionMessage 对象保存在 ActionMessages 对象中,再把ActionMessage对象存放在request范围内。最后返回一个 ActionForward 对象, 该对象包含的请求转发路径为<action>元素的input属性指定的hello.jsp。
String userName = (String)((HelloForm) form).getUserName(); String badUserName = "Monster"; if (userName.equalsIgnoreCase(badUserName)) { /* * 创建错误信息 —— new ActionMessage("hello.dont.talk.to.monster", badUserName )), * 将 ActionMessage 对象保存到 ActionMessages 对象中。 * 接下来调用在 Action 基类中定义的 saveErrors() 方法,它负责把 ActionMessages 对象保存到 request 范围内。 * 最后返回 ActionForward 对象,该对象包含的请求转发路径为<action>元素的 input 属性指定的 hello.jsp —— new ActionForward(mapping.getInput()); */ errors.add("username", new ActionMessage("hello.dont.talk.to.monster", badUserName )); saveErrors(request, errors); return (new ActionForward(mapping.getInput())); }
有时候业务逻辑验证会对数据进行更为复杂的验证。在很多情况下,需要模型组件的介入,才能完成业务逻辑验证。
(5) ActionServlet 依据 HelloAction 返回的 ActionForward 对象, 再把请求转发给 hello.jsp
(6)hello.jsp 的 <html:errors> 标签从 request 范围内读取 ActionMessages 对象, 再从 ActionMessages 对象中读取 ActionMessage 对象, 把它包含的错误消息显示在网页上。
12、验证成功的流程
(1) 重复 (1)~(3)
(2)HelloAction 的 execute() 方法先执行逻辑验证, 这次通过了验证,执行相关的业务逻辑,最后调用 ActionMapping.findForward() 方法,
return (mapping.findForward("SayHello"));
(3)ActionMapping.findForward() 方法从 <action> 元素中寻找 name属性为 “SayHello” 的 <forward> 子元素,然后返回与之对应的 ActionForward 对象, 它代表的请求转发路径为 “/hello.jsp” 。
更确切地说,ActionMapping 从本身包含的 HashMap 中查找 name 属性为 “SayHello” 的ActionForward对象。在ActionServlet 初始化时会加载Struts配置文件,把<action>元素的配置信息存放在ActionMapping对象中,<action>元素中可以包含多个<forward>子元素,每个 <forward> 子元素的配置信息存放在一个 ActionForward 对象中, 这些 ActionForward 对象存放在 ActionMapping 对象的 HashMap 中。
(4)HelloAction 的 execute() 方法然后把 ActionForward 对象返回给 ActionServlet, ActionServlet 再把客户请求转发给 hello.jsp