📄 第一章 webwork入门.txt
字号:
<%@ page contentType="text/html;charset=GBK" %>
<%@ taglib uri="/webwork" prefix="ww" %>
<body align="center">
成功
</body>
8. 部署测试
http://localhost:8080/aaa/login.jsp
9. 加上出错信息
1)修改LoginAction,加上
private String message;
getter/setter
public String execute() throws Exception {
if(uid.equals(pwd))
return this.SUCCESS;
message = "用户名或密码错误";
return this.INPUT;
}
2) 修改login.jsp
<ww:if test="message!=null">
<font color="red"><ww:property value="message"/></font><HR>
</ww:if>
提高篇
六、Action介绍
每个请求的动作都对应于一个相应的Action,excute()方法是Action类里最重要的部分,它执行返回String类型的值,与xwork配置文件里result标签name的值是相对应的。
字符常量的含义如下:
SUCCESS:Action正确的执行完成,返回相应的视图;
NONE:表示Action正确的执行完成,但并不返回任何视图;
ERROR:表示Action执行失败,返回到错误处理视图;
INPUT:Action的执行,需要从前端界面获取参数,INPUT就是代表这个参数输入的界面,一般在应用中,会对这些参数进行验证,如果验证没有通过,将自动返回到该视图; LOGIN:Action因为用户没有登陆的原因没有正确执行,将返回该登陆视图,要求用户进行登陆验证。
在WebWork中,一般Action类需要实现Action接口,或者直接继承基础类com.opensymphony.xwork.ActionSupport。如果用户输入的数据验证没有通过,我们需重新返回输入页面,并给出错误信息提示。拦截器栈“validationWorkflowStack”为我们实现了这个功能。它首先验证用户输入的数据,如果验证没有通过将不执行我们Action的execute()方法,而是将请求重新返回到输入页面。通过接口ValidationAware,我们可以获得类级别或字段级别的验证错误信息,这个错误信息也就是我们验证文件中标签里的数据。ActionSupport类已实现了此接口,这样在应用中我们的Action只要继承ActionSupport类就可以了。
七、FormBean
根据FormBean的不同可以分为二类,
1. 一类是Field-Driven(字段驱动的)FormBean Action将直接用自己的字段来充当FormBean的功能,我们的例子就是使用这种方式。它一般用在页面表单比较简单的情况使用,而且可以直接用域对象作为Action的字段,这样就不用在另写FormBean,减少了重复代码。
每个action有处理请求的方法,也可以封装前台的业务表单字段。当然也可可以将字段封装成对应的vo,即FormBean,如User对象,是一个普通的JavaBean,它可以包含用户注册的字段信息,并对每个字段提供相应的set和get方法。如“user.userid”将去分别调用Action类的getUser()和User类的getUserid()方法,即:getUser().getUsername(),取得的数据就是前面注册页面输入的用户名。而不封装时就调用action的getUid()和setUid().
2. 另一类是Model-Driven(模型驱动的)Action 它很像Struts的FormBean,但在WebWork中,只要普通Java对象就可以充当模型部分。Model-Driven(模型驱动的)Action要求我们的Action实现com.opensymphony.xwork. ModelDriven接口,它有一个方法:Object getModel();,我们用这个方法返回我们的模型对象就可以了。 我们可以将前面的RegisterAction.java改为Model-Driven(模型驱动的)Action:
public class RegisterActionModel implements Action,ModelDriven{
private User user = new User();
public String execute() throws Exception {
System.out.println("Start execute......");
return SUCCESS;
}
public Object getModel() { return user; }
}
这时我们输入信息的页面也有了变化:输入框里的命名发生了变化。它们都少了“user.”这部分信息。 当我们采用Model-Driven(模型驱动的)Action时,它将取得模型对象保存在值堆栈中。“name="username"”就是代表直接调用模型对象的setUsername()方法 我们Action的在配置文件中,也要给它指定一个拦截器model-driven,它的作用就是将模型对象保存到值堆栈中。
八、OGNL
我们把“user.username”这样的语句叫做表达式语言(Expression Language,简称为EL)。它由XWork框架提供,XWork表达式语言的核心是OGNL(Object Graph Notation Language),通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。
我们输入框的name用到的名字就是OGNL的表达式,比如:用户名的输入框:“
<input type="text" name="user.username">”,
在用户注册成功之后我们要显示用户注册的信息,用了“
<ww:property value="user.username"/>”。
Input输入框里的“user.username”,它解析成Java语句为:getUser().setUsername();,property标签里的“user.username”解析为Java语句:getUser.getUsername();。
九、ValueStack
OGNL将对象存放在哪里呢?--OgnlValueStack,即值堆栈。
1、ValueStack其实就是一个放置Java对象的堆栈而已,唯一特别的是可以使用EL来获得值堆栈中对象属性的数据,并可以为值堆栈的对象属性赋值。
2、 WebWork的ValueStack底层有第三方开源项目OGNL实现。所以EL也都遵循OGNL的规范。我们在开发中,几乎不需要知道OGNL的细节。
3、 WebWork为每一次请求构建一个ValueStack,并将所有相关的数据对象(例如:Action对象、Model对象等)放到ValueStack中。再将ValueStack暴露给视图页面,这样页面就可以直接访问后台处理生成的数据。
1)、 所有存取操作的目标对象都是已放入ValueStack中的对象。所以在使用之前,必须要先将对象入栈。例如我们在setup方法中的语句:valueStack.push(employee)。
2)、 每一次WebWork请求,在创建Action对象之前都会先生成一个ValueStack对象,再将Action对象入栈。这样我们就可以通过表达式语言来直接存取action对象的数据,所以在WebWork中,action具有数据模型的功能。
3)、 在对ValueStack进行存取操作时,我们的操作指令(表达式语言)并不知道它是对哪个对象进行操作。例如,我们在获取员工姓名时,我们给的操作指令是”name”,这时,并不知道ValueStack里面的对象一定就是employee。ValueStack会从上而下,遍历栈里面的对象,并试图调用当前遍历对象的getName方法,当它找到了这个方法,并执行之后,就会将执行得到的数据返回。这就是那神秘的ValueStack。
4、 关于值堆栈的context map,它是一个放置值堆栈上下文数据的对象。通过符号“#“再加上对象的名称,可以访问这些数据(只可以访问)。一些JavaServlet相关的数据都放在这个容器中。这个对webwork的标签库特别有用,这样我们可以直接通过表达式语言去访问request、attribute、session、application里的数据。例如:用property标签库打印出所有请求参数的数据,代码如下:<ww:property value="%{#request}"/>。
5、 其它。“top”是ValueStack里面的关键字,通过它可以找到ValueStack中最上面的那个对象。可以试着打印一下valueStack.findValue("top"))看看。表达式语言除了可以调用基于JavaBean规范的get和set方法之外,还可以调用一般的Java方法(这是需要使用方法的全名,并传入需要的参数),也可以直接访问Java类的静态字段和静态方法。具体的使用,可以查看WebWork的官方文档。
十、拦截器
1、 一个拦截器就是在xwork.xml文件中定义的一个无状态Java类,它至少要实现XWork的com.opensymphony.xwork.interceptor.Interceptor接口。代码如下:
public interface Interceptor extends Serializable {
void destroy();
void init();
String intercept(ActionInvocation invocation) throws Exception;
}
2、 实现Interceptor接口的拦截器,代码部分在intercept方法中实现。在intercept方法中,可以直接返回一个Result字符串,这样整个执行直接“短路”,这时Action的execute方法也不会执行(一般很少会这么用)。所以,一般都会在这个方法里调用参数对象invocation的invoke方法,并返回这个方法执行的结果。这样会持续执行后面的拦截器方法以及Action的execute方法等。
3、 大部分的时候,拦截器直接继承WebWork的抽象类com.opensymphony.xwork.interceptor.AroundInterceptor就可以了。这时,需要实现它的before和after方法。Before方法会在Action执行之前调用,after方法在Action执行之后调用。
4、 拦截器的执行顺序。我们可将多个拦截器放一起组装成一个拦截器栈。这样拦截器会按照栈的顺序由上而下执行before方法,所有before方法执行结束,再执行Action的方法,执行Result的方法,再返回执行结果,最后再从下而上执行拦截器的after方法。
5、 拦截器的过滤功能。我们通常会在应用中使用一个通用的定义多个拦截器的拦截器栈。但有些Action方法在调用的时候,不需要要其中的部分拦截器。这时,我们就可以使用拦截器过滤功能。如果拦截器要拥有过滤功能,必须实现抽象类com.opensymphony.xwork.interceptor.MethodFilterInterceptor。这样,拦截器在定义的时候或者在Action引用拦截器栈的时候,我们就可以指定哪些Action方法是需要过滤的,哪些Action是不需要过滤的。
WebWork提供的拦截器介绍
1、 自动为Action设置Http请求数据的拦截器(Parameters Interceptor)。这个拦截器非常方便实用,但完全自动组装对象数据,很可能会带来安全问题。如果Action不需要设置数据,那么这个Action只要实现com.opensymphony.xwork.interceptor.NoParameters接口即可。如果是Action中部分数据需要自动设置,部分数据不允许设置,这样可以实现接口com.opensymphony.xwork.interceptor.ParameterNameAware,可以在这个接口的acceptableParameterName(String parameterName)方法中,定义我们可以接受哪些方法,如果允许只要让这个方法返回True就可以了。
2、 过虑参数功能的拦截器(Parameter Filter Interceptor)。它可以全局阻止非法或不允许Action访问的参数。可以很好的和上面的组装参数的拦截器一起使用。
3、 为Action设置静态数据的拦截器(Static Parameters Interceptor)。它可以将Action定义的静态<param/>参数,设置到Action中。
4、 数据验证拦截器(Validation Interceptor)。定义之后,会调用验证文件或实现验证接口com.opensymphony.xwork.Validateable的所有验证。
5、 验证流程处理拦截器(Workflow Interceptor)。它和上面的拦截器一起使用,处理验证的流程。如果验证通过则继续前进,如果发现有验证错误消息,直接转到Action中定义的输入结果(input)页面。
6、 类型转换错误处理拦截器()。它首先去取得类型转换的错误消息(主要是由设置Http请求参数的拦截器产生),如果取到错误消息,它会将错误消息传递给实现接口com.opensymphony.xwork.ValidationAware的Action,这样我们可以将这些错误消息暴露到页面中。
7、 Action链拦截器(Chaining Interceptor)。它是用来拷贝前一个Action的属性数据到当前Action中。它要求前一个Action必须是chain Result(<result type="chain">),这样才能进行Action的数据拷贝。
8、 防止页面重复提交(或页面重复刷新)拦截器。Token Interceptor和Token Session Interceptor都是防止重复提交的拦截器。不同点是后者在Session存贮了最近一次请求的结果数据。
9、 文件上传的拦截器(File Upload Interceptor)。实现文件上传的功能。如果有人曾经手工写过文件上传程序,那一定会惊叹于这个拦截器。我们可以在这个拦截器中设定上传文件的大小和类型限制。记得需要第三方的文件上传库的支持,只要在webwork.properties中配置过,并拷贝相应的jar包就可以了。
10、 进度条等待拦截器(Execute and Wait Interceptor)。当Action的执行需要很长实际的时候,我们可以使用这个进度条等待的拦截器。它会将Action放到后台执行,而在前端显示进度条或等待消息提示的页面。
11、 还有一些其它不常用的拦截器,我们可以在WebWork文档中找到,这里就不再做介绍。
十一、多视图支持
1、velocity模板
1) 改xwork.xml
<result name="input" type="velocity">/login.vm</result>
2) freemarker文件
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk">
</head>
<body>
#wwform ("action=login" "method=post")
#wwlabel ("value=vm用户ID")#wwtextfield ("name=uid")<BR>
#wwlabel ("value=vm密 码")#wwtextfield ("name=pwd")<BR>
#wwlabel ("value=vm确认密码")#wwtextfield ("name=pwd2")<BR>
#wwsubmit() #wwreset()<BR>
#end
</body>
</html>
2、freemarker模板
1). 改xwork.xml
<result name="input" type="freemarker">/login.ftl</result>
2).velocity文件
<#ftl attributes={"content_type":"text/html; charset=GBK"}>
<html>
<body>
<@ww.fielderror/>
<@ww.form action="login.action" method="POST">
<@ww.label value="ftl用户ID" /><@ww.textfield name="uid"/><BR>
<@ww.label value="ftl密 码" /><@ww.textfield name="pwd"/><BR>
<@ww.label value="ftl确认密码" /><@ww.textfield name="pwd2"/><BR>
<@ww.submit value="保存"/><@ww.reset value="重置" /><BR>
</@ww.form>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -