这个学习笔记的是根据struts自己的doc文档写的。
环境:
strust: struts-2.1.6
tomcat:apache-tomcat-6.0.16
HelloWorld程序描述
1 . 首先要明确的是需要用到的jar包,在文档中说的是只需要下面的包,可是试了,差一个common-fileupload.jar
D:/SDK/Struts2/struts-2.1.6/lib/struts2-core-2.1.6.jar
D:/SDK/Struts2/struts-2.1.6/lib/xwork-2.1.2.jar
D:/SDK/Struts2/struts-2.1.6/lib/commons-logging-1.0.4.jar
D:/SDK/Struts2/struts-2.1.6/lib/commons-fileupload-1.2.1.jar
D:/SDK/Struts2/struts-2.1.6/lib/freemarker-2.3.13.jar
D:/SDK/Struts2/struts-2.1.6/lib/ognl-2.6.11.jar
2. 建立web应用struts2,应用目录下WEB-INF/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>My Application</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter> <filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
所有请求都会拦截,但是struts2中默认的处理.action请求。
3 . struts.xml文件位置,在classes目录下面。
<!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 name="HelloWorld" class="tutorial.HelloWorld">
<result>/HelloWorld.jsp</result>
</action>
</package>
</struts>
4 . HelloWorld.java
package tutorial;
import com.opensymphony.xwork2.ActionSupport;
public class HelloWorld extends ActionSupport {
public static final String MESSAGE = "Struts is up and running ...";
public String execute() throws Exception {
setMessage(MESSAGE);
return SUCCESS;
}
private String message;
public void setMessage(String message){
this.message = message;
}
public String getMessage() {
return message;
}
}
5 . HelloWorld.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h2><s:property value="message"/></h2>
</body>
</html>
6 . 浏览器访问http://localhost:8080/struts2/HelloWorld.action
Struts2 之初体验 | 2009年6月14日16:59:46 |
|
图片来自:struts-2.1.6/docs/docs/big-picture.html
struts2/
WEB-INF/
struts.xml
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
还在使用dtd这种正在被淘汰,但是使用最广泛的xml文件定义描述方式。文件应该在struts-core.jar文件中包含。<struts>
原来叫做struts-config这帮apache的人在想什么?
<package name="default" extends="struts-default">
包的概念
<action name="HelloWorld" class="tutorial.HelloWorld">
<result>/HelloWorld.jsp</result>
</action>
确定某个.action请求转交给某个类型的execute方法调用。子标签result确定在类的execute方法返回SUCCESS属性时要转向的页面。
<action name="Welcome">
<result>/Welcome.jsp</result>
</action>
确定Welcome.action请求直接的转发给Welcome.jsp页面上,响应客户请求。
<action name="*">
<result>/{1}.jsp</result>
</action>
利用统配付来匹配请求,所有的*.action请求,都会转交给*所统配的名字,后缀变成.jsp转发给客户端。
</package>
</struts>
表单验证
1.再类文件的同包目录下添加验证的配置文件
Logon-validation.xml
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring">
<message>Username is required</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message>Password is required</message>
</field-validator>
</field>
</validators>
2.并不希望在一开始进入页面的时候就验证内容。那么需要进行下面的修改:
将Welcome.jsp的 <li> <a href="<s:url action="Logon"/>">Sign On</a></li>
修改为<li><a href="<s:url action="Logon_input"/>">Sign On</a></li>
将struts.xml的<action name="Logon" class="tutorial.Logon">
修改为<action name="Logon_*" method="{1}" class="tutorial.Logon">工作流程
首先是从webcome页面,通过连接跳转到Logon页面,在这次跳转的过程中实际上要请求的内容是一张jsp页面,但是这里用<s:url action="Logon_input"/>那么请求的就是action对象,如果这样,action要执行的代码,从非登录页面发送的请求应该是不进行验证的,转向到登陆页面就可以,而从登陆页面进入action的请求,应该通过验证。下面就是要验证和不要验证的过程描述:
不进行验证的过程:从Welcome.jsp页面,通过连接提交请求道Logon Bean上。
1. 根据之前的例子,从 Welcome.jsp 提交来的请求, 从 ActionMapping 中发现 Login_* 。实际提交的内容是Login_input
2. 修改method属性的值{1},变成input。
3. 程序会调用Logon类型中的方法input,该方法来自于ActionSupport类。
4. 由于method属性是input,所以当请求中的servletPath带有input关键字的时候,就会绕过验证,验证框架就不在执行。如果请求中不再带有input,就会进行验证。
5. 默认的input方法(也就是ActionSupport类中的input方法)返回的结果就是字符串 ”input”
6. 框架通过”input”字符串,确定返回给客户端的响应是,不带有任何验证信息的”Logon.jsp”页面。
进行验证的过程:提交form表单的请求,从登陆页面提交到Logon Bean上。
1. 框架检查需要进行验证的目标Action类型Logon。
2. 在例子中程序在Logon类型的同包下,发现文件Logon-validation.xml,表明对Logon类型进行验证。这时框架会根据xml文件对该类型生成一个验证对象。实际上这里是对验证器对象的设置。
3. 生成的验针器会应用到引入的属性上。引入的属性,就是在.xml文件中描述的属性。
4. 如果验证失败,消息会被添加到一个内置的队列中。
5. 当所有的验证器都被调用之后,框架就会获得所有的错误消息,结果字符串的值是“input”,那么就不在调用Action类。直接的转向到input对应的Logon.jsp页面,并在页面上呈现消息。
6. 否则,默认的Action类型中的方法会被调用。这时所有的输入都已经被验证过,并且返回的结果码,是字符串”success”。
资源文件
验证消息和属性
添加资源文件绑定到验证消息和属性标签上。(属性标签指在页面上的输入文本框前显示的字符串)。
代码
框架关联消息资源到类型上。只是需要在Logon类型的同包下面,添加资源文件Logon.properties,这样资源文件就和Logon Action类型绑定到一起了。
但是,分开的资源文件分别得绑定到所有的类型上,常常不满足要求,因为有些不同类型是需要使用相同的资源描述。所有有些人们就将一个包下的所有类型,绑定到一个资源文件中。如果希望这样,我们只需要在某个包下面添加文件package.properties,那么在这个properties文件中就能描述这个包下所有类型需要绑定的资源。在例子中就是在tutorial包下添加资源文件。
tutorial/package.properties
requiredstring = ${getText(fieldName)} is required. password = Password username = User Name还需要对验证器的描述文件和Logon.jsp页面进行修改
Logon-validation.xml
<message>Username is required</message>
<message key="requiredstring"/><message>Password is required</message>
<message key="requiredstring"/>Logon.jsp
<s:textfield label="User Name" name="username"/>
<s:textfield label="%{getText('username')}" name="username"/><s:password label="Password" name="password" />
<s:password label="%{getText('password')}" name="password" />代码是怎么工作的
- <message key=”requiredstring”/> key关键字告诉框架在资源文件中查找requiredstring绑定的资源。
- 资源文件中的表达式:${getText(fieldName)} 告诉框架去查找属性名绑定的资源。(这里不解的是fieldName知道当前包下所有类型的属性名字?只有这样才能找到对应的资源)。这种表达式的方式能够让我们为验证器的requiredstring提供相同的消息。
- 另外,文本属性使用表达式 %{getText('password')} 告诉框架查找password在资源文件中对应的文本内容。
其他消息
其他的页面元素也能够使用资源文件。例如,添加“Hello World”和“Missing page”到资源文件。
代码
tutorial/package.properties
# ... HelloWorld.message = Struts is up and running ... Missing.message = This feature is under construction. Please try again in the next iteration.这样的配置会对HelloWorld action起作用,但是对于Missing action还并不能起作用,为了让配置都能够起作用,所以需要在tutorial包下给他们添加共同的父类。
就是说让HelloWorld不再直接的集成ActionSupport类型了,而是让一个其他的类型集成之后,HelloWorld在继承自这个类。那么这个基类内部实际上什么都不用实现,可以直接的配置到默认的通配所有请求的actionMapping上。TutorialSupport.java
package tutorial; import com.opensymphony.xwork2.ActionSupport; public class TutorialSupport extends ActionSupport {}修改默认的通配映射.
struts.xml
<action name="*" class="tutorial.TutorialSupport"> <result>/{1}.jsp</result> </action>现在可以去更新HelloWorld.jsp和Missing.jsp,在页面中引用资源文件中的key,查找消息
Missing.jsp
This feature is under construction. Please try again in the next iteration.
<s:text name="Missing.message"/>在HelloWorld的例子中,需要修改该的是在action类内部的message属性,修改类的内部对消息实例的使用:
HelloWorld.java
package tutorial; public class HelloWorld extends TutorialSupport { public static final String MESSAGE = "HelloWorld.message"; public String execute() throws Exception { setMessage(getText(MESSAGE)); return SUCCESS; } // ... }怎么工作:
- 在Missing.jsp页面中只用的是文本标签从资源文件中查找消息。
- 在HelloWorld中使用getText方法在action中查找消息。
- HelloWorld.jsp中显示的消息是通过Action中设置进去的,所以不需要修改页面的任何内容。
Localizing 一直在想这个词怎么翻译,叫做本地化,越写越感觉不对劲,叫做局部化可以理解但是比较牵强。
本地化:资源文件可以通过语言的设置完成国际化消息的转换,在没有提到国际化的时候将资源文件的问题描述为本地化是可以的。- 局部化:实际上想到的是局部变量,利用局部变量的方式来讲页面配置文件中需要用到的消息在一个统一的地方定义,最终只需要修改资源文件就能完成所有使用位置的修改,这样解释也有一定的道理。
- 不过这些想法都太过牵强,所有最后基本就将这个词省略了。有些地方直接的描述成了资源文件。
Flying Solo
- Download the framework - The full distribution includes sample applications, source code, and documentation.
- Subscribe to Mailing List and post a question, or browse Mail Archive. (You probably want to browse the archive or forum first.)
- Subversion Repository - Browse the source.
- Online documentation - Read it here first! The project documentation is maintained using Confluence and exported to HTML on every change.
- JIRA Issue Tracker - Browse or file enhancements requests and defect reports.