Chinaunix首页 | 论坛 | 博客
  • 博客访问: 94223
  • 博文数量: 59
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 385
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-29 15:12
文章分类

全部博文(59)

文章存档

2011年(1)

2009年(58)

我的朋友

分类: 系统运维

2009-05-30 12:28:38

WebWork介绍

  WebWork是由OpenSymphony组织开发的,致力于组件化和代码重用的拉出式MVC模式J2EE Web框架。WebWork目前最新版本是2.1,现在的WebWork2.x前身是Rickard Oberg开发的WebWork,但现在WebWork已经被拆分成了Xwork1和WebWork2两个项目,如下示意图所示:
 

  Xwork简洁、灵活功能强大,它是一个标准的Command模式实现,并且完全从web层脱离出来。Xwork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式语言(OGNL – the Object Graph Notation Language),IoC(Inversion of Control倒置控制)容器等。

  WebWork2建立在Xwork之上,处理HTTP的响应和请求。WebWork2使用ServletDispatcher将HTTP请求的变成Action(业务层Action类), session(会话)application(应用程序)范围的映射,request请求参数映射。WebWork2支持多视图表示,视图部分可以使用JSP, Velocity, FreeMarker, JasperReports,XML等。

  下面我们提到的WebWork将为WebWork2,使用的版本是2.1。

 
WebWork安装-HelloWorld

WebWork安装

  当然,在具体开发使用介绍之前,搭建好运行环境是必备的。

  首先从https://webwork.dev.java.net/servlets/ProjectDocumentList下载最新的WebWork压缩包,并将其解压开来。打开解压目录,你将看到以下的文件和目录:

  webwork-2.x.jar 当然就是WebWrok最新发布的Jar包

  webwork-example.war 是WebWrok自带的很有代表性的功能演示例子,掌握它是提高你的WebWork技术水平的捷径

  webwork-migration.jar 提供快速将1.x版本移植到2.x版本所用的类文件

  docs目录 WebWrok的使用文档,包括api文档、clover文档、单元测试(Junit)文档等

  lib目录 WebWork在运行或编译时所用到的所有.jar包

  src目录 源程序目录

  2、WebWork是J2EE Web框架,当然要运行在Web容器中,我用的是稳定的Tomcat 4.1,关于tomcat的安装和部署请自己搞定。

  3、用WebWork当然要将它的运行时用到的Jar包放到Web容器可以找到的ClassPath中,将步骤1介绍的webwork-2.x.jar放到你部署目录下WEB-INF\lib目录里,同时将WebWrok解压目录lib\core下的所有.jar文件也拷贝到WEB-INF\lib目录,这些是运行WebWork必需要用到的jar包。

  4、了解Web框架的朋友都知道,一般Web框架都是通过一个JavaServlet控制器提供统一的请求入口,解析请求的url,再去调用相应的Action进行业务处理。WebWork也不例外,它要求你在web.xml文件里配置一个派遣器ServletDispatcher,它初始化WebWrok的一些配置信息,解析XWork的Action配置信息,根据请求去组装和调用执行相应的拦截器(Interceptor)、Action、Action Result(Action执行结果的输出)等,具体配置如下:

代码
……

webwork
com.opensymphony.webwork.dispatcher.ServletDispatcher

……

webwork
*.action

……


  这样,.action结尾的所有url请求将直接有ServletDispatcher去调度。下面我们写一个经典的HelloWorld,跑一个简单实例来验证你运行环境是否可用,并感受一下简单、功能强大的WebWork的开发。

  注意:如果使用WebWork自带的标签库,除了配置相应的标签库以外,还须将com.opensymphony.webwork.views.velocity.WebWorkVelocityServlet配置到web.xml,具体可以参考webwork-example里面的配置。
HelloWorld

  首先看下面这个程序HelloWorldAction.java:

代码
package helloWorld

import com.opensymphony.xwork.Action;

public class HelloWorldAction implements Action{

String greeting;

public String getGreeting() {
return greeting;
}

public String execute() throws Exception {
greeting = "Hello World!";
return SUCCESS;
}

}


  HelloWorldAction是一个普通的Java类,它实现了Action这个接口。Action是一个非常简单的接口,只有一个方法:public String execute() throws Exception; ,Action类介绍见下一节。HelloWorldAction有一个String类型字段greeting,在execute()方法中,greeting被赋值“Hello World!”,并返回String型常量SUCCESS,SUCCESS的定义详见Action接口,这个常量代表了execute()方法执行成功,将返回成功页面。

  返回的页面greetings.jsp代码如下:

代码
<%@ taglib prefix="ww" uri="webwork" %>


First WebWork Example






  greetings.jsp很简单的jsp页面,它使用了WebWork自带的标签库。它的作用是输出变量“greeting”的值。这个语句,相当于调用相应Action(HelloWorldAction)的getGreeting()方法,取得变量“greeting”的值。

  我们的HelloWorld代码就这么多,完了。可是,HelloWorldAction怎么去调用、执行?执行成功它又怎么知道返回到greetings.jsp?XWork的配置文件xwork.xml会负责将要执行的Action和展现的视图连接起来,见xwork.xml的如下片断:

代码


/greetings.jsp



  我们先看action标签:name=”hello”,表示我们调用这个Action的标识是hello,这样我们可以通过下面的url访问这个Action:…/hello.action,
例如:;class=" helloWorld .HelloWorldAction"很好理解,这是真正调用执行的类。我们在看看result标签:name="success",记得前面HelloWorldAction返回的字符常量SUCCESS吗?它的值其实就是“success”,它表示Action执行成功返回success就转向这个结果;type="dispatcher"表示执行完Action,转向结果页面的方式;param参数指定了结果页面的位置:/greetings.jsp。

  代码写完,剩下的当然是编译、部署。启动tomcat服务器之后我们就可以执行了:

  在浏览器里输入你的地址:

  你将会看到结果

Action(动作)

Action介绍

  Action在MVC模式中担任控制部分的角色,在WebWork中使用的最多。每个请求的动作都对应于一个相应的Action,一个Action是一个独立的工作单元和控制命令,它必需要实现XWork里的Action接口,实现Action接口的execute()方法。Action接口的代码如下:

代码
package com.opensymphony.xwork;

import java.io.Serializable;

public interface Action extends Serializable {

public static final String SUCCESS = "success";
public static final String NONE = "none";
public static final String ERROR = "error";
public static final String INPUT = "input";
public static final String LOGIN = "login";

public String execute() throws Exception;
}



  excute()方法是Action类里最重要的部分,它执行返回String类型的值,在Action中返回的值一般使用它上面定义的标准静态字符常量。例如:前面的HelloWorldAction返回的就是SUCCESS字符常量,真正的值当然就是“success”,它与xwork配置文件里result标签name的值是相对应的。它用来决定execute()方法执行完成之后,调用哪一种返回结果。字符常量的含义如下:

  SUCCESS:Action正确的执行完成,返回相应的视图;

  NONE:表示Action正确的执行完成,但并不返回任何视图;

  ERROR:表示Action执行失败,返回到错误处理视图;

  INPUT:Action的执行,需要从前端界面获取参数,INPUT就是代表这个参数输入的界面,一般在应用中,会对这些参数进行验证,如果验证没有通过,将自动返回到该视图;

  LOGIN:Action因为用户没有登陆的原因没有正确执行,将返回该登陆视图,要求用户进行登陆验证。


用户注册例子

  下面我们将以一个用户注册的例子详细介绍Action的原理:

  功能描述:一个用户注册页面register.jsp,用户可以在这个页面里输入用户注册的基本信息(例如:姓名、密码、Email等),输入完成提交表单,执行用户注册的Action,执行成功返回成功提示的页面(register-result.jsp)并将注册的信息输出。

  模型:User.java

  控制:RegisterAction.java

  视图:register.jsp、register-result.jsp

  配置:xwork.xml

  User.java:

