MyEclipse6Java开发中文教程 private string message public string getMessage ( return message public void setMessage(string message this message message 这个 Action呢,大家可以看到它是继承自 com.opensymphony. work2 Action Support这个 类,而我们自己定义的业务方法,则是写在方法 public String execute( throws Exception 中,这里我们所做的操作极其简单,就是设置 Action类自身的属性 message的值为字符串 你好!Suts2!"。这个方法的其返回值为常量 SUCCESS,其实取值就是字符串 的" success"。那么这个 success应该跑到哪里去呢?所以接下来我们还需要在配置文件指 明这个类该如何访问,以及最后的结果的显示页面路径。 现在,在 struts.xm中加入一个acon定义,如下代码清单中粗斜体部分所示: <?xm1 "1.0"encoding="UTE-8"?> <I DOCTYPE struts puBlIC //Apache Software Foundation//DTD Struts Configuration 2. 0//EN http://struts.apache.org/dtds/struts-2dtd"> <struts> <package name="default"extendsastruts-default"> !-在这里添加 Action定义 <action name="HelloWorld" class="example. HelloWorld"> <result name="success">/HelloWorld. jsps/result> saction> </package> </struts> 。可以看到 action的名字(name)为 Helloworld,它的类( class)是 example. Helloworla, 同时它还有一个结果页面可以显示:∥ HelloWorld. jsp。 好了,接下来我们要创建这个显示层的JSP文件,选择菜单File>New> JsP( Advanced Template),在这个对话框中的 File name(文件名)框中输入 HelloWorld. jsp,然后点击 Finish按钮即可创建这个JSP页面。接下来将 HelloWorld. jsp 的源代码修改为如下所示: <8@ page contentType="text/html; charset=GBK"8> <80 taglib prefix="s"uri="/struts-tags <html> <head> < title> struts2示例</tit1e> </head> 刘长炯著
MyEclipse 6 Java 开发中文教程 11 刘长炯著 private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } 这个 Action 呢,大家可以看到它是继承自 com.opensymphony.xwork2.ActionSupport 这个 类,而我们自己定义的业务方法,则是写在方法 public String execute() throws Exception 中,这里我们所做的操作极其简单,就是设置 Action 类自身的属性 message 的值为字符串 "你好!Struts 2!"。这个方法的其返回值为常量 SUCCESS,其实取值就是字符串 的”success”。那么这个 success 应该跑到哪里去呢?所以接下来我们还需要在配置文件指 明这个类该如何访问,以及最后的结果的显示页面路径。 现在,在 struts.xml 中加入一个 action 定义,如下代码清单中粗斜体部分所示: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="default" extends="struts-default"> <!-- 在这里添加Action定义 --> <action name="HelloWorld" class="example.HelloWorld"> <result name="success">/HelloWorld.jsp</result> </action> </package> </struts> 。可以看到 action 的名字(name)为 HelloWorld,它的类(class)是 example.HelloWorld, 同时它还有一个结果页面可以显示:/HelloWorld.jsp。 好了,接下来我们要创建这个显示层的 JSP 文件,选择菜单 File > New > JSP(Advanced Template) ,在这个对话框中的 File Name (文件名)框中输入 HelloWorld.jsp,然后点击 Finish 按钮即可创建这个 JSP 页面。接下来将 HelloWorld.jsp 的源代码修改为如下所示: <%@ page contentType="text/html; charset=GBK" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Struts 2 示例</title> </head>
MyEclipse6Java开发中文教程 <h2><s: property value="message"/></h2> message] </body> </html> 这个页面使用了Sus2的标签库和EL表达式来获取 Action类中所定义的 message属性。 这一句<%@ taglib prefix="s"uri="% struts-tags"%>就是从地址/ struts-tags下面寻找标签库, 可能有人会好奇这个地址在哪里呢?答案是它定义在Stus2库文件 struts2core-20.11Jar 里面的文件 META-INF/ struts-tags tld里面,在这个文件的开头有这么一段代码:∠ <?xml version=1.0"encoding=UTF-8?> <!DOCTYPE taglib PUBLIC"//Sun Microsystems, Inc //DTD JSP Tag Library 1.2//EN http://ava.sun.com/dtd/web-jsptaglibrary_1_2.dtd> <tlib-version>2.2.3</tlib-version> p-version>1.2</jsp- <short-name>s</short-name <uri>/struts-tags<uri> 大家可以注意到粗斜体的<um>/ struts-tags</m>刚好与JSP文件引入tag声明里面的um属 性匹配,这样就找到了对应的标签定义位置了。 Tomcat等Web服务器会自动加载所有jar文 件下的 META-INF子目录下的td标记定义文件,这也是为什么好多框架不需要把t文件复制 到 WEB-INF目录下的原因。 到此为止,第一个项目就算开发完毕了。为了便于读者核对,我把这个项目的目录结构 截图给大家,如图122所示,A s¥c 白出 exampl +. HelloWorld.java +)-E JRE System Library [MyEclipse6 0] +l-E Java EE 5 Librarie e-E Referenced Libraries +)-0commons-logging-1.0.4.jar +-0freemarker-2.3.8 +-0ognI 0struts2-core-2.0.11.jar +-0xwork-2.0.4 多 Webroot META-INF 3-C WEB-INF x t helloworld.jsp 图122 struts2heo项目目录结构 现在将它发布后运行,打开 Internet Explorer浏览器或者 MyEclipse自带的Meb浏览器 刘长炯著
MyEclipse 6 Java 开发中文教程 12 刘长炯著 <body> <h2><s:property value="message"/></h2> ${message} </body> </html> 这个页面使用了 Struts 2 的标签库和 EL 表达式来获取 Action 类中所定义的 message 属性。 这一句<%@ taglib prefix="s" uri="/struts-tags" %>就是从地址/struts-tags下面寻找标签库, 可能有人会好奇这个地址在哪里呢?答案是它定义在Struts 2库文件struts2-core-2.0.11.jar 里面的文件META-INF/struts-tags.tld里面,在这个文件的开头有这么一段代码: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>2.2.3</tlib-version> <jsp-version>1.2</jsp-version> <short-name>s</short-name> <uri>/struts-tags</uri> .... 大家可以注意到粗斜体的<uri>/struts-tags</uri>刚好与JSP文件引入taglib声明里面的uri属 性匹配,这样就找到了对应的标签定义位置了。Tomcat等Web服务器会自动加载所有jar文 件下的META-INF子目录下的.tld标记定义文件,这也是为什么好多框架不需要把tld文件复制 到WEB-INF目录下的原因。 到此为止,第一个项目就算开发完毕了。为了便于读者核对,我把这个项目的目录结构 截图给大家,如图 12.2 所示。 图 12.2 struts2hello 项目目录结构 现在将它发布后运行,打开Internet Explorer浏览器或者MyEclipse自带的Web浏览器
MyEclipse6Java开发中文教程 键入如下的地址来进行测试http://ocalhost:8080/struts2hello/helloworld.actiono如果你 看到页面上出现了两行一粗一细的文字,内容为“你好! Struts2!”,如下图所示 ⊙ Struts2示例- Windows Internet Expl He*ahttp://localhost:8080/strutshello/helloworldaction 食 STruts2示例 你好! Struts2! 你好! Struts2 图123第一个 Struts2程序 那么恭喜!我们的第一个应用开发成功了 注意:接下来,我们会对 Struts2的内容做一些深入讨论,供大家参考。当然读者现在 也可以先直接跳过本小节余下的内容,进入下一小节,最后再回过头来看这些内容 现在,我们来简要回顾一下执行流程:首先用户访问地址 Helloworld. action,然后 Struts 的过滤器从 struts xm中解析到name为 Helloworld的 action定义,顺藤摸瓜找到了对应 的类文件 example. HelloWorldAction,接着就执行文件中的方法 execute来设置 message 属性为“你好! Struts2!”,并根据其返回值" success"到 action定义处找到name为 success 的 result定义,而它的真正地址是/ HelloWorld. jsp,所以接着就跳转到JSP页面进行显示, 同时呢大家注意到 Action类里面的 message属性竟然也可以被JSP页面所访问了,这也 是和以前的Suts1很不一样的地方。再以前,我们必须自己访问 request对象,设置属性, 之后才能被前台的JSP页面访问到。这个过程的简写就是 Helloworld. action→ example, HelloWorldAction. java→ execute0→ success→ He| oWorld. jsp→获取 message属性→显示。 再来回顾一下 example. HelloWorldAction,它呢,继承自 Action Support,而这个类本 身是实现了com, opensymphony. work2 Action接口的,这个类来自于 WOrk,它的定义 如下 package com opensymphony. xwork2i public interface Action t public static final java. lang String SuCCESS ="success"i public static final java.lang String NONe ="none"; public static final java. lang String ERROR =error public static final java. lang String INPUT ="input" public static final java. lang String LoGIN ="login public abstract java. lang String execute()throws java. lang Exception 这样大家就明白了 SUCCESS这个常量是哪里来的 SUCCESS NONE、 ERROR、NPUT、 LoG|N几个字符串常量定义了常用的几类返回值。而 execute方法,则是每个Acon的 入口方法,默认情况下 WOrk将调用每个 Action的 execute方法以完成业务逻辑处理。 刘长炯著
MyEclipse 6 Java 开发中文教程 13 刘长炯著 键入如下的地址来进行测试:http://localhost:8080/struts2hello/HelloWorld.action 。如果你 看到页面上出现了两行一粗一细的文字,内容为“你好!Struts 2!”,如下图所示: 图 12.3 第一个 Struts 2 程序 那么恭喜!我们的第一个应用开发成功了。 注意:接下来,我们会对 Struts 2 的内容做一些深入讨论,供大家参考。当然读者现在 也可以先直接跳过本小节余下的内容,进入下一小节,最后再回过头来看这些内容。 现在,我们来简要回顾一下执行流程:首先用户访问地址 HelloWorld.action,然后 Struts 的过滤器从 struts.xml 中解析到 name 为 HelloWorld 的 action 定义,顺藤摸瓜找到了对应 的类文件 example.HelloWorldAction,接着就执行文件中的方法 execute()来设置 message 属性为“你好!Struts 2!”,并根据其返回值”success”到 action 定义处找到 name 为 success 的 result 定义,而它的真正地址是/HelloWorld.jsp,所以接着就跳转到 JSP 页面进行显示, 同时呢大家注意到 Action 类里面的 message 属性竟然也可以被 JSP 页面所访问了,这也 是和以前的 Struts 1 很不一样的地方。再以前,我们必须自己访问 request 对象,设置属性, 之后才能被前台的 JSP 页面访问到。这个过程的简写就是: HelloWorld.action → example.HelloWorldAction.java → execute() → success → / HelloWorld.jsp →获取 message 属性 → 显示。 再来回顾一下 example.HelloWorldAction,它呢,继承自 ActionSupport,而这个类本 身是实现了 com.opensymphony.xwork2.Action 接口的,这个类来自于 XWork,它的定义 如下: package com.opensymphony.xwork2; public interface Action { public static final java.lang.String SUCCESS = "success"; public static final java.lang.String NONE = "none"; public static final java.lang.String ERROR = "error"; public static final java.lang.String INPUT = "input"; public static final java.lang.String LOGIN = "login"; public abstract java.lang.String execute() throws java.lang.Exception; } 。这样大家就明白了 SUCCESS 这个常量是哪里来的。SUCCESS、NONE、ERROR、INPUT、 LOGIN 几个字符串常量定义了常用的几类返回值。而 execute()方法, 则是每个 Action 的 入口方法,默认情况下 XWork 将调用每个 Action 的 execute()方法以完成业务逻辑处理
MyEclipse6Java开发中文教程 这样对于我们的 Action类来说,最简单的方式就是只实现 public java. lang String execute0 throws java|ang, Exception这个方法就可以了,它的返回值是一个字符串类型的路径别名 这个别名定义在配置文件的resu标记中。因此刚才的 Hello world类还有一种写法,就是 直接实现此接口。我们把它放在项目的Java类 example HelloWorld2中了,其代码清单 package example import com. opensymphony xwork2 Action; public class HelloWorld2 implements Action public string execute() throws Exception t setMessage("你好! struts2!") return SUCCESS private string messagei public void setMessage(String message) 。之后大家修改 struts. xm中的 action配置,将其cass属性修改为 example Helloworld.2, 再来测试,得到的结果仍然是一样的 接着,我们再来看看 struts xml。首先注意到的是 Action的访问地址,它的访问地址 由两个部分来决定,一个是 package中的 namespace定义,一个是 action的name。在 此呢,我们先来介绍一下 package标签的完整属性列表: 属性 4需说 name 供其它包引用的包名 extends 继承自其它包并获得其全部行为 namespace否参考下文的命名空间介绍 abstract否声明包为抽象(包内不需要配置 action 表122 package完整属性列表 虽然一般情况下用不着,我们还是稍微详细的介绍一下 Struts2中的新概念一一包:包 是一种用来对 action, result, result type,拦截器,以及拦截器栈进行组织,使它们成为一个 逻辑上的配置单元的方式。从概念上来说,它和Java中的对象很相似,因为它们均可被扩 展,可以有多个单独的部分(成员)组成,还可以被子包(子类)继承。而配置文件中的 package元素只需要一个必须的属性:name。 extends属性是可选的,它可以让当前包 继承一个或者多个以前包一包括所有的拦截器,拦截器栈,以及 action配置。注意配置文 件是按照顺序加载的,所以被" extends"引用的包必须定义在当前包之前。还有个可选的 abstract属性则创建了了一个基础包,类似于Java中的抽象类,它可以不带 action配置 那么这么多属性中,只有 namespace属性是对我们的 action的访问路径有影响的 刘长炯著
MyEclipse 6 Java 开发中文教程 14 刘长炯著 这样对于我们的 Action 类来说,最简单的方式就是只实现 public java.lang.String execute() throws java.lang.Exception 这个方法就可以了,它的返回值是一个字符串类型的路径别名, 这个别名定义在配置文件的 result 标记中。因此刚才的 HelloWorld 类还有一种写法,就是 直接实现此接口。我们把它放在项目的 Java 类 example.HelloWorld2 中了,其代码清单 如下: package example; import com.opensymphony.xwork2.Action; public class HelloWorld2 implements Action { public String execute() throws Exception { setMessage("你好!Struts 2!"); return SUCCESS; } private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } 。之后大家修改 struts.xml 中的 action 配置,将其 class 属性修改为 example.HelloWorld2, 再来测试,得到的结果仍然是一样的。 接着,我们再来看看 struts.xml。首先注意到的是 Action 的访问地址,它的访问地址 由两个部分来决定,一个是 package 中的 namespace 定义,一个是 action 的 name。在 此呢,我们先来介绍一下 package 标签的完整属性列表: 属性 必需 说明 name 是 供其它包引用的包名 extends 否 继承自其它包并获得其全部行为 namespace 否 参考下文的命名空间介绍 abstract 否 声明包为抽象 (包内不需要配置 action) 表 12.2 package 完整属性列表 虽然一般情况下用不着,我们还是稍微详细的介绍一下 Struts 2 中的新概念――包:包 是一种用来对 action, result, result type, 拦截器, 以及拦截器栈进行组织,使它们成为一个 逻辑上的配置单元的方式。从概念上来说,它和 Java 中的对象很相似,因为它们均可被扩 展,可以有多个单独的部分(成员)组成,还可以被子包(子类)继承。而配置文件中的 package 元素只需要一个必须的属性:name。extends 属性是可选的,它可以让当前包 继承一个或者多个以前包-包括所有的拦截器,拦截器栈,以及 action 配置。注意配置文 件是按照顺序加载的,所以被"extends"引用的包必须定义在当前包之前。还有个可选的 abstract 属性则创建了了一个基础包,类似于 Java 中的抽象类,它可以不带 actioin 配置。 那么这么多属性中,只有 namespace 属性是对我们的 action 的访问路径有影响的
MyEclipse6Java开发中文教程 它的出现可以让我们避免多个名字相同的 action定义出现冲突。它的默认值是”,也就是 空字符串。另外它还可以取值为根目录,也就是”尸,被称为 Root Namespace,它对应着 访问Web应用根目录的情况,对我们的例子来说就是在浏览器中访问/ struts2helo。其它的 取值,一般来说以开头,例如/ser,则相当于给当前所有的 action定义都加了一个前缀(虽 然这样并不是特别的确切),那么假设我们当前例子的配置文件的 package定义为 < package name="default"extends="struts-default"namespace="/test">, 新发布项目后,我们访问 Action的路径将会是 httplocalhost8080/struts2hello/test/helloworld.action,当然执行结果还是一样的。然而, 根据 Strus2的文档,这个命名空间并不和目录相对应,如果读者有兴趣可以深入查看其文 档(在完整包中docs目录下可以找到,也可以访问其在线文档库)的 namespace-configuration htm/一篇的详细介绍,当然对于一般的应用来说,可以不用关心 这么多。 接下来对我们的访问路径有影响的,当属 action的name属性了,假设我们的 action 的定义如此写 < action name=" a Helloworld"c1ass=" example.He11oWor1d"。这时候 Action的访 问路径将会变成:htto/ localhost8080/ struts2heo/ a helloworld action。如果您将上一段 所提到的 namespace="est"的配置也加进来的话,它的访问路径就会变成 http://localhost:8080/struts2hello/test/a.Helloworld.actIono 注意:这时候也许有人想知道让 action的name为"a/ Helloworld行不行?答案是:默 认情况下是不行的。如果你想在name中使用斜线(“("),那么必须设置一个属性:< constant name=" struts. enable slashes/nAction Names"vaue="rue",把这句话加在 struts标签的 后面即可。另外,虽然可以在名称中使用句点号(“,”,如 a. Helloworlc,以及破折号(“-”) 如:a- Helloworld,然而一般来说是不推荐这样做的,因为这会导致某些 Struts2所提供 JavaScript和主题heme)无法使用,主要是AJAX支持会出问题。推荐的做法是用驼峰命 名法,例如上面的可以命名为 aHelloworlo或者加下划线 a helloworlo 看完了 Action的定义之后,我们来简单的看看 result元素。它有两个作用:首先,它 提供一个逻辑上的名称。一个Acon可以返回类似于 success或者'emo这样的别名,而 不需要知道其它的细节。其次,每个 result元素都提供了一种结果类型( Result Type)。 大多数结果类型都是简单的转向一个JSP页面或者模版,然而很多其它的结果类型也都是 可以使用的,例如XsL,流, FreeMarker或者 Velocity,己经重定向等,简言之就是提供 种显示结果的方式(一种视图)。在这里我们就不再深入讨论这些内容了,我们只考虑最 常用的类型: Dispatcher Result,它用来整合网络资源例如JSP。由于 Struts2框架大量使 用了默认值,所以我们的 result元素的讲解将会看起来很费解。首先呢, Struts2已经在其 默认配置文件中定义了默认的结果类型,如下所示: <result-types> result-type name="dispatcher class="org. apache struts2 dispatcher. ServletDispatcherResult" default= true </result-types> ,它相当于JSP编程中的fwar。因此,虽然上文中我们使用的配置文件虽然没有指定type, 但是它会默认在各个类型中使用 dispatcher.。所以,它的完整声明方式为 <param name="location">/HelloWorld jsp</param> </result> 。而名为 success的 result它又可以进一步省略name属性简写为 刘长炯著
MyEclipse 6 Java 开发中文教程 15 刘长炯著 它的出现可以让我们避免多个名字相同的 action 定义出现冲突。它的默认值是””,也就是 空字符串。另外它还可以取值为根目录,也就是”/”,被称为 Root Namespace,它对应着 访问 Web 应用根目录的情况,对我们的例子来说就是在浏览器中访问/struts2hello。其它的 取值,一般来说以/开头,例如/user,则相当于给当前所有的 action 定义都加了一个前缀(虽 然这样并不是特别的确切),那么假设我们当前例子的配置文件的 package 定义为: <package name="default" extends="struts-default" namespace="/test" >,重 新发布项目后,我们访问 Action 的路径将会是: http://localhost:8080/struts2hello/test/HelloWorld.action,当然执行结果还是一样的。然而, 根据Strus 2 的文档,这个命名空间并不和目录相对应,如果读者有兴趣可以深入查看其文 档(在完整包中 docs 目录下可以找到,也可以访问其在线文档库)的 namespace-configuration.html 一篇的详细介绍,当然对于一般的应用来说,可以不用关心 这么多。 接下来对我们的访问路径有影响的,当属 action 的 name 属性了,假设我们的 action 的定义如此写: <action name="a.HelloWorld" class="example.HelloWorld">。这时候Action的访 问路径将会变成:http://localhost:8080/struts2hello/a.HelloWorld.action。如果您将上一段 所提到的namespace="/test"的配置也加进来的话,它的访问路径就会变成: http://localhost:8080/struts2hello/test/a.HelloWorld.action。 注意:这时候也许有人想知道让 action 的 name 为”a/HelloWorld”行不行?答案是:默 认情况下是不行的。如果你想在 name 中使用斜线(“/”),那么必须设置一个属性:<constant name="struts.enable.SlashesInActionNames" value="true"/>,把这句话加在 struts 标签的 后面即可。另外,虽然可以在名称中使用句点号(“.”),如 a.HelloWorld,以及破折号(“-”), 如:a-HelloWorld,然而一般来说是不推荐这样做的,因为这会导致某些 Struts 2 所提供的 JavaScript 和主题(theme)无法使用,主要是 AJAX 支持会出问题。推荐的做法是用驼峰命 名法,例如上面的可以命名为 aHelloWorld 或者加下划线 a_HelloWorld。 看完了 Action 的定义之后,我们来简单的看看 result 元素。它有两个作用:首先,它 提供一个逻辑上的名称。一个 Action 可以返回类似于"success"或者"error"这样的别名,而 不需要知道其它的细节。其次,每个 result 元素都提供了一种结果类型(Result Type)。 大多数结果类型都是简单的转向一个 JSP 页面或者模版,然而很多其它的结果类型也都是 可以使用的,例如 XSL,流,FreeMarker 或者 Velocity ,已经重定向等,简言之就是提供 一种显示结果的方式(一种视图)。在这里我们就不再深入讨论这些内容了,我们只考虑最 常用的类型:Dispatcher Result,它用来整合网络资源例如 JSP。由于 Struts 2 框架大量使 用了默认值,所以我们的 result 元素的讲解将会看起来很费解。首先呢,Struts 2 已经在其 默认配置文件中定义了默认的结果类型,如下所示: <result-types> <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> </result-types> ,它相当于 JSP 编程中的 foward。因此,虽然上文中我们使用的配置文件虽然没有指定 type, 但是它会默认在各个类型中使用 dispatcher。所以,它的完整声明方式为: <result name="success" type="dispatcher"> <param name="location"> /HelloWorld.jsp</param> </result> 。而名为 success 的 result 它又可以进一步省略 name 属性简写为: