1. 开发环境
本文开发环境为 MyEclipse10 和 Struts 2.1,Spring 和 Hibernate 使用 MyEclipse 内置的版本。
2. 建立 Web 工程并添加 Struts 支持
File新建一个Web Project,命名为NeuqStudent,javaEE默认5.0版本,右键工程名-->Add Struts Capabilities...选择Struts2.1,下面是过滤器的名字和URL,如图。
在系统中加入 Struts 支持,实际上就是要在系统中增加一个 Struts“过滤器(filter)”;所有的文件,在以页面形式展示 到用户的浏览器之前,先要通过该过滤器“过滤”(即处理)一遍,这样给了 Struts 控制模块一个处理页面中特有的 Struts 标签的机会;也就是说,后台程序可以将这些 Struts 标签“翻译”成为相关的数据并处理后,才将生成的页面提交给 终端用户。
也可之后在系统中添加Struts “过滤器”,方法是设置系统的全局配置文件 web.xml ;该文件在工程的树形结构中位于 WebRoot/WEB-INF 目录下。我们暂不需要理解复杂的配置语法,只需要在 MyEclipse 的 Package 窗口中,找到该文件 并双击,即可进入图形化的 web.xml 配置界面。该界面中,树型结构的第二项,即是“Fileters”,选中后使用 窗体右边的“Add”按钮,弹出“Add Filters”对话框;这个框中只有两项带“*”号的项目是必填的:
第一项是要为我们的过滤器起一个名字,你可以随便起一个好记的名称,例如“struts2”;
第三项是实现该过滤器的 Java 类;点击“Browse”按钮,输入 StrutsPrepareAndExecuteFilter(实际上你只需要输 入前几个字母,例如 strutsp 就可找到该类),将该类设为过滤器类即可。
添加完过滤器后,还需要指定哪些文件必须通过该过滤器。在我们的例子中,我们简单地要求所有的文件都要通过 Struts 过滤器,因此我们可以这样来设置过滤器的“mapping”:点击 web.xml 树形目录的 Filters,在右边“Filter Mappings” 列表框旁边,点击“Add”按钮,输入我们刚才的过滤器名“s2”,并在“URL-Pattern”处输入“/*”,即要求系统根目 录下所有的文件都需要通过该过滤器处理。保存 web.xml 文件;这时我们的 WarpSpeed 工程可以说已经完全支持 Struts2 了。配置完成后的web.xml如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping></web-app>
3. 设计一个最简单的 Struts2 系统
在设计一个最简单的 Struts 系统之前,我们需要理解这样两个概念:“action”的执行和导航。
(1) 所谓“action”(“动作”),就是在表单提交后系统会自动执行的一个 Java类,该类必须继承 ActionSupport(在 com.opensymphony.xwork2 中)并重写其中的 execute()方法。表单提交后,系统会将表单里包含的字段数据传递给 该 action 类,并执行其中的 execute()方法。
(2) execute()方法必须返回一个字符串,而该字符其将决定系统要转向那个页面;这就是所谓的“导航”。 因此,一个最简单的 Struts 系统,起码包括这样几个文件:
带有表单的页面文件(jsp 文件) 表单提交后要执行的 action(java 类) Action 执行完毕要转向的页面(jsp 文件)
因此,在构建系统前,我们首先要构思我们的系统到底需要怎样的功能结构,以及需要哪些文件来实现这些功能—— 这正是软件工程的“设计”阶段的任务。作为最简单的例子,我们可以这样设计我们的系统:
(1) 页面 index.jsp,其中包含一个简单的 form,该 form 的 action 名为“aCheck”,其中包含两个文本字段:name和 password;
(2) 表单提交后要执行的 action 类为 AccountCheck;
(3) AccountCheck 类执行时,打印出传递过来的 name 和 password 参数的值
(4) AccountCheck 执行后转向页面 index2.jsp。
为了将这一个构思传递给系统,我们需要使用 struts.xml 来配置这几个文件之间的逻辑关系。修改struts.xml代码如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <package name="default" namespace="/" extends="struts-default"> <action name="aCheck" class="com.neuq.check.AccountCheck"> <result name="toIndex2">/index2.jsp</result> </action> </package> </struts>
说明:
(1) “action”标签定义了一个动作,该动作由其 name 属性确定,并和页面表单中的“action=”属性相对应;class 属 性则指定了该动作由哪个 Java 类来实现。例如,上面的代码相对应的页面表单应该有如下形式:
<form action="aCheck">...</form>
则上述 form 提交时,系统将寻找 AccountCheck 类并执行之。
(2) “result”标签定义了在动作执行之后的跳转(导航),其中 name属性和动作中 execute()函数的返回值相应,也就 是说,如果动作中 execute()返回值为字符串“toIndex2”,则系统跳转到 index2.jsp 页面。
(3) package 是对 action 分类的标签,其最核心的属性是“name”,该 name 是与其他 package 区分的依据;而 namespace(命名空间)属性则定义了到哪个地址寻找其下属的 action;例如,namespace="/example" 表示,如果请求的动作的URL 是/example/HelloWorld.action的话,系统首先到/example 命名空间寻找“HelloWorld”动作对应的 Java 类;如果没有找到,系统还会到默认的命名空间去寻找,以及到“/”根命名空间寻找。对于我们修改后的例子,我们只是简单的定义了一个名为“default”的 package 并指定根命名空间。需要注意的是,命名空间只有“一层”,而不是像文件目录那样可以有多个层次。另注意:URL 中“xxx.action”和简化形式的“xxx”是等同的。
4. 实现最简单的 Struts2 系统
对于上面设计好的简单 Struts2系统,我们可以根据 struts.xml 的要求按下面步骤实现之——注意这里体现的软件工程 思想:先设计,后实现:
(1) 页面表单编码:Web 工程默认的“入口”页面是 index.jsp,位于 WebRoot(相当于网站的根目录)下。最简单的支持Struts2 框架的 JSP 文件结构为:
<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <body> </body> </html>
也就是说,最上面两行最关紧要!使用上面的模板替换系统中 index.jsp 原来的内容,并在<body>标签内加入 struts 表 单:
<s:form action="aCheck"> <s:textfield name="name" value="wang"></s:textfield> <s:textfield name="password" value="123"></s:textfield> <s:submit></s:submit> </s:form>
其中“s:”是由上面所示第二行代码
<%@ taglib prefix="s" uri="/struts-tags" %>
规定的 struts 标签的前缀,也就是说,所有 struts 标签都要以“s:”打头。“form”和“submit”标签和 HTML 表单中类似的标签的意义相同,而“textfield”标签相当于 HTML 表单的 input 标签。请注意下划线的部分:action 属性定义的 名称"aCheck"和 struts.xml 中的 action name 是一致的;两个 textfield 定义了两个表单字段,一个名为“name”,另一个 名为“password”。用户在这两个字段中输入的数据将被 Struts 传递到后台 action 程序中。
(2) 动作编程:根据 struts.xml 要求,我们要编写一个名为“AccountCheck”的类来实现 action“aCheck”,放在com.neuq.check下。这个类 有 4个要求:
a) 继承 ActionSupport;
b) 包含表单字段对应的属性变量;
c) 对上面的属性变量编写 getter 和 setter 方法;
d) 重写 execute()方法,并返回与 struts.xml 对应的字符串以进行导航。
AccountCheck.java 的代码如下:
package com.neuq.check; import com.opensymphony.xwork2.ActionSupport; public class AccountCheck extends ActionSupport { private String name; private String password; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String execute() { System.out.println(name + password); return "toIndex2"; } }
上文中的核心代码只有 4 行,前两行只是声明了与表单字段相对应的变量(Struts 会自动在表单和 action 类之间进行数据传递);第三行将传递过来的字段值打印出来(一个简单的数据处理 );最后一行返回字符串“toIndex2”以指示系统导航到/index2.jsp 页面。注意其中的 setter 和 getter 函数分别用于设置和获取字段变量的值;但是我们在上面的代码中并没有看到对 getter 和 setter 的引用,而其实这正是 Struts 的奇妙之处:当 execute()被执行时, 所有的字段变量已经在 Struts 的控制调度下被设置好了!
(3) 结果页面编程:根据 struts.xml 的要求,我们的结果页面是 index2.jsp;目前我们暂不需要在该页面中工作,因 此您可以随便写个页面并命名为 index2.jsp 即可。
现在我们可以运行我们的系统了。在安装了tomcat6.0后,将工程部署在tomcat下,运行。在浏览器中输入http://localhost/NeuqStudent/index.jsp
我们可以输入一些内容,点击“Submit”按钮,系统将自动转到 index2.jsp, 并在控制台打印出来您输入的内容(由 execute()函数中的 println()实现)。
在这一阶段常见的错误是
HTTP Status 404 - There isnoAction mapped for namespace / and action name xxx该错误意味着在你指定的命名空间没有找到名为 xxx 的动作(同时在“根”命名空间也没有找到)。你需要查看并修改你的struts.xml 配置文件。
5. 莫名其妙的错误?
MyEclipse 首次启动的时候,会要求你建一个“工作区(workspace)”,后继的工程文件均存放到这个工作区文件夹中。 如果在你的学习过程中,编写了多个工程,有时候会出现莫名其妙的错误,那么除了认真阅读错误提示并进行更正意 外,有些错误可能是你前期的工程遗留下来的,即使你早已删除了那些工程,其发布到 tomcat 中的应用并没有移除干净!
解决的方法很简单:
退出 MyEclipse,到 workspace 目录,在.metadata\.me_tcat\webapps 中有你已经发布所有工程的文件夹,找到原来的工程文件夹,删除那些有问题的工程(或者干脆全部删除,因为这并不影响你的源文件),然后重新启动 MyEclispse 就可 以了。因此,如果你怕麻烦,最好一个工程使用一个独立的工作区。
6. 结果页面编程
从上面的实验当中可以看到,Java 的打印语句只能在服务器的控制台上输出结果,而不能将结果显示到用户的浏览器 中。Struts 将 action 处理的数据(包括表单提交给 action 的数据)和应用(Application)范围内的数据,都存储在一个 叫做“值栈”(valueStack)的地方;有很多种方法可以从这里取出值来。现在我们重新对 index2.jsp 编程,已将这些值 取出到页面中:
首先,使用通用的 struts 页面模板替换 index2.jsp 的内容,并在<body>标签内加上:
<s:text name="password"/><hr/> <s:property value="password" /><hr/> ${password}<hr/>
运行一下试试。可以看到,三种方法都可以将输入的 password 显示出来。其中前两种为 Struts 标签形式,${password}的写法是 OGNL 表达式语言,其用法暂略。
7. 结果页面导航
如果我们需要根据后台程序的处理结果转向不同的页面的话,必须同时配置 struts.xml 和 action。例如,如果要在传递过来的name 和 password 参数的值分别为“dj”和“123”时,系统导航转向 index2.jsp 页面,否则的话转向验证失败页面fail.jsp,则我们可以先配置 struts.xml 如下:
<action name="aCheck" class="com.neuq.check.AccountCheck"> <result name="toIndex2">/index2.jsp</result> <result name="toFail">/fail.jsp</result> </action>
根据这一配置,我们需要在 action 的 execute()方法作相应修改:
public String execute() { if (name.equals("dj") && password.equals("123")) return "toIndex2"; else return "toFail"; }
最后,需要实现 fail.jsp;由于这个页面比较简单,只需要将 index2.jsp 另存为 fail.jsp,并将其页面内容修改为“失败” 信息即可(略)。
再次运行工程,则输入数据不同会导航到不同的页面。至此,我们已经完整的体验了 Struts2 简单而强大的前后台交互及表现能力。下面我们看看如何方便地与底层数据处理进行交互。
8. 为工程添加 Spring 支持 在工程名上点鼠标右键并选择
“MyEclipse”—>“Add Spring Capabilities...”
为简单起见,因为系统内置的 Spring 支持是 2.5 版本的,我们选中所有 2.5 版的 Spring 包,并选择“拷贝支持包到 lib
目录”;另特别注意:
(1)将 Spring 的配置文件 applicationContext.xml 放到 WEB-INF/目录下(而不是缺省的 src目录);
(2)重要:web.xml 中增加一个 listener:ContextLoaderListener; 上述第(2)项使得我们可以方便的获取当前程序的运行上下文,从而得到 DAO 对象以操纵数据库。
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
9.添加 Hiberbate 支持
和上面的步骤类似,我们为工程添加 Hibernate 支持。同样选择将 Hibernate 的所有支持包拷贝到 lib 目录下;在“配置文件”选项中,选择使用已有的 Spring 配置文件(即上一步中的 WEB-INF/applicationContext.xml);
数据库选用Sql Server2008,
在最后的选项窗口中,我们还要为 Hibernate 创建一个专用的包:点击“Java Package”右边的“New”按钮,在 src 目录下面输入你的包名com.neuq.common即可;这个包是你以后放置 Hibernate 有关文件的包。
10.建立数据源
window-->showview-->DB Brower,在空白处右键,新建,选择sqlserver驱动,填写自己的驱动名称,连接sqlserver2008的URLjdbc:sqlserver://localhost:1433;DatabaseName=student(其中student是数据库的名称),下面填写数据库用户名和密码,添加固定的连接jar包(需要自己网上下载)
下一步,选择第三项,选择自己的数据库,点击完成即可。
student数据库的student表设计如下:
11.打开数据源
右击刚才建立的数据源studentdriver,打开
12. 更为奇怪的错误(可能出现)
直到目前为止,我们还没有进行任何涉及底层数据库操作的编码工作,仅仅是为我们的工程添加了 Spring和 Hibernate 的支持而已。现在我们看看在新的支持下,原来的页面还能正常运行否——竟然是“404”(资源无法找到)错误!
您可以仔细研究 Console 控制台中显示的异常信息,但是,我可以告诉你一个简单得多的经验:这个错误本来不应该发生!出错的原因是你添加的各种支持里面所包含的 JAR 包有重复的,并且版本不一致!展开“Package Explorer”中的“Referenced Libraries”,可以看到工程中所引用的所有 JAR 包;现在知道为什么在前面的步骤中要将支持的 JAR 包拷贝到同一个 lib 目录下面了吧:起码我们检查重复 JAR 包的时候方便多了。 仔细检查后可以发现,“asm-2.2.3.jar”和“asm.jar”以及“cglib-nodep-2.1.3.jar”和“cglib-2.1.3.jar”是重复的;我们要 删除这两对中的后者,方法是:在要删除的包上面点击鼠标右键并选择“Build Path”—>“Remove From Build Path” 然后就可以删除了。 再运行一下试试,如果还不行,就要按照上面第“6”步所说的方法,彻底地清空一下已经发布的文件了。
13. 设计一个最简单的 Table记录显示系统目的:从“student”表中读出所有数据,并显示在页面中。流程:
(1) 在 index3.jsp 中建立一个表单,对应的动作是“showList”;
(2) “showList”对应的 Java 类命名为“StudentList”,它在 Struts 的调控下获取数据表中的记录;
(3) “showList”执行完毕后转向 studentlist.jsp,在该页面上显示动作类获取的数据。
14. 实现最简单的 Table 记录显示系统
根据上述设计,首先修改 struts.xml 文件,添加如下的动作配置:
<action name="showList" class="com.neuq.list.StudentList"> <result name="toList">/studentlist.jsp</result> <result name="toFail">/fail.jsp</result> </action>
然后依次编码所需要的各个文件:首先是起始页面 index3.jsp:
<%@ page contentType="text/html; charset=UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <body> <s:form action="showList"> <s:submit value="List students"></s:submit> </s:form> </body> </html>
这里面实际上只有一个 submit 按钮。
然后是动作类 StudentList.java;因为该类需要读取数据表“student”,因此在编写该类之前需要 先对所涉及的表进行所谓“逆向工程”以生成相关的实体类和 DAO(数据存取对象)类。方法是:
(1) 在 Database Explorer 中 , 找 到 数 据 表 “student” 并 点 击 右 键 , 选 择 “ Hibernate Reverse Engineering”,设定 Java srcfolder(点击 Browse 选择/WarpSpeed/src)和 Java Package(创建的common包吗?就是这个),勾选下面的三个复选框(其中“Create Abstract Class”不用选;这三个复选框的含义就是指定使 用逆向工程生成数据表相关的实体类或说 POJO 类以及对应的 DAO类)。
(2) 第二页中,比较重要的是确定 Id 生成策略,例如,如果你的主键是自增生成的 id,请使用 identity 策略。点击“Next”到下一页。
(3) 第三页中,注意在表清单的下方,有两个复选框,“Include referenced tables”和“Include referencing tables”,意思 是在逆向工程的时候要包含和当前表有关联的其他表。
执行逆向工程后,在 Package Explorer 中可以看到 src/hib 包下面多了许多源文件,例如Student.java 是 student表对应的实体类,而 StudentDAO.java 则是其 DAO 类。说明:DAO类:
DAO类中集成了对实体类的通用操作,例如 findAll(),findBy(),attachDirty()等;特别地,DAO 类包含一个静态方法 用于从应用上下文中获取该 DAO 类的一个实例:getFromApplicationContext(ApplicationContext ctx);这样只要我们获取了当前应用的上下文(Context)后,即可取得 DAO 实例并通过该实例操作数据对象了(参见下面的步骤)。数据处理action的“三板斧”为:
(1) 获取当前应用上下文;
(2) 获取实体类的 DAO 对象实例;
(3) 使用 DAO 对象操作数据;
特别提醒:在使用 DAO 对象操作数据时,经常使用 Java的集合类对象,例如 List 等。
EmployeeList.java 核心代码为:
package com.neuq.list; import java.util.List; import org.apache.struts2.ServletActionContext; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import com.neuq.common.Student; import com.neuq.common.StudentDAO; import com.opensymphony.xwork2.ActionSupport; public class StudentList extends ActionSupport { public String execute() { ApplicationContext ct = WebApplicationContextUtils .getWebApplicationContext(ServletActionContext .getServletContext()); StudentDAO dao = StudentDAO.getFromApplicationContext(ct); List<Student> list = dao.findAll(); int n = list.size(); for (int i = 0; i < n; i++) { Student c = list.get(i); String name = c.getName(); System.out.println(name); } return "toList"; } }
我们暂且不实现 studentlist.jsp,先测试一下已经实现的部分: 运行工程;系统自动打开一个浏览器,其地址栏中显示的是工程的 Web 主目录,形如:
http://localhost/NeuqStudent/index3.jsp,即可显示该起始页面。点击“List Students”按钮,则浏览器提示“404” 无法找到资源错误(暂且不用管它,我们下面再来解决);但是你可以看到,控制台中已经打印出来所有的员工名单了。
15. 在结果页面上显示记录
上面的实现还有缺陷:我们并没有将 action 获取的数据带到结果页面上。要做到这一点,必须进行两项工作:
(1) 在 action 中将需要传递给结果页面的数据声明为类属性并为其编写 setter 和 getter 函数。
(2) 在页面中使用 Struts 标签取出 action 传递过来的数据。
因此我们首先将 EmployeeList.java 做如下修改:将 list 声明为类属性,并为其 list 添加 getter 和 setter:
注意 execute()中对 list 引用的时候就不需要重复声明了。
package com.neuq.list; import java.util.List; import org.apache.struts2.ServletActionContext; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import com.neuq.common.Student; import com.neuq.common.StudentDAO; import com.opensymphony.xwork2.ActionSupport; public class StudentList extends ActionSupport { List<Student> list; StudentDAO studentDAO; public List<Student> getList() { return list; } public void setList(List<Student> list) { this.list = list; } public StudentDAO getStudentDAO() { return studentDAO; } public void setStudentDAO(StudentDAO studentDAO) { this.studentDAO = studentDAO; } public String execute() { ApplicationContext ct = WebApplicationContextUtils .getWebApplicationContext(ServletActionContext .getServletContext()); studentDAO = StudentDAO.getFromApplicationContext(ct); list = studentDAO.findAll(); int n = list.size(); for (int i = 0; i < n; i++) { Student c = list.get(i); String name = c.getName(); System.out.println(name); } return "toList"; } }
然后编写 studentlist.jsp:
<%@ page contentType="text/html; charset=UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <body> <s:iterator value="list"> studentid: <s:property value="studentid" /> <br /> name: <s:property value="name" /> <br /> department: ${department} <br /> qq: <s:text name="qq" /> <p> </s:iterator> </body> </html>
这里面,我们尝试了几种不同的表现方法。
首先看<s:iterator>标签:它的作用是遍历由 value 指定的“集合型”对象(一般为 Map或 List 类型);在我们的例子中, 我们要遍历的是“list”对象(该对象由 action 传递过来,对应于 action 内的一个类属性)。其次要注意<s:property>标签,它的作用是将 iterator 中的对象的属性取出来,即<s:property value="name"/>的作用 相当于调用 list 的 getFirstname()方法(action 中的 getter 在这里得到了“隐形的”调用)。 从上面的代码中可以看出,除了使用<s:property>之外,我们还尝试了另外两种标签方法,一是<s:text>,它可以生成一个国际化的信息文本;另一个是${department},用的是 OGNL 表达式语言。网上有争论说,既然是 struts2,就尽量用 struts2 的标签;也有人说:OGNL 是主流,应该和<s:>标签配合使用;请自行深入学习后选择。
16.Spring与struts结合(1)复制文件。复制struts2-spring-plugin-x-x-x.jar到WEB-INF/lib目录下。其中的x对应了Spring的版本号。还需要复制commons-logging.jar文件到WEB-INF/lib目录下。
(2)配置struts.objectFactory属性值。在struts.properties中设置struts.objectFactory属性值:
struts.objectFactory = spring
或者在XML文件中进行常量配置:<struts> <constant name="struts.objectFactory" value="spring" /> </struts>(3)修改Spring配置文件applicationcontext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"> </property> <property name="url" value="jdbc:sqlserver://localhost:1433;DatabaseName=student"> </property> <property name="username" value="sa"></property> <property name="password" value="123456"></property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.SQLServerDialect </prop> </props> </property> <property name="mappingResources"> <list> <value>com/neuq/common/Student.hbm.xml</value></list> </property></bean> <bean id="studentDAO" class="com.neuq.common.StudentDAO"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean> <bean id="studentList" class="com.neuq.list.StudentList"> <property name="studentDAO"> <ref bean="studentDAO" /> </property> </bean> </beans>
注意将原来的bean id="StudentDAO"改成了bean id="studentDAO",并且要将对应的StudentDAO.java中最后的getFromApplicationContext函数改为
public static StudentDAO getFromApplicationContext(ApplicationContext ctx) { return (StudentDAO) ctx.getBean("studentDAO"); }再次部署运行,成功!
关于Spring如何与struts2结合,参见http://hi.baidu.com/z57354658/blog/item/c8085234a431a1b0d1a2d36c.html
至此,关于简单的ssh开发就介绍到这里,笔者小白刚接触此架构不久,愿意与大家共同讨论,第一次写博文,希望错误之处大家指出啦~~