代码
package register;

public class User {
  
private String username;
private String password;
private String email;
private int age;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

……

public int getAge() {
return age;
}

public int setAge(int age) {
this.age = age;
}

public String toString() {
return "username=" + username
     + ";password=" + password
     + ";email=" + email
     + ";age=" + age;
}
}



  模型User是一个普通的JavaBean,它包含了用户注册的字段信息,并对每个字段提供相应的set和get方法。下面我们来看看进行用户注册动作的RegisterAction.java:

代码
package example.register;

import com.opensymphony.xwork.Action;

/**
* @author moxie-qac
*            achqian@yahoo.com.cn
*/
public class RegisterAction implements Action {

private User user= new User();

public User getUser() {
return this.user;
}

public String execute() {

System.out.println("Start execute 。。。。。。。。。。。。。");
System.out.println("User="+user);
//在这里调用用户注册的业务逻辑,比如:将注册信息存储到数据库

return SUCCESS;
}
}



  这个Action是不是特清爽?用户注册就这么几行代码搞定,当然,我们提倡在Action里最好不要实现业务代码,Action的主要功能是提供从请求中取得参数的值,转化成相应的模型,再将模型传递给执行业务操作的对象,比如:将注册的用户信息存储到数据库中,由业务对象执行业务操作,再返回执行的结果。为了简化我们省去了注册的业务逻辑执行步骤。

  再看看我们注册信息输入的页面:register.jsp

代码

Register Example





Username:

Password:

Email:

Age:








  register.jsp页面其实只是一个普通的HTML页面,它提供了一个表单,用来接受用户输入的注册信息,它唯一特殊的部分就是input输入框定义的name部分,例如:用户姓名用的是“user. username”。这种命名方式代表什么含义?它是必需的吗?后面我们将会给出答案。

  RegisterAction正确执行完成之后,会将执行的结果返回到register-result.jsp页面,由它来显示用户在前面页面输入的注册信息。register-result.jsp代码如下:

代码
<%@ taglib prefix="ww" uri="webwork" %>

Register result



    


     Congratulation,your register success!


     Username:

     Password:

     Email:

     Age:

    





  这个Jsp页面使用了WebWork的标签库 ,记得HelloWorld里的greetings.jsp吗?它也使用了这个标签库。我们看这个:

  它是一个普通的使用标签库语句,查看这个标签库的源程序,见包com.opensymphony.webwork.views.jsp里的PropertyTag.java文件,你会发现这个类会根据value后面赋予的表达式值,去OgnlValueStack里查找这个表达式值所对应的操作。执行这个语句OgnlValueStack会根据value的值(一个表达式)“user.username”去分别调用RegisterAction类的getUser()和User类的getUsername()方法,即:getUser().getUsername(),取得的数据就是前面注册页面输入的用户名。

  我们把“user.username”这样的语句叫做表达式语言(Expression Language,简称为EL)。它由XWork框架提供,XWork表达式语言的核心是OGNL(Object Graph Notation Language),OGNL是一种功能强大,技术成熟,应用广泛的表达式语言,将在下面的章节有详细介绍。

  我们在回到前面介绍的register.jsp,Input输入框

里用的“user.username”,现在我们可以明白,它不是随意设置的,它是一个表达式语言,有着特殊的功能。看到这里,不知道你心中是否有一个疑问:我们的RegisterAction是如何取得用户注册页面输入的数据呢?如果你做过Web开发,你一定会想到RegisterAction里必需有一些从客户端请求中获取参数的语句,例如: 类似:String username = request.getParameter(“user. username”)的语句(request是HttpServletRequest的对象),去从request请求里面获取用户输入的参数值。可是我们这个Action里面只有User对象简单的get方法,并没有其它的代码。Xwork框架的Action是如何去实现了与Web无关?request请求的参数是怎么传递到我们Action的模型User中呢?

  在回答答案之前,我们先看一看Xwork的配置文件xwork.xml:
  

