- 浏览: 414731 次
文章分类
最新评论
-
xieke:
就一句话?内容呢?
用RMI实现基于Java的分布式计算 -
grandboy:
搞成功了,但是生成的代码不好。我不想用这个生成了,还是用mid ...
用PowerDesigner生成Hibernate映射文件的步骤 -
rmn190:
麻烦你帮我看下这个关于struts-menu方面的问题吧: h ...
Struts-menu源码分析 -
wcily123:
按照你的这个搞了半天都没有成功!
用PowerDesigner生成Hibernate映射文件的步骤 -
beijixuem:
骗人的家伙!
JAVA + Oracle存储过程返回查询结果集
本文将介绍 StrutsTestCase(STC)框架,解释如何用模拟方式和 Cactus 方式测试示例应用程序。作者 Sunil Patil 是 IBM 印度软件试验室的开发人员,他首先将介绍 STC,然后会带您遍历设置使用 STC 和测试各种 Struts 特性的环境的过程。还将演示如何在 STC 中同时使用 Cactus 和模拟方式。
注意:本文要求读者熟悉 Struts 框架。
StrutsTestCase(STC)框架是一个开源框架,用来测试基于 Struts 的 Web 应用程序。这个框架允许您在以下方面进行测试:
- 在
ActionForm
类中的验证逻辑(validate()
方法)。 - 在
Action
类中的业务逻辑(execute()
方法)。 - 动作转发(Action Forwards)。
- 转发 JSP。
STC 支持两种测试类型:
- Mock 方法 —— 在这种方法中,通过模拟容器提供的对象(
HttpServletRequest
、HttpServletResponse
和ServletContext
),STC 不用把应用程序部署在应用服务器中,就可以对其进行测试。 - Cactus 方法 —— 这种方法用于集成测试阶段,在这种方法中,应用程序要部署在容器中,所以可以像运行其他 JUnit 测试用例那样运行测试用例。
首先我们将逐步介绍示例 Struts 应用程序的创建,这个应用程序是测试的基础。可以用 Struts 自带的 struts-blank.war 或者自己喜欢的 IDE 来创建示例应用程序。示例应用程序中有一个登录页面,用户在这里输入用户名和口令。如果登录成功,用户会被重定向到成功页面。如果登录失败,那么用户会被重定向到登录页面。
选择本文顶部或底部的 Code 图标可以得到本文附带的源代码。
创建登录页面,如清单 1 所示:
清单 1. Login.jsp
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %><%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %><html:html><HEAD><%@ page language="java"contentType="text/html; charset=ISO-8859-1"pageEncoding="ISO-8859-1" %><META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><TITLE>Login.jsp</TITLE></HEAD><BODY><html:form action="/login"><html:errors/><H3>Login</H3> <TABLE border="0"> <TBODY> <TR> <TH>User Name</TH> <TD><html:text property='userName' value='' /></TD> <TR> <TR> <TH>Password</TH> <TD><html:text property='password' value='' /></TD> </TR> <TR> <TD><html:submit property="submit" value="Submit" /></TD> <TD><html:reset /></TD> </TR> </TBODY> </TABLE></html:form></BODY></html:html> |
创建 LoginActionForm.java 类,如清单 2 所示:
清单 2. LoginActionForm.java
public class LoginActionForm extends ActionForm {public ActionErrors validate( ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if (userName == null || userName.length() == 0) errors.add("userName", new ActionError("username.required")); if (password == null || password.length() == 0) errors.add("password", new ActionError("password.required")); if( isUserDisabled(userName)) errors.add("userName",new ActionError("user.disabled")); return errors;}//Query USERDISABLED table to check if user account is disabled public boolean isUserDisabled(String userName) { //SQL logic to check if user account is disabled}} |
在 validate()
方法中,需要检测用户是否输入了用户名和口令,因为这些字段是必需的。而且,还需要查询 USERDISABLED 表,确认用户的帐户没有被禁用。
接下来,要创建 LoginAction.java
类,如清单 3 所示:
清单 3. LoginAction.java 类
public class LoginAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {if (isValidUser(loginForm.getUserName(), loginForm.getPassword())) { request.getSession().setAttribute( "userName", loginForm.getUserName()); return mapping.findForward("success"); } else { ActionErrors errors = new ActionErrors(); errors.add("userName", new ActionError("invalid.login")); saveErrors(request, errors); return new ActionForward(mapping.getInput()); } }//Query User Table to find out if userName and password combination is right. public boolean isValidUser(String userName, String password) { //SQL Logic to check if username password combination is right }} |
在这里,execute()
方法用于验证用户名和口令是否有效。示例应用程序用 USER
表保存用户名和口令。如果用户的凭证有效,则会在请求范围内保存用户名,并把用户转到登录成功页面(Success.jsp)。
创建 struts-config.xml 文件,如清单 4 所示:
清单 4. struts-config.xml 文件
<action-mappings> <action path="/login" type="com.sample.login.LoginAction" name="loginForm" scope="request" input="Login.jsp"> <forward name="success" path="/Success.jsp"/> </action></action-mappings> |
如果登录不成功,那么用户会被重新定向到登录页面。
创建 Success.jsp 页面,如清单 15 所示:
清单 5. Success.jsp 页面
<HTML><HEAD><%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %><%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %><%@ page language="java" contentType="text/html; %><META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><TITLE>Success.jsp</TITLE></HEAD><BODY><% String userName = (String)session.getAttribute("userName");%>Login Successful<br/><P>Welcome: <%=userName%> .</P></BODY><HTML> |
在这里,可从属性范围中读取 userName
属性,并用它来欢迎已经登录的用户。
|
模拟测试是对应用程序进行单元测试的流行方式。如果是初次接触模拟测试方式,想了解更多的内容,那么请参阅参考资料。
要使用模拟方式,必须对示例应用程序做少许修改。首先要从编写模拟测试开始:
- 把 strutstest-2.1.*.jar 和 junit3.8.1.jar 添加到 classpath。
- 把 WEB-INF 文件夹添加到 classpath。
- 创建
MockLoginTestAction
类,它扩展了MockStrutsTestCase
类。 - 运行单元测试用例。
现在就完成了对环境的设置,可以开始编写单元测试用例了。
首先,需要验证用户是否没有输入用户名或口令,然后向用户显示适当的错误信息,并将用户重定向到登录页面。可以在 MockLoginTestAction
类中创建 testLoginActionFormError()
方法, 如清单 6 所示:
清单 6. testLoginActionFormError() 方法
public void testLoginActionFormError()throws Exception{ setRequestPathInfo("/login"); actionPerform(); String[] actionErrors = {"username.required","password.required"}; verifyActionErrors(actionErrors); verifyInputForward();} |
在编写 STC 测试用例时,要做的第一件事就是告诉 STC 要测试哪个 ActionMapping
类,在这里要测试 LoginAction
,它被映射到 struts-config.xml 文件中的 "/login" 路径,因此我们必须调用 setRequestPathInfo("/login")
。默认情况下,STC 在 /WEB-INF/ 文件夹中查找 struts-config.xml 文件。如果在 classpath 没有这个文件,就必须用 struts-config.xml 文件的完整路径调用 setConfigFile()
。
现在可以执行测试用例了。首先要调用 actionPerform()
方法,把控制权传递给 Struts 框架,执行测试用例。一旦控制权从 actionPeform()
返回,就可以调用 verifyXXX()
方法,测试对程序的假设。在示例应用程序中,我们想测试一下,在没有用户名和口令的时候,调用 LoginAction
映射是否会利用出错信息 ActionErrors
(用于 username.required
和 password.required
)将用户重定向到登录页面。verifyInputForward()
方法检查这个事务的结果是否把用户重定向到动作映射的输入属性指定的页面,在这个例子中,该页面是 Login.jsp。
可以用 String
数组调用 verifyActionErrors()
,该数组指出,作为这个事务的结果,应当在请求范围中设置哪些 ActionErrors
。我们想设置 username.required
、password.required
和 ActionErrors
,所以创建了一个 String
数组来保存这些出错信息,并把它们发送给 verifyActionErrors()
方法。
ActionServlet
在 Struts 框架中是一个控制器 servlet。当容器得到请求时,会把请求传递给 ActionServlet
,由后者进行所有的请求处理。
STC 背后的基本想法是自行创建 ActionServlet
对象,而不是让容器来创建它,然后再调用对象上的适当方法。ActionServlet
在初始化时需要 ServletContext
和 ServletConfig
对象,在请求处理时需要 HttpServletRequest
和 HttpServletResponse
对象。STC 创建这些类的模拟对象,并把它们传递给 Struts。
MockStrutsTestCase
是一个扩展了 junit.framework.TestCase
类的 JUnit 测试用例,所以每个测试用例都会执行 setup()
方法。在 MockStrutsTestCase
对象的 setup()
方法中,STC 创建 ActionServlet
对象和其他必需的模拟对象。
在调用 setRequestPathInfo()
或 addRequestParameter()
方法时,会调用模拟 HttpServletRequest
对象的适当方法。在 HttpServletRequest
的模拟实现中,会把这条信息保存在适当的设置状态。所以,如果调用 addRequestParameter("name","value")
,模拟的 HttpServletRequest
对象会保存它,然后,在 Struts 调用 request.getParameter("name")
时,用 "value"
作为返回值。
在恰当地完成 HttpServletRequest
初始化之后,就可以调用 actionPerform()
方法把控制权传递给 Struts。actionPerform()
方法调用 ActionServlet
的 doPost()
方法传递 HttpServletRequest
和 HttpServletResponse
的模拟实现。
在 ActionServlet
的 doPost()
方法中,处理请求的方式与其他 Struts 请求的处理方式类似,区别是直到执行 ActionForward
JSP 组件之前才停止请求处理。在这个阶段,模拟对象的状态会被修改,以指出已经保存 ActionErrors
或 ActionMessages
,或者指出由此生成的 ActionForward
是什么。
一旦控制权从 control returns from the actionPerform()
方法返回,就可以调用适当的 verifyXXX()
方法(检测模拟对象的状态)来检查各种假设是否成立。
LoginActionForm
类的 isUserDisabled()
方法存在一个问题。在这个方法中,是通过查询 USERDISABLED 表来找出用户帐户是否被禁用。但是在当前的环境下,我们不想把时间浪费在设置和查询数据库上。
请记住,我们的目标是检查应用程序的 Struts 部分,而不是检查数据库的交互代码。为了测试数据库交互代码,可以从若干个可用工具中选择一个工具,例如 DBUnit。针对这一情况的最佳方案应当是创建一个 LoginActionForm
类的子类,并重写其中的 isUserDisabled()
方法。这个方法将根据输入参数的值判断是返回 true
还是返回 false
。
比如在这个例子中,方法会一直返回 true
,除非用 disabledUser
作为输入参数调用它。现在只应当在单元测试阶段使用这个方法,而主程序 LoginActionForm
不应当知道这一点。针对这个需求,我创建了 STCRequestProcessor
,它扩展了 RequestProcessor
。它允许向 Action
和 ActionForm
类中插入模拟实现。
要使用 STCRequestProcessor
,需要修改 struts-config.xml,如清单 7 所示:
清单 7. struts-config.xml 文件
<controller> <set-property property="processorClass" value="com.sample.util.STCRequestProcessor"/></controller></code> |
这一行指出 Struts 用 STCRequestProcessor.java
作为 RequestProcessor
。不要忘记,在容器中部署应用程序部署时要删除这些行。
接下来是创建 LoginActionForm
的模拟类,如清单 8 所示:
清单 8. MockLoginActionForm.java 类
public class MockLoginActionForm extends LoginActionForm { public boolean isUserDisabled(String userName) { if (userName != null && userName.equals("disableduser")) return true; return false; }} |
isUserDisabled()
方法检查用户名是否为 "disableduser"
。如果是,则应当返回 true
;否则应当返回 false
。
接下来要 创建一个测试用例,对禁用用户进行测试,如清单 9 所示:
清单 9. testDisabledUser() 方法
public void testDisabledUser()throws Exception{ STCRequestProcessor.addMockActionForm("loginForm", "com.sample.login.mock.MockLoginActionForm"); setRequestPathInfo("/login"); addRequestParameter("userName","disableduser"); addRequestParameter("password","wrongpassword"); actionPerform(); verifyInputForward(); String[] userDisabled ={"user.disabled"}; verifyActionErrors(userDisabled);} |
STCRequestProcessor.addMockActionForm()
方法把 MockLoginActionForm
作为 LoginActionForm
的模拟实现插进来。addRequestParameter()
方法设置用户名和口令这两个请求参数。一旦控制权从 actionPerform()
返回,就可以调用 verifyActionErrors()
验证是否利用 user.disabled
出错信息将用户重定向到输出页面。
测试用例要测试 LoginAction
类的 execute()
方法内部的业务逻辑。execute()
方法调用同一个类的 isValidUser()
方法,该方法接下来会查询 USER 表,查看用户名和口令组合是否有效。现在,因为我们不想在测试阶段查询真正的数据库,所以要创建一个 LoginAction
类的模拟子类,重写 isValidUser()
方法,如清单 10 所示:
清单 10. MockLoginAction.java 类
public class MockLoginAction extends LoginAction { public boolean isValidUser(String userName, String password) { if( userName.equals("ibmuser") && password.equals("ibmpassword")) return true; return false; }} |
如果用户名是 "ibmuser"
,口令是 "ibmpassword"
,则 MockLoginAction
类的 isValidUser()
方法将返回 true。调用 STCRequestProcessor.addMockAction()
方法把 MockLoginAction
插入 LoginAction
,如清单 11 所示:
清单 11. testInvalidLogin() 方法
public void testInvalidLogin()throws Exception{ STCRequestProcessor.addMockActionForm("loginForm", "com.sample.login.mock.MockLoginActionForm"); STCRequestProcessor.addMockAction("com.sample.login.LoginAction", "com.sample.login.mock.MockLoginAction"); setRequestPathInfo("/login"); addRequestParameter("userName","ibmuser"); addRequestParameter("password","wrongpassword"); actionPerform(); String[] invalidLogin ={"invalid.login"}; verifyActionErrors(invalidLogin); verifyInputForward();} |
在这个测试用例中,插入了 LoginAction
和 LoginActionForm
的模拟实现,避免数据库查询,接着要设置用户名和口令参数。在控制权从 actionPerform()
返回之后,就可以检查是否利用 "invalid.login"
这条出错信息把用户重定向到登录页面。
现在是时候来验证在用户输入正确的用户名和口令时,是否用成功页面欢迎用户,如清单 12 所示:
清单 12. testLoginActionFormError
public void testValidLogin() throws Exception{ STCRequestProcessor.addMockActionForm("loginForm", "com.sample.login.mock.MockLoginActionForm"); STCRequestProcessor.addMockAction("com.sample.login.LoginAction", "com.sample.login.mock.MockLoginAction"); setRequestPathInfo("/login"); addRequestParameter("userName","ibmuser"); addRequestParameter("password","ibmpassword"); actionPerform(); verifyNoActionErrors(); verifyForward("success");} |
这一代码段首先在请求参数中把用户名设置为"ibmuser"
,并把口令设置为 "ibmpassword"
,然后调用 actionPerform()
。在执行 actionPerform()
方法时,需要调用 verifyForward()
方法,检查用户是否被重定向到成功页面。它还调用了 verifyNoActionErrors()
方法,以验证在这个事务中没有出现 ActionErrors
。
|
使用模拟方式有一些优势。这种方式比较快,因为不必为了每个更改而启动和停止容器。另一方面,因为没有使用真正的容器,所以可能无法验证监听器或过滤器带来的副作用。而且,因为没有执行 ActionForward
JSP 组件,所以也无法发现 JSP 中的错误。
|
Cactus(容器内)是集成测试阶段的一种流行测试方法。这里不对它进行详细介绍 Cactus,有关的更多信息,请参阅参考资料。
要设置 Cactus,需要将 cactus.1.6.1.jar 和 aspectjrt1.1.1.jar 复制到 classpath 中。
Cactus 需要在 Web 应用程序中配置两个 servlet,所以必须在 web.xml 文件中声明它们,如清单 13 所示:
清单 13. web.xml
<servlet> <servlet-name<ServletTestRedirector</servlet-name> <display-name<ServletTestRedirector</display-name><servlet-class<org.apache.cactus.server.ServletTestRedirector</servlet-class></servlet><servlet> <servlet-name<ServletTestRunner</servlet-name> <display-name<ServletTestRunner</display-name> <servlet-class<org.apache.cactus.server.runner.ServletTestRunner</servlet-class></servlet><servlet-mapping> <servlet-name<ServletTestRedirector</servlet-name> <url-pattern</ServletRedirector</url-pattern></servlet-mapping><servlet-mapping> <servlet-name<ServletTestRunner</servlet-name> <url-pattern</ServletTestRunner</url-pattern></servlet-mapping> |
接下来要创建 cactus.properties 文件,并把它放在 classpath 中,如下所示:
cactus.contextURL = http://localhost:9080/sample1cactus.servletRedirectorName = ServletRedirector |
本文使用 WebSphere Studio 内置的测试环境来运行测试用例,所以可以从 http://localhost:9080/sample1 访问示例应用程序。请确保把这个路径修改成指向 Web 应用程序实际部署位置的路径。
接下来要创建一个类,扩展 CactusStrutsTestCase
。因为在模拟和 Cactus 方式中可以使用相同的测试用例,所以可以在这个类中复制 MockLoginActionTest
的内容。在选中的容器中构建并部署这个应用程序。
最后,把 jdbc/ds1
配置成数据源。
在使用 Cactus 测试应用程序的时候,必须把应用程序部署在 Web 容器中,还要在容器外面用 JUnit 测试用例的形式运行 Cactus 测试用例。在运行 Cactus 单元测试时,它会为类中的每个测试用例方法都创建并执行一个针对 URL 的HTTP 请求,URL 由 cactus.properties 文件中 cactus.contextURL
参数指定。
在示例应用程序的例子中,在执行 testDisableUser
时,会创建并执行以下请求:
http://localhost:9080/sample1/ServletRedirector?Cactus_TestMethod=testDisabledUser&Cactus_TestClass= com.sample.test.CactusLoginActionTest&Cactus_AutomaticSession=true&Cactus_Service=CALL_TEST |
这个请求会调用 ServletTestRedirector
servlet(作为示例 Web 应用程序的一部分部署)。在 ServletTestRedirector
中,Cactus 从 Cactus_TestClass
请求参数中查找测试用例类的名称,并调用 Cactus_TestMethod
参数指定的方法。在执行这个方法之后,就会以 HTTP 响应的方式把结果返回 Cactus
测试类,这个类将执行一个外部容器。
此外,在 testDisabledUser()
方法中的 CactusStrutsTestCase
的容器内(in-container)版本得到控制时(在本文的示例中是 CactusLoginActionTest
),STC 会调用 actionPerform()
方法,该方法将创建 ActionServlet
、ServletContext
和 ServletConfig
对象的实例。STC 还在包装器中包装了当前的请求和响应。然后它调用 ActionServlet
的方法 doPost()
,该方法使用的参数是这些包装的 ServletRequest
和 ServletResponse
对象。然后 Struts 会像平常一样处理请求。
通过使用 Cactus 方式,就可以调用 processRequest(true)
方法告诉 STC 验证转发 JSP,从而执行和测试转发的 JSP,以确保不会抛出任何编译和运行时错误。
一旦控制权从 actionPerform()
返回,就可以调用各种 verifyXXX()
方法检验假设是否成立。
修改 testVaidLogin()
方法,测试 Success.jsp,保证它没有编译时错误或运行时错误, 如清单 14 所示:
清单 14. testValidLogin() 方法
public void testValidLogin() throws Exception{STCRequestProcessor.addMockActionForm("loginForm","com.sample.login.mock.MockLoginActionForm"); STCRequestProcessor.addMockAction("com.sample.login.LoginAction","com.sample.login.mock.MockLoginAction"); processRequest(true); setRequestPathInfo("/login"); addRequestParameter("userName","ibmuser"); addRequestParameter("password","ibmpassword"); actionPerform(); verifyNoActionErrors(); verifyForward("success"); } |
还要修改 Success.jsp,添加以下几行,让它抛出 RunTimeException
异常:
<% throw new RuntimeException("test error");%> |
现在,当运行这个测试用例时,testValidLogin()
会创建并执行数据库查找,检查用户帐户是否禁用,用户名和口令是否有效。如果测试失败,则表明在执行 Success.jsp 时遇到了运行时错误。
|
使用 Cactus 当然有优势,但是困难也不少。从正面来说,它允许测试 JSP 页面的编译和运行时错误,还允许测试数据访问代码。从负面来说,这种方式要求把应用程序部署在容器中,然后每做一次修改都要启动和停止容器,这使 Cactus 成为一种较慢的模拟方式。
|
单元测试提供了很多好处。除了让人确信代码按照设计的方式工作之外,测试还是造就优秀文档的原因。而且,在设计类和接口时,单元测试还提供了一个优秀的反馈机制。最后,单元测试对于管理变化也很有帮助。如果在对代码进行更改之后,代码通过了所有单元测试,那么就可以确信这些更改是安全的。
不幸的是,许多开发人员放弃了单元测试,因为他们要花太多时间来编写测试代码。但是通过使用 STC 的模拟方式,可以把通常花费在设置特定领域(例如数据库和容器)开发环境上的大量时间节省下来。因为不必每次都重新启动和停止容器,所以 STC 还有助于迅速测试变化。一旦代码稳定下来,能够通过所有测试用例,那么只要改变一下测试用例的父类,就可以将它用于集成测试。在集成阶段使用 Cactus 还允许您自动化集成测试过程。
|
sample1.zip | 21 KB | FTP |
关于下载方法的信息 | Get Adobe® Reader® |
相关推荐
总的来说,StrutsTestCase是Struts开发中不可或缺的工具,它简化了测试过程,使得开发者能够更高效地测试和调试Action类,从而提升整个应用程序的稳定性和可靠性。通过深入研究这个工程例子,你可以掌握使用...
AppFuse 是一个开源的Web应用程序开发框架,旨在简化Java Web应用程序的构建过程,尤其是在使用Spring、Hibernate或iBATIS等技术栈时。通过AppFuse,开发者可以快速搭建基础的开发环境,节省大约85%的初期开发时间。...
AppFuse架构是一个基于开源技术构建的Web应用框架,旨在简化开发流程并提供可扩展的结构。这个框架的主要目的是为了帮助开发者快速启动一个新的企业级项目,通过整合多种流行的技术,如Struts、Hibernate和Spring,...
尽管Struts1提供了动态`ActionForm`简化开发过程,但依然需要在配置文件中定义`ActionForm`。 - **Struts2**:直接使用Action类中的属性来封装用户的请求参数,无需额外的`ActionForm`类。这不仅减少了开发工作量,...
该框架旨在简化基于Java Servlet和JavaServer Pages (JSP)技术的应用程序开发过程,并提供了一个标准化的解决方案,让开发者可以更加专注于业务逻辑而非框架本身。 #### Struts框架的优点 1. **开源性**:Struts是...
总的来说,`struts2-junit-plugin`是Struts2开发过程中不可或缺的一部分,它简化了测试流程,提高了代码质量。通过这个插件,开发者可以更有效地测试Action类,确保它们按照预期工作,从而构建出可靠的Java Web应用...
Junit则是Java编程语言中最常用的单元测试框架,它简化了对代码进行测试和调试的过程。 `struts2-junit-plugin-2.1.8.1.jar` 是一个特定版本的Struts2 JUnit插件,它的版本号是2.1.8.1。这个插件允许开发者在JUnit...
因此,在开发过程中需要严格按照这一流程来编写代码。 **Struts2:** Struts2为每个请求提供了更加灵活的处理流程。它使用拦截器(Interceptors)机制来管理请求处理过程中的各个阶段。这使得开发者可以根据实际...
3. **ActionForms使用不便:** Struts中的ActionForms在使用过程中可能存在不便之处,例如,它们无法直接进行单元测试(通常需要借助StrutsTestCase进行集成测试)。此外,由于所有数据默认都是以字符串形式存储,...
6. **开发与调试**:使用这三个框架,开发者可以利用它们提供的工具和API进行开发,如Struts 2的StrutsTestCase进行单元测试,Hibernate的Criteria或HQL进行复杂查询,Spring的AspectJ Weaver进行AOP编译。...
在开发过程中,错误和异常是无法避免的。Struts提供了异常处理机制,允许开发者定义全局或特定Action的异常策略,提高应用的健壮性。 10. **测试与调试**: 为了确保系统稳定,测试是必不可少的。Struts支持JUnit...
1. **对象关系映射(ORM):** Hibernate是一个开源的ORM框架,它将Java对象映射到关系型数据库表中,简化了数据持久化过程,使得开发者可以使用面向对象的方式进行数据库操作。 2. **跨平台:** Hibernate支持多种...
Struts2.x还支持多种视图技术,包括JSP、FreeMarker、Velocity等,同时提供了丰富的标签库,简化了页面开发。 #### 转换与验证 Struts1.x的验证机制基于ActionForm,利用Commons Validator等库进行数据校验,而...
Struts2提供了ActionSupport基类来简化Action的实现。Action本身可以是任何实现了特定接口的Java对象,甚至是普通的POJO。这种设计使得Struts2更加灵活,易于维护。 #### 架构模式 - **Struts1**: 在Struts1架构中...
此外,Struts2还提供了一个`ActionSupport`基类,用于简化Action的开发过程。因此,在Struts2中,Action对象可以更加独立于具体的Web容器,提高了代码的可重用性和灵活性。 - **与Servlet API的交互**:Struts1的...
为了简化测试,通常会使用StrutsTestCase提供的模拟环境。 - **Struts2**:相比之下,Struts2中的Action类更加灵活。它们可以是任何实现了Action接口的Java类,甚至是普通的POJO(Plain Old Java Object)。Struts...
- 测试Struts1的Action时,通常需要模拟整个Servlet环境,使用如StrutsTestCase等工具进行单元测试。 - **Struts2中的Action** - Struts2采用了更灵活的Action设计,允许Action实现多个接口或者继承自`...