代码


/register-result.jsp




  看了前面的介绍,这段配置文件应该不难理解。用户通过注册页面register.jsp输入自己的注册信息,提交表单到动作register.action,它将有ServletDispatcher调度,从配置文件xwork.xml里查找与“register”匹配的Action名字,即上面配置的Action。通过这个名字XWork框架找到这个Action的类:example.register.RegisterAction,XWork框架会负责去创建这个Action类的对象并调用execute()方法进行用户注册操作。正确执行execute()方法返回String类型数据“success”之后,它会请求再派遣到register-result.jsp页面。

  在这段配置文件里,你一定注意到了它特殊的一句:,interceptor-ref标签设置这个Action用到的拦截器(Interceptor),“params”引用的是配置文件中的,这个拦截器将在RegisterAction的execute()方法执行之前调用,作用是将request请求的参数值通过表达式语言设置到相应RegisterAction的模型里。例如:register.jsp里的,它输入的值会由RegisterAction类的getUser()和User类的setUserName(“…”)设置到这个User模型里。假设你在注册页面输入用户名“moxie”,提交表单ParametersInterceptor就会下面的操作:首先从请求中取得参数的名字和名字对应的值,分别为:“user.username”和“moxie”,根据这个名字,从OgnlValueStack中取得堆栈最上面的getUser().setUsername(“moxie”)操作,即取得RegisterAction对象的User模型,并设置username属性的值为“moxie”。

  原来,我们的Action是通过XWork的拦截器ParametersInterceptor从提交的表单中取得请求的参数和值,再通过OgnlValueStack来执行表达式,调用Action和模型里相应的ge或set方法,将从请求中取得的值设置到模型中去。register.jsp中Input输入框的name="user.username"是必需要遵守OGNL的命名规则。也正是很多拦截器的使用,使得我们的Action类和Web实现了完全的解耦,让我们的Action能如此的简单、优雅,拦截器的原理后面章节我们也将会有详细的介绍。

  罗索了这么多,你一定是精通了这个用户注册的例子了吧!呵呵!
 
 
==================================================================================
WebWork实例 
  •   web.xml文件



  
        webwork
        com.opensymphony.webwork.dispatcher.ServletDispatcher
   

  
        webwork
        *.action
   

   
        webwork
        /WEB-INF/lib/webwork-2.1.7.jar
   

  • xwork.xml文件

   

   

       
      
           
            hello.jsp
           

           
           index.jsp
           

     

   

  • webwork.properties文件

webwork.tag.altSyntax = true

  • Action文件       HelloWorld.java

package hbu.cmc.webwork.action;

import com.opensymphony.xwork.ActionSupport;

public class HelloWorld extends ActionSupport {
 private String name = null;
 private String message= null;
 public String execute() throws Exception {
  
  
  if(name==null||"".equals(name))
  {
   addFieldError("name","name is null!");
   return INPUT;
   
  }
  message = "hello,"+name;
  
  return SUCCESS;
 }
     public String getMessage()
     {
      return message;
     }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public void setMessage(String message) {
  this.message = message;
 }
 
}

  • jsp文件

index.jsp

<%@ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding="GB18030"%>
<%@ taglib prefix="ww" uri="webwork" %>




Insert title here









 

hello.jsp

<%@ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding="GB18030"%>
<%@ taglib prefix="ww" uri="webwork" %>




Insert title here



//输出message的内容


 

发现webwork要比stucts好用一些,第一webwork 进一步隐去了一些细节。比如没有structs的formbean了,这一点很好。

webwork也就三部分组成,第一部分当然就是JSP,JSP标签。第二部分便是webwork的servlet他是接收客户端的请求,并他解析出相应的action名,通过xwork转发到处理求的后台处理程序上。

然后就是后台处理后通过返回字段来判断要跳转的页面。

整个流程大致如此。

阅读(1282) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~