Profil de javax咖啡生活PhotosBlogListes Outils Aide

Blog


21 juin

软件设计编程得基本技术

1.设计父类时考虑不周到,等到设计或者编写子类的时候,才发现父类需要修改、增加功能等等,都很平常

2.尽量避免多次写同样的代码

3. 持续改进

4.评价软件设计的高低的几个基本原则

内容

1.软件设计/编程中,有一门基本技术叫“面向对象编程”。面向对象编程的基本思路是对象封装和继承。继承的基本思路是,所有子类共同的部分,提取、抽象后,放到父类中。

这是一个说起来容易,做起来难的事情。父类总是先设计,先实现。一个父类一般都有多个子类。没有人能够先知先觉。设计父类时考虑不周到,等到设计或者编写子类的时候,才发现父类需要修改、增加功能等等,都很平常。例如
public class RequestInfo{
    public DataItem getDI(String name){
    }
}

public class DataItem{
    public String getValue() {
    }
}

当我们经常写
String cycCode = info.getDI("cycCode") == null ? null : info.getDI("cycCode").getValue();

的时候,我们自然会想,如果在 class RequestInfo 中增加一个函数 getDIValue() 就可以写更短的代码了:
String cycCode = info.getDIValue("cycCode");
这样做的好处,代码更简洁,更易懂,也更容易维护。
同样的道理,当我们经常需要从 info 中取 int value 的时候,我们自然会知道,应该往 class RequestInfo 中增加 getIntValue().

2.在软件开发的过程中,最基本的原则是,避免多次写同样的代码。举例来说:

这是很常见的基类设计时考虑不周导致的问题,每个子类有同样的代码,。解决方法也很简单,将共同的部分放在 base class 中就可以了:

 

3.软件行业和其他行业一样,要想做出质量好的产品,关键在于“持续改进”。持续改进的意思是,如果发现了不好的设计,就应该修改。然而,很多时候事情并不这样简单。
例如,一个公司有两百个同样的生产线,现在有人发现了一个改进办法,可以提高效率。我们都知道,不可能把所有的生产线同时进行改造,那样对于现有的生产造成很大的影响,并且从人力物力方面,也有很大问题。更好的办法是,对于新的生产线,采用新的改进办法。原有的生产线,既然还能工作,就不用立即修改,可以在以后逐步改进。
这个例子换成软件行业的话:
一个公司有两百个类似功能的软件模块/类(比如 xxxBPI),现在有人发现了一个改进办法,可以在子类中写更少的代码,提高效率,代码更易于维护。我们都知道,不可能把所有 xxxBPI同时进行改造,那样对于现有的开发造成很大的影响,并且从人力物力方面,也有很大问题。更好的办法是,对于新的xxxBPI,采用新的改进办法。原有的代码,既然还能工作,就不用立即修改,可以在以后逐步改进。

因此,大型的软件中,新老方法并用的情况很多。比如, MS SQL Server, 很多原有的代码是从 Sybase 购买,MS 的技术专家发现了一些提高性能的办法,在经过多年,多个版本更新后,才逐步完成了改进老的代码。在开源的项目上面,也有很多项目版本说明中申明,计划采用某某技术改写原有的代码,目前完成哪些模块,计划增加哪些模块。改进和增加新功能永远是同时进行的。

上面的例子,采用持续改进的方法后,变成下面的样子:

4.评价软件设计的高低的几个基本原则

评价软件设计的高低的几个基本原则依次为:易懂,易用,稳定性,功能。
易懂:VB 的用户之所以比 VC 多,在于它易懂。用 Word 写设计文档的人比用 Rose 的人多,也在于懂 Word 的人更多。易懂意味着可以用更短的时间学会。
易用:如果 class A 和 class B 完成同样的功能,但使用 class A 需要写的代码更少,我们就说 class A 设计得比 class B 更好。因为使用 class A 写代码,代码更短,开发效率更高。代码短对于以后的维护也更容易。
稳定性,功能:软件的卖点在于稳定性,功能。之所以这两项排在前面亮项后面,同样有事实为证:Unix/Linux 的稳定性、功能超过于 Windows,但是它的用户反而少,原因就在于它输在 “易懂,易用”这两项上面。



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=98170

[点击此处收藏本文]   jacklondon发表于 2004年09月08日 13:37:00
 
chon 发表于2004-09-19 08:20:00  IP: 218.86.50.*
class A 需要写的代码更少,我们就说 class A 设计得比 class B 更好

这个说法是错的,很多高效的算法的代码都会比一般的方法代码要少,担是它很容易带来一个难以维护的问题.
还有一些教学上的方法,如i+++i+++++i什么的运算式,它也是很短的,但是它就有一个难以理解的坏味道,我就会把它分成多个式子,容易看懂.

所以,代码少,就会容易出现难以理解的坏味道.

 
Jacklondon Chen 发表于2004-09-19 21:40:00  IP: 61.149.102.*
在同样容易理解的情况下面,使用MS XML lib 写程序比使用 IBM XML lib 的代码少,因此我们认为MS XML lib 设计得更好。
一般来说,组件完成功能是第一步,接口简化是第二步,更高级的一步。

Jakarta Project 的 Commons tools各个子项目

Apache 的 Jakarta Project  里面有很多子项目。其中的 Commons 着眼于提供各种很通用的函数/类,这

样大家可以在平时自己的项目中用。这些 tools 因为非常 common, 以至于无论你用哪种 framework ,你

可以用到其中的一部分,来节省自己的编码量,并且其代码质量也是非常不错的。

Commons tools 一部分出发点在于解决 JDK 中的各种不足:

1. Exception 不好用,不得不写很多 try catch, 而改成使用 C/C++ 常用的以返回值判断,可以少写很多代

码。这方面以 jdbc interface 最为臭名昭著。

2. 弥补 JDK 类库的不完善地方。比如 String , Collection Framework, 正则表达式等等。

打算写文章介绍其中几个我认为比较通用的东西:

Codec 包含 Hex, Base64, URL 的编码和反解码。对于 web 应用很有用处。

Commons-Collections 增强 jdk 的 Collection Framework 功能。

Commons-Configuration 读写配置参数。大多数程序都有运行参数放在某个地方,这个工具可以读写各种参数格式:数据库,xml ,Properties 文件,系统变量,等等。强吧?

Commons-DBCP 数据库连接池,呵呵,现在连接池很多服务器都自带。但也有很多直接用这个。如果写 java application 要用到数据库,用这个吧。

DbUtils 可以减少写 JDBC 程序的 try catch, 减少代码量。一个我想写一直没有时间写的东西。但没有想象中那么好。

Email 发电子邮件。JDK 标准库对于发电子邮件支持不强,很让人看不懂。

FileUpload 文件上传。J2EE 标准库对于文件上传支持不强,也让人看不懂。这两个功能对于现在的 j2ee 应用来说,是基本功能了。稍微大一点的系统都会有。

IO 虽然 jdk 号称 IO 重写了,并且还用了 nio(new IO) 的 package 名,但是还是不够好。这个可以看作是增强版了。

Commons-Lang 好东西。 lang 包是 java 最基本的包,默认自动 import , 功能还是不够强,补补!这个包在其他系统,包括 weblogic, websphere 中都大量用它。基本上凡是有点名气的 java 系统都会用它。

Commons-Logging 好东西。大多数 EJB server 和 tomcat 都用到它。开源的 java project 也大部分用它。log 的抽象层。Java 中的 log 以前有很多种,如果你选了一种开发程序,以后想换另一种,比较麻烦。通过这个工具抽象一把,就很容易换了。不过最近 log4j 一支独大,JDK 自带的 log 没有几个人用,似乎不会有人换其他的 log, 让人搞不懂。

Math 呵呵。Java 中的 Math 包只能勉强够用,如果稍微偏们一点的数学函数,都要自己写了。用它吧,节省时间。

Net 增强 Java 网络功能。Java 的网络类库比起专业一点的 C++ 网络类库,差别还是很大。这里还是增强一点为好。

Commons-Pool 普通的对象池。不是 EJB 的对象池。池这个东西,很难写好。弄不好特耗内存,速度反而慢(比如 EJB)。无论如何,是个好的思路,可以借鉴。

Validator 这是好东西。不管是写 web 应用程序还是普通 java 应用程序,只要有用户输入界面,都用得上。比自己写省事阿。不赞成写在 xml 中,多一个字母少一个字母很难查。

Commons project 下面还有 Sandbox,包含Cache ,Clazz ,Compress, Convert ,I18n,Id ,Mapper, SQL ,ThreadPool 等等,很多都用得上。哎,好东西真多,怎么介绍得完呢?

慢慢来,一个一篇文章,慢慢来。希望大家支持。

Apache Jakarta Common Configuration, 系统配置, 工具包

在很多系统中,需要用到配置文件来存放配置参数。配置参数从代码中单独提出来主要是为了方便修改用的。常见的一个用法是将数据库连接参数(数据库服务器 IP,用户名,密码等等)写在一个配置文件中,这主要是系统可能会更换数据库,或者网络可能更换 IP 地址范围,或者服务器 IP 可能会变动等等。
  
  配置参数不仅限于配置文件,也可以保存在其他地方,比如数据库单独用一个表保存配置参数,或者在内存中,或者在操作系统环境变量中,等等。有个现成的读写配置数据工具包,让人感觉很不错。
  
  早期的配置文件主要用 ini 文件,或者类似 ini 文件格式。这种配置文件格式简单,相应的读写工具类也很容易写,各种开发语言基本上都能在网上找到现成的代码。其主要特点是 key <--> value 对应。ini 文件是纯文本文件,对于不是程序员的最终用户,修改 ini 配置文件也没有太多的难度。相比较而言,其他格式的配置都比 ini 有更大的难度。

  可惜的是 Common Configuration 工具包不支持 ini 格式。文档中说它支持的配置参数来源有:
  * Properties files
  * XML documents
  * Property list files (.plist)
  * JNDI
  * JDBC Datasource
  * System properties
  * Applet parameters
  * Servlet parameters

  数据形式也不限于 key <--> value 形式,Common Configuration 工具包也支持树形结构的参数配置。

  Common Configuration 工具包体系比较简单。一个基本的 Configuration interface 定义了各种配置通用的操作,一个 AbstractConfiguration 从 Configuration interface 下来将所有公用的操作实现了,留下一个不通用的函数 getProperty, setProperty 等待子类实现。真正有实际操作的 DatabaseConfiguration、PropertiesConfiguration、XMLConfiguration、XMLPropertiesConfiguration、MapConfiguration 等等,都是从 AbstractConfiguration 继承。MapConfiguration 是基于内存操作的配置参数读写工具类,XMLPropertiesConfiguration 则是基于 XML 文件的模仿 java properties 格式的配置文件读写工具类。有点怪吧?主要是因为 java property 文件本来设计只是为了存放多语言字符串用的,有的 java 程序员希望在 java 中有类似 INI 文件的配置文件,但是 JDK 中没有现成的工具类,只能用 property 文件凑合着用。举例来说, log4j 就可以用 property 格式的配置文件。但是这种格式的配置文件有个很大的弱点,如果里面包含非 ASCII 字符,比如说是中文,必须要写成 UNICODE 编码格式。如果软件交付给用户,用户需要改一个参数,用户没有办法改这种 property 文件。XMLPropertiesConfiguration 使用的是 XML 格式配置文件,一般用 UTF-8 编码,这种文件可以用常用操作系统自带的软件来修改(比如 windows 的记事本程序),因而更加方便。XML property 格式配置文件现在已经用得比较多了,在 J2SE 5.0 中也定义了一种 XML property 格式,这里的 XMLPropertiesConfiguration 工具类就是遵循这种格式标准。

  Configuration interface 定义了一些基本操作:addProperty, clear, clearProperty, containsKey, getBigDecimal, getBigInteger, getBoolean, getByte,getDouble,getFloat,getInt, getKeys, getList, getLong, getProperties, getProperty, getShort, getString, getStringArray, isEmpty, setProperty 等等。看起来还是比较齐全。也可以用 DataConfiguration 将已有的 Configuration 重新包装一下,然后可以读写其它类型的配置参数:URL, Locale, Date, Calendar, Color, 以及各种形式对象的  lists 和 arrays。DataConfiguration 主要做的事情是在读写配置数据的时候将这些额外的类型数据与 String 类型相互转换,最终所有配置参数还是保存成 String 形式。

  这里面还有另外一个类 CompositeConfiguration, 可以将几个 Configuration 并在一起用,这不太常见,偶尔会用到。举例来说,将数据库连接参数放在文件型配置文件中,将系统其他参数放在数据库中是一个比较常见的设计。如果几个程序员同时调试程序,可能需要将数据库中同一个配置参数设置成不同的值,这个时候就比较麻烦,要吵架了。这个时候可以将文件型配置和数据库配置做成一个组合配置CompositeConfiguration, 优先读取文件型配置中参数,如果文件型配置参数中没有才读取数据库中参数。这样就可以解决了。真正最后系统交付的时候把所有配置放在数据库中,只留下数据库连接配置放在文件型配置中。

  值得注意的是,有的 Configuration 性能不够优化,可能需要自己写一个相应的子类将 getProperty, setProperty 等函数重新写一下。现成的思路是,DatabaseConfiguration 每次 getProperty 都读取一次数据库,如果不是在集群环境,可以把所有配置数据一次读出放在一个 map 中,这样每次 getProperty 速度快很多。

  无论如何,Common Configuration 是一个非常优秀的 java 工具包。我注意到,在它的开发 roadmap 中,INI 格式配置计划在 1.3 版本中支持,应该说 INI 格式不难,不知道为什么要放到 1.3 版本中才能实现。1.3 版本还计划支持 windows 注册表格式的配置,个人觉得没有什么大的用处。其他有些稀奇古怪的计划,可能是有的开发人员提出的不太通用的一些要求。从目前的开发版本的 bugzilla 上面看,没有较核心的 bug ,比较让人放心,值得推荐。

Apache Jakarta Common Lang 介绍

无论你在开发哪中 Java 应用程序,都免不了要写很多工具类/工具函数。你可知道,有很多现成的工具类可用,并且代码质量都很不错,不用你写,不用你调试,只要你发现。
  在 Apache Jakarta Common 中, Lang 这个 Java 工具包是所有 Apache Jakarta Common 项目中被使用最广泛的,几乎你所知道的名气比较大的软件里面都有用到它,包括 Tomcat, Weblogic, Websphere, Eclipse 等等。我们就从这个包开始介绍整个 common 项目。
  Lang 中最大的也是最常用的类是 StringUtils, StringUtils 最常用的函数是 isEmpty。这里举一个例子让你熟悉一下:

  String str = null;

  if(StringUtils.isEmpty(str)){

  }

  str = StringUtils.lowerCase(str);
  str = StringUtils.capitalize(str);
  str = StringUtils.swapCase(str);
  StringUtils.isNumeric(str);
  StringUtils.isAsciiPrintable(str);
  StringUtils.equalsIgnoreCase(str,"");

  其中,
  if(StringUtils.isEmpty(str)){

  }
  相当于
  if(str == null || str.length() == 0){

  }


  从以上代码可以看出这个工具类的特点:
  第一、这些函数都是静态函数,并且很少抛出异常,也很少抛出空指针异常。
  第二、这些函数的功能大多是增强标准 Java 中 java.lang.String 类的功能。

  其实,整个 lang 包的函数基本上都在增强 java.lang 包的功能。一个有趣的设计是,虽然 StringUtils 里面的函数都是静态函数,按照通常的做法,会把构造函数设计成 private, 但是不!StringUtils 的构造函数是 public 的。构造函数里面的注释写着 "no init"。这就有意思了,你可以 new 一个 StringUtils,虽然没有特别的好处,但是也没有特别的坏处;你可以写一个 StringUtils 的子类,虽然这也不太常见。这里面的思想似乎是,使用这个工具包的软件开发人员想怎么用就怎么用,做工具类的时候不用太多限制。
  至于不抛异常是因为现在很多人已经意识到 Java 中的异常不是什么好东西,如果不用异常也能写程序,为什么还要用异常?用了异常就要写很多 try catch,在很多场合,比如 jdbc driver,这已经证明了会使代码量增加并且代码的可读性变差。
  这里的思路会不会影响大家写程序的习惯呢?

  StringUtils 的函数很多,不一一列举。 Lang 中次重要的类要数 ArrayUtils,主要功能涉及到数组的比较、转换、拆分、合并、查找、增减、倒转等等操作。在 JDK 中,这类操作没有现成的函数。

  Lang 中工具类比较多,这里介绍几个主要的:
  ClassUtils getShortClassName,这个函数应该在 java.lang.Class 类中有的,我看到很多人自己写这个函数。getAllInterfaces,convertClassNamesToClasses,isAssignable,primitivesToWrappers,isInnerClass。
  NumberUtils 关于数字以及数字和字符串转换的类 stringToInt,toDouble,createNumber,isAllZeros, int compare(float lhs, float rhs), isNumber(String str),double min(double[] array)。
  RandomUtils 用于产生随机数的。
  DateFormatUtils 日期时间格式转换,以及本地时间和 UTC 时间转换。
  DateUtils 日期工具类。isSameDay,truncate,round,modify。

  基于反射机制的几个类:
  CompareToBuilder 比较,用在算法、排序、比较的地方。reflectionCompare,append。
  EqualsBuilder 通过反射机制比较。reflectionEquals 很多项目中用到。
  HashCodeBuilder 可以通过反射生成 hash code,很多算法的地方涉及到 hash code,但是并不是每个人都知道一种 hash code 的生成方法。
  ToStringBuilder 当你需要重载 toString 函数而不想写代码把当前类的所有成员信息列出来,可以用这个函数。

  其它的几个类我用得比较少:
  SerializationUtils Java 中得序列化比较奥妙,容易出错啊。
  SystemUtils 可以读取一些关于 jdk 信息,操作系统信息的工具类。


instanceof应用

instanceof
instanceof是Java的一个二元操作符,和==,>,<是同一类东东。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。举个例子:

String s = "I AM an Object!";
boolean isObject = s instanceof Object;

我们声明了一个String对象引用,指向一个String对象,然后用instancof来测试它所指向的对象是否是Object类的一个实例,显然,这是真的,所以返回true,也就是isObject的值为True。

org.apache.commons.beanutils.BeanUtils 简介

BeanUtils简读本
一、简介:

BeanUtils提供对 Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度。

二、用法:

BeanUtils是这个包里比较常用的一个工具类,这里只介绍它的copyProperties()方法。该方法定义如下:

public static void copyProperties(java.lang.Object dest,java.lang.Object orig)
  throws java.lang.IllegalAccessException,
         java.lang.reflect.InvocationTargetException


如果你有两个具有很多相同属性的JavaBean,一个很常见的情况就是Struts里的PO对象(持久对象)和对应的ActionForm,例如 Teacher和TeacherForm。我们一般会在Action里从ActionForm构造一个PO对象,传统的方式是使用类似下面的语句对属性逐个赋值:

//得到TeacherForm
TeacherForm teacherForm=(TeacherForm)form;
//构造Teacher对象
Teacher teacher=new Teacher();
//赋值
teacher.setName(teacherForm.getName());
teacher.setAge(teacherForm.getAge());
teacher.setGender(teacherForm.getGender());
teacher.setMajor(teacherForm.getMajor());
teacher.setDepartment(teacherForm.getDepartment());

//持久化Teacher对象到数据库
HibernateDAO=;
HibernateDAO.save(teacher);

而使用BeanUtils后,代码就大大改观了,如下所示:
//得到TeacherForm
TeacherForm teacherForm=(TeacherForm)form;
//构造Teacher对象
Teacher teacher=new Teacher();
//赋值
BeanUtils.copyProperties(teacher,teacherForm);
//持久化Teacher对象到数据库
HibernateDAO=;
HibernateDAO.save(teacher);


如果Teacher和TeacherForm间存在名称不相同的属性,则BeanUtils不对这些属性进行处理,需要程序员手动处理。例如 Teacher包含modifyDate(该属性记录最后修改日期,不需要用户在界面中输入)属性而TeacherForm无此属性,那么在上面代码的 copyProperties()后还要加上一句:

teacher.setModifyDate(new Date());


怎么样,很方便吧!除BeanUtils外还有一个名为PropertyUtils的工具类,它也提供copyProperties()方法,作用与BeanUtils的同名方法十分相似,主要的区别在于后者提供类型转换功能,即发现两个JavaBean的同名属性为不同类型时,在支持的数据类型范围内进行转换,而前者不支持这个功能,但是速度会更快一些。BeanUtils支持的转换类型如下:

    * java.lang.BigDecimal
    * java.lang.BigInteger
    * boolean and java.lang.Boolean
    * byte and java.lang.Byte
    * char and java.lang.Character
    * java.lang.Class
    * double and java.lang.Double
    * float and java.lang.Float
    * int and java.lang.Integer
    * long and java.lang.Long
    * short and java.lang.Short
    * java.lang.String
    * java.sql.Date
    * java.sql.Time
    * java.sql.Timestamp


这里要注意一点,java.util.Date是不被支持的,而它的子类java.sql.Date是被支持的。因此如果对象包含时间类型的属性,且希望被转换的时候,一定要使用java.sql.Date类型。否则在转换时会提示argument mistype异常。

三、优缺点:

Apache Jakarta Commons项目非常有用。我曾在许多不同的项目上或直接或间接地使用各种流行的commons组件。其中的一个强大的组件就是BeanUtils。我将说明如何使用BeanUtils将local实体bean转换为对应的value 对象:


BeanUtils.copyProperties(aValue, aLocal)


上面的代码从aLocal对象复制属性到aValue对象。它相当简单!它不管local(或对应的value)对象有多少个属性,只管进行复制。我们假设local对象有100个属性。上面的代码使我们可以无需键入至少100行的冗长、容易出错和反复的get和set方法调用。这太棒了!太强大了!太有用了!

现在,还有一个坏消息:使用BeanUtils的成本惊人地昂贵!我做了一个简单的测试,BeanUtils所花费的时间要超过取数据、将其复制到对应的 value对象(通过手动调用get和set方法),以及通过串行化将其返回到远程的客户机的时间总和。所以要小心使用这种威力!

通用日志接口

Common-logging

Common-logging的应用程序编程接口主要在org.apache.commons.logging.log接口中

定义,这个接口主要定义了两类操作:

一类是级别判断,用于减少不必要的日志操作的参数计算从而提高性能,函数名

和参数如下所示:

log.isDebugEnabled();

log.isTraceEnabled();

下面的代码可以很好地解释这点:

  if (log.isDebugEnabled()) {

        ... 一些高代价操作 ...

        log.debug(theResult);

    }

如果日志设施的级别定义高于debug,这些高代价操作可以避免运行。

另一类是日志登记,按照级别登记日志信息,函数名和参数如下所示:

log.debug(Object message);

log.debug(Object message, Throwable t);

log.trace(Object message);

log.trace(Object message, Throwable t);

日志登记操作分又为两小类:一个参数的日志信息登记操作和两个参数的日志信

息登记操作。前者对三类用户都适用,后者用于打印日志登记处的出错堆栈信息,

所以更适用于开发人员调式与维护使用

有关Object根类若干方法得辅助实现

在前面的专题文章中,我们一起过了一遍org.apache.commons.lang包,接下来我们继续看org.apache.commons.lang.builder这个包。在这里面我们可以找到7个类,用于帮助我们实现Java对象的一些基础的共有方法。这7个类分别是:

 

CompareToBuilder – 用于辅助实现Comparable.compareTo(Object)方法;

EqualsBuilder – 用于辅助实现Object.equals()方法;

HashCodeBuilder – 用于辅助实现Object.hashCode()方法;

ToStringBuilder – 用于辅助实现Object.toString()方法;

ReflectionToStringBuilder – 使用反射机制辅助实现Object.toString()方法;

ToStringStyle – 辅助ToStringBuilder控制输出格式;

StandardToStringStyle – 辅助ToStringBuilder控制标准格式。

 

我们知道,在实际应用中,其实经常需要在运行过程中判定对象的知否相等、比较、取hash、和获取对象基本信息(一般是产生log日志)。然而实现这些compareToequalshashCodetoString其实并非那么直截了当,甚至稍有不注意就可能造成难以追踪的bug,而且这些方法手工维护的话,比较繁琐,也容易出错。于是Commons Langbuilder这个包中提供了上述辅助类,为我们简化这些方法的实现和维护。

 

来看一个例子:

 

package sean.study.jakarta.commons.lang;

 

import java.util.Date;

 

import org.apache.commons.lang.builder.CompareToBuilder;

import org.apache.commons.lang.builder.EqualsBuilder;

import org.apache.commons.lang.builder.HashCodeBuilder;

import org.apache.commons.lang.builder.ToStringBuilder;

import org.apache.commons.lang.builder.ToStringStyle;

 

public class BuilderUsage {

 

    public static void main(String[] args) {

       

        Staff staff1 = new Staff(123, "John Smith", new Date());

        Staff staff2 = new Staff(456, "Jane Smith", new Date());

       

        System.out.println("staff1's info: " + staff1);

        System.out.println("staff2's info: " + staff2);

        System.out.println("staff1's hash code: " + staff1.hashCode());

        System.out.println("staff2's hash code: " + staff2.hashCode());

        System.out.println("staff1 equals staff2? " + staff1.equals(staff2));

 

    }

 

}

 

class Staff implements Comparable {

 

    private long staffId;

    private String staffName;

    private Date dateJoined;

 

    public Staff() {

    }

 

    public Staff(long staffId, String staffName, Date dateJoined) {

        this.staffId = staffId;

        this.staffName = staffName;

        this.dateJoined = dateJoined;

    }

 

    public int compareTo(Object o) {

        int res = -1;

        if (o != null && Staff.class.isAssignableFrom(o.getClass())) {

            Staff s = (Staff) o;

            res = new CompareToBuilder()

                    .append(dateJoined, s.getDateJoined())

                    .append(staffName, s.getStaffName()).toComparison();

        }

        return res;

    }

 

    public boolean equals(Object o) {

        boolean res = false;

        if (o != null && Staff.class.isAssignableFrom(o.getClass())) {

            Staff s = (Staff) o;

            res = new EqualsBuilder()

                    .append(staffId, s.getStaffId())

                    .isEquals();

        }

        return res;

    }

 

    public int hashCode() {

        return new HashCodeBuilder(11, 23).append(staffId).toHashCode();

    }

 

    public String toString() {

        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)

                .append("staffId", staffId)

                .append("staffName", staffName)

                .append("dateJoined", dateJoined)

                .toString();

    }

 

    public Date getDateJoined() {

        return dateJoined;

    }

 

    public void setDateJoined(Date dateJoined) {

        this.dateJoined = dateJoined;

    }

 

    public long getStaffId() {

        return staffId;

    }

 

    public void setStaffId(long staffId) {

        this.staffId = staffId;

    }

 

    public String getStaffName() {

        return staffName;

    }

 

    public void setStaffName(String staffName) {

        this.staffName = staffName;

    }

}

 

以下是运行结果:

 

staff1's info: sean.study.jakarta.commons.lang.Staff@190d11[

  staffId=123

  staffName=John Smith

  dateJoined=Sat Jul 30 13:18:45 CST 2005

]

staff2's info: sean.study.jakarta.commons.lang.Staff@1fb8ee3[

  staffId=456

  staffName=Jane Smith

  dateJoined=Sat Jul 30 13:18:45 CST 2005

]

staff1's hash code: 376

staff2's hash code: 709

staff1 equals staff2? false

 

这些builder使用起来都很简单,new一个实例,append需要参与的信息,最后加上toComparisonisEqualstoHashCodetoString这样的结尾即可。相应的,如果你不需要这样级别的控制,也可以使用利用反射机制的版本自动化实现需要的功能,如:

 

    public int compareTo(Object o) {

        return CompareToBuilder.reflectionCompare(this, o);

    }

 

    public boolean equals(Object o) {

        return EqualsBuilder.reflectionEquals(this, o);

    }

 

    public int hashCode() {

        return HashCodeBuilder.reflectionHashCode(this);

    }

 

    public String toString() {

        return ReflectionToStringBuilder.toString(this);

    }

 

尤其当我们在项目中不希望过多的参与到对这些对象方法的维护时,采用Commons提供的利用反射的这些API就成了方便而相对安全的一个方案

整合 JSF+Spring+Hibernate的小例子

整合 JSF+Spring+Hibernate的小例子

(1)UserInfo.java
package com.zhaoqingjie.service.hibernate;

import java.io.Serializable;
import org.apache.commons.lang.builder.ToStringBuilder;

public class UserInfo implements Serializable{
   
    private String id;
   
    private String username;
   
    private String email;
   
    public UserInfo(String id,String username,String email){
       
        this.id = id;
        this.username = username;
        this.email = email;
             
    }
   
    public UserInfo(){
       
    }
   
    public UserInfo(String id){
        this.id = id;    
    }
   
    public String getId(){
        return id;    
    }
   
    public void setId(String id){
        this.id = id;    
    }
   
    public String getEmail(){
        return email;    
    }
   
    public void setEmail(String email){
        this.email = emial;    
    }
   
    public String getUsername(){
        return username;    
    }    
   
    public void setUsername(String username){
        this.username = username;    
    }
   
    public String toString(){
        return new ToStringBuilder(this).append("id",getId()).toString();    
    }
   

}
(2)UserInfo.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
  "
http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
 
<hibernate-mapping>
<class name="com.zhaoqingjie.spring.service.hibernate.UserInfo" table="userinfo">
<meta attribute="class-description" inherit="false">
    @hibernate.class
    table="userinfo"
</meta>

<id name="id" type="java.lang.String" column="id">
<meta attribute="field-description">
    @hibernate.id
    generator-class="assigned"
    type="java.lang.String"
    column="id"
</meta>
<generator class="assigned"/>
</id>

<property name="username" type="java.lang.String" column="username" length="36">
<meta attribute="field-description">
    @hibernate.property
    column="username"
    length="36"
</meta>
</property>

<property name="email" type="java.lang.String" column="email" length="60">
<meta attribute="field-description">
    @hibernate.property
    column="email"
    length="60"
</meta>
</property>

</class>
</hibernate-mapping>

-------------------------------------------------------------------------------------------------------
(3)IUserInfoDAO.java
package com.zhaoqingjie.spring.service.dao;

import com.openv.spring.domainmodel.UserInfoVO;
import org.springframework.dao.DataAccessException;
import java.io.Serializable;

public interface IUserInfoDAO extends Serializable{
    public boolean setUserInfo(UserInfoVO userinfoVO)throws DataAccessException;
   
       
}

(4)UserInfoDAO.java
package com.zhaoqingjie.spring.service.dao.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.doomdark.uuid.UUIDGenerator;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate.support.HibernateDaoSupport;
import com.zhaoqingjie.spring.domainmodel.UserInfoVO;
import com.zhaoqingjie.spring.service.dao.IUserInfoDAO;
import com.zhaoqingjie.spring.service.hibernate.UserInfo;

public class UserInfoDAO extends HibernateDaoSupport implements IUserInfoDAO{
    private static final Log log = LogFactory.getLog(UserInfoDAO.class);
   
    public boolean setUserInfo(UserInfoVO userinfoVO)throws DataAccessException{
        if(userinfoVO == null){
              return false;    
        }    
       
        UserInfo ui = new UserInfo();
        ui.setId(getID());
        ui.setUsername(userinfoVO.getUsername().trim());
        ui.setEmail(userinfoVO.getEmail().trim());
        this.getHibernateTemplate().save(ui);
        return true;
       
    }    
   
    private String getID(){
        return UUIDGenerator.getInatance().generateTimeBaseUUID().toString();    
    }
}

--------------------------------------------------------------------------------------------------
(5)IExampleManager.java

package com.zhaoqingjie.spring.service;
import com.openv.spring.domainmodel.UserInfoVO;
import org.springframework.dao.DataAccessException;
import java.io.Serializable;


public interface IExampleManager extends Serializable {
  public boolean setUserInfo(UserInfoVO userinfoVO)
        throws DataAccessException;
}
(6)ExampleManagerImpl.java
package com.zhaoqingjie.spring.service.impl;

import com.openv.spring.domainmodel.UserInfoVO;
import com.openv.spring.service.IExample29Manager;
import com.openv.spring.service.dao.IUserInfoDAO;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.dao.DataAccessException;

public class ExampleManagerImpl implements IExampleManager {
  private static final Log log = LogFactory
        .getLog(ExampleManagerImpl.class);

  private IUserInfoDAO userinfo;

  public ExampleManagerImpl() {
    log.info("ExampleManagerImpl()...................");
  }

  public void setUserinfo(IUserInfoDAO userinfoDAO)
        throws DataAccessException {
    this.userinfo = userinfoDAO;
  }

  public boolean setUserInfo(UserInfoVO userinfoVO)
        throws DataAccessException {
    return userinfo.setUserInfo(userinfoVO);
  }
}

-----------------------------------------------------------------------------
(7)UserInfoVO.java
package com.zhaoqingjie.spring.domainmodel;

import java.io.Serializable;

public class UserInfoVO implements Serializable{
   
    private String username;
    private String email;
   
    public     String getEmail(){
        return email;    
    }
   
    public void setEmail(String email){
        this.email = email;    
    }
   
    public String getUsername(){
        return username;    
    }
   
    public void setUsername(String username){
        this.username = username;    
    }
}

------------------------------------------------------------------------------------------
JSF表示层
(8)InfoBean.java
package com.zhaoqingjie.spring.jsf;

import javax.faces.context.FacesContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.jsf.FacesContextUtils;

import com.openv.spring.domainmodel.UserInfoVO;
import com.openv.spring.service.IExampleManager;

public class InfoBean {
  private static final Log log = LogFactory.getLog(InfoBean.class);

  private String username = null;

  private String email = null;

  private String response = null;

  private long maximum = 0;

  private boolean maximumSet = false;

  private long minimum = 0;

  private boolean minimumSet = false;
 

  public InfoBean() {
  }

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }
  public String getUsername() {
    return username;
  }
  public void setUsername(String username) {
    this.username = username;
  }

  public String submitPersonInfo() {
    log.info(username);
    log.info(email);

    ApplicationContext ac = FacesContextUtils
          .getWebApplicationContext(FacesContext.getCurrentInstance());
    IExampleManager em = (IExampleManager) ac
          .getBean("exampleService");
    UserInfoVO uiVO = new UserInfoVO();
    uiVO.setUsername(username);
    uiVO.setEmail(email);

    boolean flag = em.setUserInfo(uiVO);


    if (flag) {
        setResponse("注册成功");

        return "success";
    } else {
        setResponse("注册失败");

        return "failure";
    }
  }

  public void setResponse(String response) {
    this.response = response;
  }

  public String getResponse() {
    return null;
  }

  public long getMaximum() {
    return (this.maximum);
  }

  public void setMaximum(long maximum) {
    this.maximum = maximum;
    this.maximumSet = true;
  }

  public long getMinimum() {
    return (this.minimum);
  }

  public void setMinimum(long minimum) {
    this.minimum = minimum;
    this.minimumSet = true;
  }
}
(9)index.jsp
<html>
<head>
</head>
<body>
<jsp:forward page="/example/home.jsp" />
</body>
</html>
(10)home.jsp
<%@ page contentType="text/html; charset=gbk" %>
<%@ taglib uri="
http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="
http://java.sun.com/jsf/core" prefix="f" %>
<html>
<head>
<title>
用户注册
</title>
</head>
<br>
  <f:view>
  <h:form id="helloForm" >
        <table border="10" align="center"
            bordercolor="#0099CC" cellpadding="6" bordercolorlight="#999999">
              <tr>
                  <td colspan="2" bgcolor="#66CCFF">输入用户注册信息:</td>
              </tr>
              <tr>
                <td>
                  <div align="right">用户名</div>
                </td>
                <td>
                        <h:inputText id="username" value="#{InfoBean.username}">
                        <f:validateLength minimum="#{InfoBean.minimum}"
                            maximum="#{InfoBean.maximum}" />
                    </h:inputText>
                </td>
              </tr>
              <tr>
                <td>
                  <div align="right">E_mail</div>
                </td>
                <td>
                        <h:inputText id="email" value="#{InfoBean.email}"/>
                </td>
              </tr>
              <tr>
                  <td colspan="2" bgcolor="#FFFF40">
                      <span>    
                            <h:message id="message"
                                for="username"/></span>
                  </td>
              </tr>
              <tr>
                  <td align="center" colspan="2">
                        <h:commandButton id="submit"
                            action="#{InfoBean.submitPersonInfo}" value="提交" />
                  </td>
              </tr>    
        </table>
  </h:form>
  </f:view>
</html>

(11)success.jsp
<%@ page contentType="text/html; charset=gbk" %>
<%@ taglib uri="
http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="
http://java.sun.com/jsf/core" prefix="f" %>
<html>
<head>
<title>
用户注册成功
</title>
</head>
<body bgcolor="white">
  <f:view>
    <h:form id="responseForm">
        <h:graphicImage id="successImg"
            url="images/form-success.jpg" alt="注册成功!"/>
        <h2>
        <h:outputText id="result"
                  value="#{InfoBean.response}"/></h2>  
            <h:commandButton id="back"
                value="返回" action="su"/>
            <p>
      </h:form>
  </f:view>
</html>
(12)failure.jsp
<%@ page contentType="text/html; charset=gbk" %>
<%@ taglib uri="
http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="
http://java.sun.com/jsf/core" prefix="f" %>
<html>
<head>
<title>
用户注册失败
</title>
</head>
<body bgcolor="white">
  <f:view>
    <h:form id="responseForm">
        <h:graphicImage id="successImg"
            url="images/form-error.jpg" alt="注册失败!"/>
        <h2>
        <h:outputText id="result"
                  value="#{InfoBean.response}"/></h2>  
            <h:commandButton id="back"
                value="返回" action="su"/>
            <p>
      </h:form>
  </f:view>
</html>
(13)web.xml
<?xml version="1.0"?>
<web-app xmlns="
http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
http://java.sun.com/xml/ns/j2ee
   
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
  version="2.4">
 
  <display-name>example</display-name>

    <context-param>    
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>

    <servlet>
        <display-name>FacesServlet</display-name>
        <servlet-name>FacesServlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
      <servlet-name>FacesServlet</servlet-name>
      <url-pattern>/example/*</url-pattern>
    </servlet-mapping>
     
</web-app>
(14)applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

    <bean id="dataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName">
        <value>java:/MySqlDS</value>
    </property>
  </bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
        <property name="dataSource">
              <ref local="dataSource"/>
        </property>
        <property name="mappingResources">
              <list>
                  <value>
                      com/openv/spring/service/hibernate/UserInfo.hbm.xml
                  </value>
              </list>
        </property>
        <property name="hibernateProperties">
              <props>
                  <prop key="hibernate.dialect">
                      net.sf.hibernate.dialect.MySQLDialect
                  </prop>
                  <prop key="hibernate.show_sql">
                      true
                  </prop>
              </props>
        </property>
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate.HibernateTransactionManager">
        <property name="sessionFactory">
              <ref local="sessionFactory"/>
        </property>
    </bean>

    <bean id="exampleServiceTarget"
        class="com.openv.spring.service.impl.Example29ManagerImpl">
        <property name="userinfo">
              <ref local="userinfoDAO"/>
        </property>
    </bean>    
   
    <bean id="exampleService"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager">
              <ref local="transactionManager"/>
        </property>
        <property name="target">
              <ref local="exampleServiceTarget"/>
        </property>
        <property name="transactionAttributes">
              <props>
                  <prop key="get*">
                      PROPAGATION_REQUIRED,readOnly
                  </prop>
                  <prop key="set*">
                      PROPAGATION_REQUIRED
                  </prop>
              </props>
        </property>
    </bean>
   
    <bean id="userinfoDAO"
        class="com.openv.spring.service.dao.impl.UserInfoDAO">
        <property name="sessionFactory">
              <ref local="sessionFactory"/>
        </property>
    </bean>
   
</beans>
(15)faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
"
http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>

<application>
  <locale-config>
    <default-locale>zh_CN</default-locale>
  </locale-config>
</application>

<navigation-rule>
  <description>
      JSF Home Page
  </description>
  <from-view-id>/home.jsp</from-view-id>
  <navigation-case>
    <description>
          success
    </description>
    <from-outcome>success</from-outcome>
    <to-view-id>/success.jsp</to-view-id>
  </navigation-case>
  <navigation-case>
    <description>
          failure
    </description>
    <from-outcome>failure</from-outcome>
    <to-view-id>/failure.jsp</to-view-id>
  </navigation-case>
</navigation-rule>

<navigation-rule>
  <description>
  </description>
  <from-view-id>/success.jsp</from-view-id>
  <navigation-case>
    <description>
    </description>
    <from-outcome>su</from-outcome>
    <to-view-id>/home.jsp</to-view-id>
  </navigation-case>
</navigation-rule>

<navigation-rule>
  <description>
  </description>
  <from-view-id>/failure.jsp</from-view-id>
  <navigation-case>
    <description>
    </description>
    <from-outcome>su</from-outcome>
    <to-view-id>/home.jsp</to-view-id>
  </navigation-case>
</navigation-rule>

<managed-bean>
  <description>
      InfoBean
  </description>
  <managed-bean-name>InfoBean</managed-bean-name>
  <managed-bean-class>
      com.openv.spring.jsf.InfoBean
  </managed-bean-class>
 
  <managed-bean-scope>session</managed-bean-scope>
  <managed-property>
    <property-name>minimum</property-name>
    <property-class>long</property-class>
    <value>6</value>
  </managed-property>
 
  <managed-property>
    <property-name>maximum</property-name>
    <property-class>long</property-class>
    <value>18</value>
  </managed-property>
</managed-bean>

</faces-config>


20 juin

快速上手XDoclet 1 -- Servlet简单实例

XDoclet是一个扩展的Javadoc Doclet引擎。它是一种通用的java工具,可以让你创建自己的javadoc @tags进而利用XDoclet中的Templet enging基于这些@tags生成源代码或其他文件(例如xml的deployment descriptors)。
 
     关于XDoclet的体系结构和工作原理方面的内容我不想多说,可以google一下。我只想通过简单的实例对XDoclet快速上手。因为我发现,学习某个新的知识点的时候,概念方面介绍的很多,但是实例却很少,很难通过实例快速消化概念性的东西。与其说一大堆天书之类的话,还不如给我一个实例,好让我揣摩揣摩。
 
   在看这篇文章之前,最好要熟悉ANT
 
 
 
1. 所需软件
● Ant 1.6.2  http://ant.apache.org
 
 
● Tomcat 5.0.28   http://jakarta.apache.org/tomcat/
 
2. 安装 
F:\j2sdk                              JDK 目录
F:\java\ant                           Ant 目录
F:\java\xdoclet                       XDoclet 目录
F:\java\jakarta-tomcat                Tomcat  目录 
 
    这里着重指出一下,需要在环境变量中设置 ANT_HOME ,并将其指向Ant安装目录,还要在Path变量值中添加 “%ANT_HOME%\bin;” 可以参考 java环境变量设置
 
 
 
1. 编写代码
 
   创建 D:\XDocletSample 目录, 依照如下结构建立3个文件。           
 

D:\XDocletSample\src\javamxj\HelloServlet.java

/*
 * @author javamxj (CSDN Blog) 创建日期 2005-1-7
 */
package javamxj;
import javax.servlet.*;
import javax.servlet.http.*;
/**
 * @web.servlet name="HelloServlet" 
 *              display-name="Hello Servlet"
 *              load-on-startup="1"
 * @web.servlet-init-param name="hello" 
 *              value="${hello.servlet}"
 * @web.servlet-mapping url-pattern="/Hello/*"
 */
public class HelloServlet extends HttpServlet {
    public void init(ServletConfig config) throws ServletException {
        //从web.xml中获得初始化参数
        super.init(config);
    }
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException,
            java.io.IOException {
        ServletConfig config = this.getServletConfig();
        String h = config.getInitParameter("hello");
        try {
            //首先设置文档类型
            response.setContentType("text/html; charset=GBK");
            //获取输出流
            java.io.PrintWriter out = response.getWriter();
            out.println("<html><head><title>Welcome javamxj Blog!</title></head>");
            out.println("<body><h1>");
            out.println(" Hello:  " + h);
            out.println("</h1></body></html>");
            out.close();
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }
}
 

D:\XDocletSample\build.xml

<?xml version="1.0" encoding="GBK"?>
<project name="filtering" default="deploy" basedir=".">
 <description>一个简单的XDoclet实例</description>
 
 <!-- 载入属性文件 -->
 <property file="build.properties"/>
 
 <!-- 定义类路径 -->
 <path id="web.classpath">
  <pathelement location="${tomcat.home}/common/lib/servlet-api.jar"/>
  <pathelement location="${tomcat.home}/common/lib/jsp-api.jar"/>
 </path>
 <path id="xdoclet.classpath">
  <fileset dir="${xdoclet.home}/lib">
   <include name="*.jar"/>
  </fileset>
  <path refid="web.classpath"/>
 </path>
 
 <!-- 初始化,建立目录 -->
 <target name="init">
  <mkdir dir="${dist.dir}"/>
  <mkdir dir="${dist.dir}/WEB-INF"/>
  <mkdir dir="${dist.dir}/WEB-INF/classes"/>
 </target>
 
 <!-- XDoclet 的 WebDoclet 任务 -->
 <target name="webdoclet" depends="init">
  <taskdef 
      name="webdoclet" 
      classpathref="xdoclet.classpath" 
      classname="xdoclet.modules.web.WebDocletTask"/>
      
  <webdoclet destDir="${dist.dir}/WEB-INF" force="${xdoclet.force}">
      <deploymentdescriptor Servletspec="2.4" xmlencoding="GBK"/>
   <fileset dir="${src.dir}" includes="**/*Servlet.java"/>   
  </webdoclet>  
 </target>
 
 <!-- 编译与部署 -->
 <target name="deploy" depends="webdoclet">
  <javac srcdir="${src.dir}" destdir="${dist.dir}/WEB-INF/classes">
   <classpath refid="web.classpath"/>
  </javac>
  <jar destfile="${tomcat.home}/webapps/${app.name}.war" basedir="${dist.dir}"/>
 </target> 
</project>
 
 

D:\XDocletSample\build.properties

################ 环境设置 ###################
 
#  
#  文件名:build.properties  
#  作者: CSDN javamxj
#
#  web服务器目录
tomcat.home=F:/java/jakarta-tomcat
#  xdoclet目录
xdoclet.home=F:/java/xdoclet
#  web的临时目录
dist.dir=./dist
#  源文件目录
src.dir=./src
#  发布的程序名
app.name=HelloWeb
#  Servlet参数,可以改变
hello.servlet=javamxj blog    
你可以根据自己的设置在 build.properties 属性文件中改变 Tomcat、XDoclet 的目录。
 
 
2. 运行程序
 
● 打开一个MS-DOS窗口,切换到 D:\XDocletSample 目录,输入 ant 命令:
  
● 然后启动Tomcat服务器,打开浏览器窗口,输入地址: http://localhost:8080/HelloWeb/Hello/
 
 
   打开 build.properties 文件,将“ hello.servlet=javamxj blog ”语句修改为“ hello.servlet=CSDN ”, 然后保存。
 
  在MS-DOS中,输入“ant -Dxdoclet.force=true”
 
  刷新浏览器窗口,则显示如下:
 
好了,这只是一个简单的XDoclet实例。
 
 
三、web.xml 是如何生成的   
 
   注意到没有,这里并没有写 web.xml 文件,但是可以从 D:\XDocletSample\dist\WEB-INF 目录下发现一个 web.xml 文件。 内容如下(为了便于浏览,我已把注释删除):
  D:\XDocletSample\dist\WEB-INF\web.xml
 
    也许你会认为这没什么,也不是很简单,但当利用XDoclet开发EJB时,你就会更加体会到它的优越性的。 下篇文章就谈谈如何开发EJB。
 
 
 
四、参考资料
 
         (这是IBM网站上的一个教程,这篇文章就是以它为蓝本写作的。需要注册,才能登陆。)
         (同上,这是IBM 的中国台湾网站上的文章,繁体的,不用注册)
 
           XDoclet 学习笔记
        (这是一个系列,共有4篇文章,对于XDoclet的原理说的比较透彻。)
 
 
其它: XDoclet本身自带的文档和实例。
        (建议好好看看,反正我是经常用到的)

快速上手XDoclet 1 -- Servlet简单实例

 XDoclet是一个扩展的Javadoc Doclet引擎。它是一种通用的java工具,可以让你创建自己的javadoc @tags进而利用XDoclet中的Templet enging基于这些@tags生成源代码或其他文件(例如xml的deployment descriptors)。
 
     关于XDoclet的体系结构和工作原理方面的内容我不想多说,可以google一下。我只想通过简单的实例对XDoclet快速上手。因为我发现,学习某个新的知识点的时候,概念方面介绍的很多,但是实例却很少,很难通过实例快速消化概念性的东西。与其说一大堆天书之类的话,还不如给我一个实例,好让我揣摩揣摩。
 
   在看这篇文章之前,最好要熟悉ANT
 
 
 
1. 所需软件
● Ant 1.6.2  http://ant.apache.org
 
 
● Tomcat 5.0.28   http://jakarta.apache.org/tomcat/
 
2. 安装 
F:\j2sdk                              JDK 目录
F:\java\ant                           Ant 目录
F:\java\xdoclet                       XDoclet 目录
F:\java\jakarta-tomcat                Tomcat  目录 
 
    这里着重指出一下,需要在环境变量中设置 ANT_HOME ,并将其指向Ant安装目录,还要在Path变量值中添加 “%ANT_HOME%\bin;” 可以参考 java环境变量设置
 
 
 
1. 编写代码
 
   创建 D:\XDocletSample 目录, 依照如下结构建立3个文件。           
 

D:\XDocletSample\src\javamxj\HelloServlet.java

/*
 * @author javamxj (CSDN Blog) 创建日期 2005-1-7
 */
package javamxj;
import javax.servlet.*;
import javax.servlet.http.*;
/**
 * @web.servlet name="HelloServlet" 
 *              display-name="Hello Servlet"
 *              load-on-startup="1"
 * @web.servlet-init-param name="hello" 
 *              value="${hello.servlet}"
 * @web.servlet-mapping url-pattern="/Hello/*"
 */
public class HelloServlet extends HttpServlet {
    public void init(ServletConfig config) throws ServletException {
        //从web.xml中获得初始化参数
        super.init(config);
    }
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException,
            java.io.IOException {
        ServletConfig config = this.getServletConfig();
        String h = config.getInitParameter("hello");
        try {
            //首先设置文档类型
            response.setContentType("text/html; charset=GBK");
            //获取输出流
            java.io.PrintWriter out = response.getWriter();
            out.println("<html><head><title>Welcome javamxj Blog!</title></head>");
            out.println("<body><h1>");
            out.println(" Hello:  " + h);
            out.println("</h1></body></html>");
            out.close();
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }
}
 

D:\XDocletSample\build.xml

<?xml version="1.0" encoding="GBK"?>
<project name="filtering" default="deploy" basedir=".">
 <description>一个简单的XDoclet实例</description>
 
 <!-- 载入属性文件 -->
 <property file="build.properties"/>
 
 <!-- 定义类路径 -->
 <path id="web.classpath">
  <pathelement location="${tomcat.home}/common/lib/servlet-api.jar"/>
  <pathelement location="${tomcat.home}/common/lib/jsp-api.jar"/>
 </path>
 <path id="xdoclet.classpath">
  <fileset dir="${xdoclet.home}/lib">
   <include name="*.jar"/>
  </fileset>
  <path refid="web.classpath"/>
 </path>
 
 <!-- 初始化,建立目录 -->
 <target name="init">
  <mkdir dir="${dist.dir}"/>
  <mkdir dir="${dist.dir}/WEB-INF"/>
  <mkdir dir="${dist.dir}/WEB-INF/classes"/>
 </target>
 
 <!-- XDoclet 的 WebDoclet 任务 -->
 <target name="webdoclet" depends="init">
  <taskdef 
      name="webdoclet" 
      classpathref="xdoclet.classpath" 
      classname="xdoclet.modules.web.WebDocletTask"/>
      
  <webdoclet destDir="${dist.dir}/WEB-INF" force="${xdoclet.force}">
      <deploymentdescriptor Servletspec="2.4" xmlencoding="GBK"/>
   <fileset dir="${src.dir}" includes="**/*Servlet.java"/>   
  </webdoclet>  
 </target>
 
 <!-- 编译与部署 -->
 <target name="deploy" depends="webdoclet">
  <javac srcdir="${src.dir}" destdir="${dist.dir}/WEB-INF/classes">
   <classpath refid="web.classpath"/>
  </javac>
  <jar destfile="${tomcat.home}/webapps/${app.name}.war" basedir="${dist.dir}"/>
 </target> 
</project>
 
 

D:\XDocletSample\build.properties

################ 环境设置 ###################
 
#  
#  文件名:build.properties  
#  作者: CSDN javamxj
#
#  web服务器目录
tomcat.home=F:/java/jakarta-tomcat
#  xdoclet目录
xdoclet.home=F:/java/xdoclet
#  web的临时目录
dist.dir=./dist
#  源文件目录
src.dir=./src
#  发布的程序名
app.name=HelloWeb
#  Servlet参数,可以改变
hello.servlet=javamxj blog    
你可以根据自己的设置在 build.properties 属性文件中改变 Tomcat、XDoclet 的目录。
 
 
2. 运行程序
 
● 打开一个MS-DOS窗口,切换到 D:\XDocletSample 目录,输入 ant 命令:
  
● 然后启动Tomcat服务器,打开浏览器窗口,输入地址: http://localhost:8080/HelloWeb/Hello/
 
 
   打开 build.properties 文件,将“ hello.servlet=javamxj blog ”语句修改为“ hello.servlet=CSDN ”, 然后保存。
 
  在MS-DOS中,输入“ant -Dxdoclet.force=true”
 
  刷新浏览器窗口,则显示如下:
 
好了,这只是一个简单的XDoclet实例。
 
 
三、web.xml 是如何生成的   
 
   注意到没有,这里并没有写 web.xml 文件,但是可以从 D:\XDocletSample\dist\WEB-INF 目录下发现一个 web.xml 文件。 内容如下(为了便于浏览,我已把注释删除):
  D:\XDocletSample\dist\WEB-INF\web.xml
    也许你会认为这没什么,也不是很简单,但当利用XDoclet开发EJB时,你就会更加体会到它的优越性的。 下篇文章就谈谈如何开发EJB。
 
 
 
四、参考资料
 
         (这是IBM网站上的一个教程,这篇文章就是以它为蓝本写作的。需要注册,才能登陆。)
         (同上,这是IBM 的中国台湾网站上的文章,繁体的,不用注册)
 
           XDoclet 学习笔记
        (这是一个系列,共有4篇文章,对于XDoclet的原理说的比较透彻。)
 
 
其它: XDoclet本身自带的文档和实例。
        (建议好好看看,反正我是经常用到的)

xdoclet 与 hibernate

 

这里将利用xdoclet来为hibernate生成相关代码(由Customer.java生成Customer.hbm.xml),看看xdoclet对提供工作效率的。

运行环境:
1、xdoclet
2、ant
3、hibernate
需要的jar包有

  • xdoclet-/X.X.X/.jar
  • xdoclet-hibernate-module-/X.X.X/.jar
  • xdoclet-xjavadoc-/X.X.X/.jar
  • xdoclet-xdoclet-module-/X.X.X/.jar
  • log4j-/X.X.X/.jar
  • commons-collections-2.0.jar
  • commons-logging.jar

    前四个可以从xdoclet里的lib里面找到(这里“ /X.X.X/ ” 表示版本号),后面的几个我想大家都熟了吧可以从很多地方找到。


    程序
    看下文件结构
    .(项目目录)
         |
         -src(文件夹,命名src.dir,存放源文件)
         |
         -lib(文件夹,命名lib.dir,存放上面提到的几个jar文件)
                  |
                  -*.jar
         |
         -bin(文件夹,命名bin.dir)
                 |
                 -src(文件夹,存放生成的*.java文件,这里将不用到)
                 |
                 -classes(文件夹,存放所编译的*.class文件)
       |
       -build.xml
     
    看下源程序吧。
    1、Customer.java

    /*
     * Created on 2004-12-20
     * @author roson
     */
    package hibernate;
    import java.util.Set;
    import java.util.Collections;
    /**
     * @author roson
     * @since 1.0
     * @version 1.0
     * @hibernate.class tables="customers"
     */
    public class Customer {
        /**This customer's identifier field.
         */
        private long id;
       
        /**This customer's name field.
         */
        private String name;
       
        /**The customer's orders set.
         */
        private Set orders=Collections.EMPTY_SET;
       
        /**The default construtor for Hibernate to instantiate with.
         */
        public Customer() {}
       
        /**The getter method for this Customer's identifier.
         *
         * @hibernate.id generator-class="native"
         */
        public long getId()
        {
            return id;
        }
       
        /**The setter method for this Customer's identifier.
         */
        public void setId(long id)
        {
            this.id=id;
        }
       
        /**The getter method for this Customer's name.
         *
         * @hibernate.property
         */
        public String getName()
        {
            return name;
        }
       
        /**The setter method for this Customer's name.
         */
        public void setName(String name)
        {
            this.name=name;
        }
       
        /**The getter method for this Customer's orders.
         *
         * @hibernate.set role="orders"
         *
         * @hibernate.collection-key column="customer_id"
         *
         * @hibernate.collection-one-to-many class="Order"
         */
        public Set getOrders()
        {
            return orders;
        }
       
        /**The setter method for this Customer's orders.
         */
        public void setOrders(Set orders)
        {
            this.orders=orders;
        }
    }

    可以看到在源程序中多了一些注释之类的标签,xdoclet就是通过这些标签来识别自动生成xml文件的,除此之外Customer.java与普通的javabean没什么区别。
    注意:这里Customer.java打包为hibernate,如要改动要更改一下build.xml。

    2、build.xml

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <project name="hibernate" default="compile" basedir=".">
     <property name="src.dir" location="src"></property>
     <property name="bin.dir" value="bin"></property>
     <property name="lib.dir" location="lib"></property>
     <path id="lib.path">
     <fileset dir="${lib.dir}">
     <include name="*.jar"/>
     </fileset> 
      <pathelement location="lib/xdoclet-hibernate-module-1.2.1.jar"/>
     </path>
     <target name="init">
      <tstamp>
      <format property="TODAY" pattern="yy-mm-d"/>
      </tstamp>
      <mkdir dir="bin"/>
      <mkdir dir="${bin.dir}/src"/>
      <mkdir dir="${bin.dir}/classes"/>
      <taskdef   name="hibernatedoclet"
         classname="xdoclet.modules.hibernate.HibernateDocletTask"
         classpathref="lib.path"
        />
      
      <taskdef name="ejbdoclet"
        classname="xdoclet.ejb.EjbDocletTask"
        classpathref="lib.path">
      </taskdef>
     </target>


     <target name="compile" depends="init,hibernate">
     <javac srcdir="${src.dir};${bin.dir}/src" destdir="${bin.dir}/classes">
     <classpath refid="lib.path"></classpath>
     </javac>
     </target>
     

     <target name="hibernate" depends="init">
      <hibernatedoclet
       destdir="${bin.dir}"
       mergedir="${bin.dir}"
       force="${bin.dir}"
       excludedtags="@version,@author,@todo"
       addedtags="@xdoclet-generated at ${TODAY},@copyright netone,@author roson,@version ${version}"
       verbose="false"
       >
       <fileset dir="${src.dir}">
       <include name="*.java"/>
       </fileset>
       <hibernate version="2.0"/>
      </hibernatedoclet>
     </target>
     
     
     <target name="clean">
     <delete dir="${bin.dir}"></delete>
     </target>
    </project>

    build.xml文件通过ant来运行。首先 请确保ant能够运行,接着 打开 命令提示行(在运行那里输入cmd),转到上面结构所提的“项目目录”,直接输入  ant    就行。
    注意:
    最让我烦恼的就是 taskdef 部分。原因就是没有把所需要的jar包放进 lib 文件夹。并且要理解的是,它所需的classname="xdoclet.modules.hibernate.HibernateDocletTask"  ,并不仅仅要求含有HibernateDocletTask.class这个文件的包,而是同时需要几个包同时存在。希望大家不要在犯同样的错误。

    好了,大体就是这样了。可以参照http://www.hibernate.org/72.html


  • XHTML 1.0 Tags 参考

    开始标签 用途(Purpose) NN IE DTD
             
    基本标签        
    <!DOCTYPE> 文档类型(Defines the document type)     STF
    <html> html文档(Defines a html document) 3.0 3.0 STF
    <body> body元素(Defines the body element) 3.0 3.0 STF
    <h1> to <h6> 标题1 -- 标题6(Defines header 1 to header 6) 3.0 3.0 STF
    <p> 段落(Defines a paragraph) 3.0 3.0 STF
    <br /> 换行(Inserts a single line break) 3.0 3.0 STF
    <hr /> 水平线(Defines a horizontal rule) 3.0 3.0 STF
    <!--...--> 注释(Defines a comment) 3.0 3.0 STF
    Char Format        
    <b> 粗体文本(Defines bold text) 3.0 3.0 STF
    <font> 文字的外观,大小和颜色(Defines the font face, size, and color of text) 3.0 3.0 TF
    <i> 文本为斜体(Defines italic text) 3.0 3.0 STF
    <em> 文本为重要(Defines emphasized text) 3.0 3.0 STF
    <big> 文本增大(Defines big text) 3.0 3.0 STF
    <strong> 文本为非常重要(Defines strong text) 3.0 3.0 STF
    <small> 文本缩小(Defines small text) 3.0 3.0 STF
    <sup> 文本上标(Defines superscripted text) 3.0 3.0 STF
    <sub> 文本下标(Defines subscripted text) 3.0 3.0 STF
    <bdo> 文本输出顺序(Defines the direction of text display) 6.2 5.0 STF
    <u> 文本下划线(Defines underlined text) 3.0 3.0 TF
    输出        
    <pre> 预先格式(保留文件中空格的大小)(Defines preformatted text) 3.0 3.0 STF
    <code> 码(显示源码用)(Defines computer code text) 3.0 3.0 STF
    <tt> 打印机字体(Defines teletype text) 3.0 3.0 STF
    <kbd> 键盘(Defines keyboard text) 3.0 3.0 STF
    <dfn> 定义(Defines a definition term)   3.0 STF
    <var> 变数(Defines a variable) 3.0 3.0 STF
    <samp> 样本(Defines sample computer code) 3.0 3.0 STF
    <xmp> 不赞成使用,使用<pre>代替(Deprecated. Defines preformatted text. Use <pre> instead) 3.0 3.0  
    结构性定义        
    <acronym> 只取首字母的缩写词(Defines an acronym) 6.2 4.0 STF
    <abbr> 缩写(Defines an abbreviation) 6.2 ? STF
    <address> 地址(Defines an address element) 4.0 4.0 STF
    <blockquote> 引文区块(Defines an long quotation) 3.0 3.0 STF
    <center> 句中对齐(Defines centered text) 3.0 3.0 TF
    <q> 引用短语(Defines a short quotation) 6.2 4.0 STF
    <cite> 引文(Defines a citation) 3.0 3.0 STF
    <ins> 插入(Defines inserted text) 6.2 4.0 STF
    <del> 删除(Defines deleted text) 6.2 4.0 STF
    <s> 删除线(Defines strikethrough text) 3.0 3.0 TF
    <strike> 删除线(Defines strikethrough text) 3.0 3.0 TF
    链接        
    <a> 链接(Defines an anchor) 3.0 3.0 STF
    <link> 资源参考(Defines a resource reference) 4.0 3.0 STF
    框架        
    <frame> 定义个别视框(Defines a sub window (a frame)) 3.0 3.0 F
    <frameset> 视框格式总定义(Defines a set of frames) 3.0 3.0 F
    <noframes> 无视框时的内容(Defines a noframe section) 3.0 3.0 TF
    <iframe> 定义嵌入视图(Defines an inline sub window (frame)) 6.0 4.0 TF
    输入        
    <form> 定义表单(Defines a form) 3.0 3.0 STF
    <input /> 定义输入域(Defines an input field) 3.0 3.0 STF
    <textarea> 输入区换行方式(Defines a text area) 3.0 3.0 STF
    <button> 按钮(Defines a push button) 6.2 4.0 STF
    <select> 下拉式选单(Defines a selectable list) 3.0 3.0 STF
    <optgroup> 选项组(Defines an option group) 6.0 6.0 STF
    <option> 列表选项(Defines an item in a list box) 3.0 3.0 STF
    <label>

    标签(用于表单控制?)(Defines a label for a form control)

    6.2 4.0 STF
    <fieldset> 域(Defines a fieldset) 6.2 4.0 STF
    <legend> 域标题(Defines a title in a fieldset) 6.2 4.0 STF
    <isindex> 不建议使用(可搜寻,使用input代替)(Deprecated. Defines a single-line input field. Use <input> instead) 3.0 3.0 TF
    列举        
    <ul> 无次序式列举(Defines an unordered list) 3.0 3.0 STF
    <ol> 有次序式列举(Defines an ordered list) 3.0 3.0 STF
    <li> 每条项目列表(Defines a list item) 3.0 3.0 STF
    <dir> 目录式列举(Defines a directory list) 3.0 3.0 TF
    <dl> 定义式列举(Defines a definition list) 3.0 3.0 STF
    <dt> 定义项目(Defines a definition term) 3.0 3.0 STF
    <dd> 定义说明(Defines a definition description) 3.0 3.0 STF
    <menu> 菜单列表(Defines a menu list) 3.0 3.0 TF
    图片        
    <img /> 图片(Defines an image) 3.0 3.0 STF
    <map> 图片地图(Defines an image map) 3.0 3.0 STF
    <area /> 图片热点(Defines an area inside an image map) 3.0 3.0 STF
    表格        
    <table> 表格(Defines a table) 3.0 3.0 STF
    <caption> 表格抬头(Defines a table caption) 3.0 3.0 STF
    <th> 表格标题(Defines a table header) 3.0 3.0 STF
    <tr> 行(Defines a table row) 3.0 3.0 STF
    <td> 单元格(列)(Defines a table cell) 3.0 3.0 STF
    <thead> 定义表格头(Defines a table header)   4.0 STF
    <tbody> 定义表格主体(Defines a table body)   4.0 STF
    <tfoot> 定义表格脚(Defines a table footer)   4.0 STF
    <col> 定义特有特征(Defines attributes for table columns)   3.0 STF
    <colgroup> 定义特征集合(Defines groups of table columns)   3.0 STF
    样式        
    <style> 样式定义(Defines a style definition) 4.0 3.0 STF
    <div> 在文档中定义一个区域(Defines a section in a document) 3.0 3.0 STF
    <span> 在文档中定义一个区域(Defines a section in a document) 4.0 3.0 STF
    头信息        
    <head> 定语关于文档的信息(Defines information about the document) 3.0 3.0 STF
    <title> 定义文档标题(Defines the document title) 3.0 3.0 STF
    <meta> 定义背景资讯(Defines meta information) 3.0 3.0 STF
    <base /> 基本文档中所有链接的基准(Defines a base URL for all the links in a page) 3.0 3.0 STF
    <basefont /> 定义基本字体(Defines a base font) 3.0 3.0 TF
    脚本、引用外部对象相关        
    <script> 定义脚本(Defines a script) 3.0 3.0 STF
    <noscript> 定义无脚本的显示区域(Defines a noscript section) 3.0 3.0 STF
    <applet> 定义java程序(Defines an applet) 2.0 3.0 TF
    <object> 定义内嵌对象(Defines an embedded object) ? 3.0 STF
    <param> 定义对象的参数(Defines a parameter for an object) 3.0 3.0 STF

    ps:我原打算整理一下关于xhtml tag的语义,发现这个表已经说得挺明确。随后我会补充一下!

    Last update:2006-06-13 00:30

    1. dl, dt, dd系列定义列表
    dl就是“定义列表”。比如说词典里面的词的解释、定义就可以用这种列表。如:

    <dl>
    <dt>Dog</dt>
    <dd>A carnivorous mammal of the family Canidae.</dd>
    </dl>

    2. citeq, 良好引用
    在写blog的时候,经常是要引用一些blogger的话语,那么可以用cite标签。一般的blog程序后代自带的blockquote,是用来引用大段的话,还必须包含块级元素,比如div, p等等。而且blockquote也自带一个cite属性,可以以URI标注资料的来源。cite标签则主要用来引用某人的话,如:

    <p>And <cite>Bob</cite> said <q>No, I think it's a banana</q>.</p>

    3. dfn, 下定义

    <p><dfn title="Microsoft web browser">Internet Explorer</dfn> is the most popular browser used underwater.</p>

    4. ins, del, 插入和删除

    知道del,就不要再用<s>做删除线了,用del显然更具有语义化。而且del还带有citedatetime来表明删除的原因以及删除的时间。ins是表示插入,也有这样的属性。如:
    <p>It really was <ins cite="rarara.html" datetime="20031024">very</ins> good.</p>

    5. code, 表示是计算机代码
    本文所用到的标签,都用<code>和</code>包含了起来,表示是计算机代码。而默认情况下,这些代码会用打字体表示。

    <code>p{margin:2px 0;}</code>

    Javaserver Faces 简介 — 什么是 JSF?

    什么是 JSF?

    JavaServer Faces (JSF) 是一种用于构建 Web 应用程序的新标准 Java 框架。它提供了一种以组件为中心来开发 Java Web 用户界面的方法,从而简化了开发。JavaServer Faces 还引起了广大 Java/Web 开发人员的兴趣。“企业开发人员”和 Web 设计人员将发现 JSF 开发可以简单到只需将用户界面 (UI) 组件拖放到页面上,而“系统开发人员”将发现丰富而强健的 JSF API 为他们提供了无与伦比的功能和编程灵活性。JSF 还通过将良好构建的模型-视图-控制器 (MVC) 设计模式集成到它的体系结构中,确保了应用程序具有更高的可维护性。最后,由于 JSF 是通过 Java Community Process (JCP) 开发的一种 Java 标准,因此开发工具供应商完全能够为 JavaServer Faces 提供易于使用的、高效的可视化开发环境。

    JSF 体系结构

    JavaServer Faces 的 MVC 实现

    JSF 的主要优势之一就是它既是 Java Web 用户界面标准又是严格遵循模型-视图-控制器 (MVC) 设计模式的框架。用户界面代码(视图)与应用程序数据和逻辑(模型)的清晰分离使 JSF 应用程序更易于管理。为了准备提供页面对应用程序数据访问的 JSF 上下文和防止对页面未授权或不正确的访问,所有与应用程序的用户交互均由一个前端“Faces”servlet(控制器)来处理。

    图 1:JavaServer Faces 的 MVC 实现

    JSF 生命周期

    Faces Controller servlet 充当用户和 JSF 应用程序之间的纽带。它在明确限定的 JSF 生命周期(规定了用户请求之间的整个事件流)的范围内工作。例如,一收到访问 JSF 应用程序的初始 Web 请求,Faces Controller servlet 便通过首先准备 JSF 上下文(存放所有应用程序数据的一个 Java 对象)来处理请求。然后控制器把用户指引到所请求的页面。该页面通常使用简单的表达式语言来处理来自 JSF 上下文的应用程序数据。一收到后续请求,控制器就更新所有模型数据(假设输入了新数据)。JSF 开发人员可以通过编程的方式在应用程序运行期间随时访问整个 JSF 生命周期,从而可以随时对应用程序的行为进行高度控制。

    JavaServer Faces 的用户界面组件

    JavaServer Faces 的真正威力在于它的用户界面组件模型。在该模型中,应用程序完全用组件集合构建,这些组件可以针对多种客户端类型用不同的方式来进行显示。与其他专有技术(如 ASP.Net)有点类似,JSF 的 UI 组件模型技术使开发人员能够使用预先构建的用户界面 (UI) 组件来构建 Web 用户界面(而非完全从头构建用户界面),从而提供了前所未有的开发效率。JSF UI 组件有多种形式,可以简单到只是显示文本的 outputLabel,或者复杂到可以表示来自数据集合(如数据库表)的表格化数据的 dataTable

    JavaServer Faces 规范在其参考实施中提供了一组基本 UI 组件,这些组件本身是非常有用的。它们包括两个组件库,即“HTML”组件库 — 它大部分映射了标准的 HTML 输入元素;以及“核心”库 — 它辅助常见的应用程序开发任务(如,国际化和验证/转换输入数据)。除了提供一个基本 UI 组件库之外,JSF API 还提供了扩展和创建定制 JSF UI 组件的功能,从而在基本组件之上提供更多功能。

    其他用户界面组件库

    由于 JSF API 的丰富性和灵活性,许多 Java 开发人员开始创建新的 JSF 组件库和实现。Oracle 的 ADF Faces 是一个完全符合 JSF 规范的组件库,它为 JSF 应用程序开发提供了一组广泛的增强 UI 组件。这些组件包括针对每种客户端类型的多种呈现器、高级表格、颜色和日期选择器以及大量通用组件(如菜单、命令按钮、转移选择器和进度指示计)。

    图 2:Oracle 的 ADF Faces JSF UI 组件

    除了 Oracle 的 ADF Faces 之外,还有其他新的 JSF 组件库开始从开放源代码社区和软件供应商社区中出现。MyFaces 就是一个新 JSF UI 组件库的例子,它通过 Apache 作为一个开放源代码项目提供的。Myfaces 还是对 JSF 基本 UI 组件的增强,它拥有更广泛的 UI 功能,如集成的 Tiles 支持、支持 Javascript 的菜单和树控件。

    图 3:开放源代码的 MyFaces 实现和 UI 组件库

    JSF UI 组件的可插入呈现技术

    JSF UI 组件技术最引人注目一个方面就是它的可插入呈现功能。JSF UI 组件能够根据查看组件的客户端的类型来以不同方式呈现自身。例如,HTML 浏览器将看到特定 UI 组件的“HTML 浏览器友好”版本,而支持无线或 WAP 的微型设备将看到同一 UI 组件的“WML 友好”版本!JSF 通过解除 UI 组件与其呈现逻辑之间的耦合从而能够为同一 UI 组件创建多个呈现器实现了这一功能。不同的呈现器可以与 UI 组件相关联,在运行时 UI 组件可以根据请求的客户端类型决定使用哪个呈现器。

    图 5:一个 ADF Faces 表格组件针对无线客户端和 HTML 客户端进行了不同的呈现

    还应当指出的是,由于 JSF 的可插入呈现功能,使得 JSF UI 组件能够显示任何类型的数据,无论它是标记数据(如 HTML、XML、WML 等)还是二进制数据。例如,UI 组件还可以显示二进制数据,如图像流或不同的文档类型,如 SVG、PDF 和 Word。

    一个新的 JSF 组件开发人员社区

    随着 JSF 开发人员和拥护者社区的不断壮大,现在有几个网站致力于进一步推动独立的 JSF 开发。JSFCentral 就是一个完全为 JSF 开发社区服务的新网站。它包含 JSF 技术信息、产品/组件信息以及大量与 JSF 相关的文章。

    图 4:JSFCentral — 一个免费的 Javaserver Faces 社区

    (JSFCentral 的地址是:http://jsfcentral.com

    JSF 开发工具

    因为 JavaServer Faces 是一种标准的 Java 技术,因此软件开发工具完全能够为 JavaServer Faces 提供高级的集成开发工具支持。多个供应商现在不同程度地支持 JSF 开发,这大大提高了 JSF 的易用性和功能。Oracle、Sun、Borland 和 IBM 都为 JavaServer Faces 提供了开发环境。由于开发工具供应商在竞相提供更好、更简单和更多的开发环境,因此基于 IDE 的 JSF 开发拥有美好的前景!

    图 6:Oracle 的 JDeveloper 提供高效、可视化的 JSF 开发体验

    总结

    JavaServer Faces 通过提供模型-视图-控制器设计模式的一个简洁实现,同时在不牺牲开发能力和灵活性的前提下提供高效的以组件为中心的开发,解决了 Java Web 开发的许多历史问题。此外,因为 JSF 是一种 Java 标准,因此多个软件供应商将继续提供始终高效的开发环境,这些开发环境毫无疑问将达到或很可能超过专有的可视化开发环境。请继续关注!

    什么是 JSF?

    JavaServer Faces (JSF) 是一种用于构建 Web 应用程序的新标准 Java 框架。它提供了一种以组件为中心来开发 Java Web 用户界面的方法,从而简化了开发。JavaServer Faces 还引起了广大 Java/Web 开发人员的兴趣。“企业开发人员”和 Web 设计人员将发现 JSF 开发可以简单到只需将用户界面 (UI) 组件拖放到页面上,而“系统开发人员”将发现丰富而强健的 JSF API 为他们提供了无与伦比的功能和编程灵活性。JSF 还通过将良好构建的模型-视图-控制器 (MVC) 设计模式集成到它的体系结构中,确保了应用程序具有更高的可维护性。最后,由于 JSF 是通过 Java Community Process (JCP) 开发的一种 Java 标准,因此开发工具供应商完全能够为 JavaServer Faces 提供易于使用的、高效的可视化开发环境。

    JSF 体系结构

    JavaServer Faces 的 MVC 实现

    JSF 的主要优势之一就是它既是 Java Web 用户界面标准又是严格遵循模型-视图-控制器 (MVC) 设计模式的框架。用户界面代码(视图)与应用程序数据和逻辑(模型)的清晰分离使 JSF 应用程序更易于管理。为了准备提供页面对应用程序数据访问的 JSF 上下文和防止对页面未授权或不正确的访问,所有与应用程序的用户交互均由一个前端“Faces”servlet(控制器)来处理。

    图 1:JavaServer Faces 的 MVC 实现

    JSF 生命周期

    Faces Controller servlet 充当用户和 JSF 应用程序之间的纽带。它在明确限定的 JSF 生命周期(规定了用户请求之间的整个事件流)的范围内工作。例如,一收到访问 JSF 应用程序的初始 Web 请求,Faces Controller servlet 便通过首先准备 JSF 上下文(存放所有应用程序数据的一个 Java 对象)来处理请求。然后控制器把用户指引到所请求的页面。该页面通常使用简单的表达式语言来处理来自 JSF 上下文的应用程序数据。一收到后续请求,控制器就更新所有模型数据(假设输入了新数据)。JSF 开发人员可以通过编程的方式在应用程序运行期间随时访问整个 JSF 生命周期,从而可以随时对应用程序的行为进行高度控制。

    JavaServer Faces 的用户界面组件

    JavaServer Faces 的真正威力在于它的用户界面组件模型。在该模型中,应用程序完全用组件集合构建,这些组件可以针对多种客户端类型用不同的方式来进行显示。与其他专有技术(如 ASP.Net)有点类似,JSF 的 UI 组件模型技术使开发人员能够使用预先构建的用户界面 (UI) 组件来构建 Web 用户界面(而非完全从头构建用户界面),从而提供了前所未有的开发效率。JSF UI 组件有多种形式,可以简单到只是显示文本的 outputLabel,或者复杂到可以表示来自数据集合(如数据库表)的表格化数据的 dataTable

    JavaServer Faces 规范在其参考实施中提供了一组基本 UI 组件,这些组件本身是非常有用的。它们包括两个组件库,即“HTML”组件库 — 它大部分映射了标准的 HTML 输入元素;以及“核心”库 — 它辅助常见的应用程序开发任务(如,国际化和验证/转换输入数据)。除了提供一个基本 UI 组件库之外,JSF API 还提供了扩展和创建定制 JSF UI 组件的功能,从而在基本组件之上提供更多功能。

    其他用户界面组件库

    由于 JSF API 的丰富性和灵活性,许多 Java 开发人员开始创建新的 JSF 组件库和实现。Oracle 的 ADF Faces 是一个完全符合 JSF 规范的组件库,它为 JSF 应用程序开发提供了一组广泛的增强 UI 组件。这些组件包括针对每种客户端类型的多种呈现器、高级表格、颜色和日期选择器以及大量通用组件(如菜单、命令按钮、转移选择器和进度指示计)。

    图 2:Oracle 的 ADF Faces JSF UI 组件

    除了 Oracle 的 ADF Faces 之外,还有其他新的 JSF 组件库开始从开放源代码社区和软件供应商社区中出现。MyFaces 就是一个新 JSF UI 组件库的例子,它通过 Apache 作为一个开放源代码项目提供的。Myfaces 还是对 JSF 基本 UI 组件的增强,它拥有更广泛的 UI 功能,如集成的 Tiles 支持、支持 Javascript 的菜单和树控件。

    图 3:开放源代码的 MyFaces 实现和 UI 组件库

    JSF UI 组件的可插入呈现技术

    JSF UI 组件技术最引人注目一个方面就是它的可插入呈现功能。JSF UI 组件能够根据查看组件的客户端的类型来以不同方式呈现自身。例如,HTML 浏览器将看到特定 UI 组件的“HTML 浏览器友好”版本,而支持无线或 WAP 的微型设备将看到同一 UI 组件的“WML 友好”版本!JSF 通过解除 UI 组件与其呈现逻辑之间的耦合从而能够为同一 UI 组件创建多个呈现器实现了这一功能。不同的呈现器可以与 UI 组件相关联,在运行时 UI 组件可以根据请求的客户端类型决定使用哪个呈现器。

    图 5:一个 ADF Faces 表格组件针对无线客户端和 HTML 客户端进行了不同的呈现

    还应当指出的是,由于 JSF 的可插入呈现功能,使得 JSF UI 组件能够显示任何类型的数据,无论它是标记数据(如 HTML、XML、WML 等)还是二进制数据。例如,UI 组件还可以显示二进制数据,如图像流或不同的文档类型,如 SVG、PDF 和 Word。

    一个新的 JSF 组件开发人员社区

    随着 JSF 开发人员和拥护者社区的不断壮大,现在有几个网站致力于进一步推动独立的 JSF 开发。JSFCentral 就是一个完全为 JSF 开发社区服务的新网站。它包含 JSF 技术信息、产品/组件信息以及大量与 JSF 相关的文章。

    图 4:JSFCentral — 一个免费的 Javaserver Faces 社区

    (JSFCentral 的地址是:http://jsfcentral.com

    JSF 开发工具

    因为 JavaServer Faces 是一种标准的 Java 技术,因此软件开发工具完全能够为 JavaServer Faces 提供高级的集成开发工具支持。多个供应商现在不同程度地支持 JSF 开发,这大大提高了 JSF 的易用性和功能。Oracle、Sun、Borland 和 IBM 都为 JavaServer Faces 提供了开发环境。由于开发工具供应商在竞相提供更好、更简单和更多的开发环境,因此基于 IDE 的 JSF 开发拥有美好的前景!

    图 6:Oracle 的 JDeveloper 提供高效、可视化的 JSF 开发体验

    总结

    JavaServer Faces 通过提供模型-视图-控制器设计模式的一个简洁实现,同时在不牺牲开发能力和灵活性的前提下提供高效的以组件为中心的开发,解决了 Java Web 开发的许多历史问题。此外,因为 JSF 是一种 Java 标准,因此多个软件供应商将继续提供始终高效的开发环境,这些开发环境毫无疑问将达到或很可能超过专有的可视化开发环境。请继续关注!

    什么是 JSF?

    JavaServer Faces (JSF) 是一种用于构建 Web 应用程序的新标准 Java 框架。它提供了一种以组件为中心来开发 Java Web 用户界面的方法,从而简化了开发。JavaServer Faces 还引起了广大 Java/Web 开发人员的兴趣。“企业开发人员”和 Web 设计人员将发现 JSF 开发可以简单到只需将用户界面 (UI) 组件拖放到页面上,而“系统开发人员”将发现丰富而强健的 JSF API 为他们提供了无与伦比的功能和编程灵活性。JSF 还通过将良好构建的模型-视图-控制器 (MVC) 设计模式集成到它的体系结构中,确保了应用程序具有更高的可维护性。最后,由于 JSF 是通过 Java Community Process (JCP) 开发的一种 Java 标准,因此开发工具供应商完全能够为 JavaServer Faces 提供易于使用的、高效的可视化开发环境。

    JSF 体系结构

    JavaServer Faces 的 MVC 实现

    JSF 的主要优势之一就是它既是 Java Web 用户界面标准又是严格遵循模型-视图-控制器 (MVC) 设计模式的框架。用户界面代码(视图)与应用程序数据和逻辑(模型)的清晰分离使 JSF 应用程序更易于管理。为了准备提供页面对应用程序数据访问的 JSF 上下文和防止对页面未授权或不正确的访问,所有与应用程序的用户交互均由一个前端“Faces”servlet(控制器)来处理。

    图 1:JavaServer Faces 的 MVC 实现

    JSF 生命周期

    Faces Controller servlet 充当用户和 JSF 应用程序之间的纽带。它在明确限定的 JSF 生命周期(规定了用户请求之间的整个事件流)的范围内工作。例如,一收到访问 JSF 应用程序的初始 Web 请求,Faces Controller servlet 便通过首先准备 JSF 上下文(存放所有应用程序数据的一个 Java 对象)来处理请求。然后控制器把用户指引到所请求的页面。该页面通常使用简单的表达式语言来处理来自 JSF 上下文的应用程序数据。一收到后续请求,控制器就更新所有模型数据(假设输入了新数据)。JSF 开发人员可以通过编程的方式在应用程序运行期间随时访问整个 JSF 生命周期,从而可以随时对应用程序的行为进行高度控制。

    JavaServer Faces 的用户界面组件

    JavaServer Faces 的真正威力在于它的用户界面组件模型。在该模型中,应用程序完全用组件集合构建,这些组件可以针对多种客户端类型用不同的方式来进行显示。与其他专有技术(如 ASP.Net)有点类似,JSF 的 UI 组件模型技术使开发人员能够使用预先构建的用户界面 (UI) 组件来构建 Web 用户界面(而非完全从头构建用户界面),从而提供了前所未有的开发效率。JSF UI 组件有多种形式,可以简单到只是显示文本的 outputLabel,或者复杂到可以表示来自数据集合(如数据库表)的表格化数据的 dataTable

    JavaServer Faces 规范在其参考实施中提供了一组基本 UI 组件,这些组件本身是非常有用的。它们包括两个组件库,即“HTML”组件库 — 它大部分映射了标准的 HTML 输入元素;以及“核心”库 — 它辅助常见的应用程序开发任务(如,国际化和验证/转换输入数据)。除了提供一个基本 UI 组件库之外,JSF API 还提供了扩展和创建定制 JSF UI 组件的功能,从而在基本组件之上提供更多功能。

    其他用户界面组件库

    由于 JSF API 的丰富性和灵活性,许多 Java 开发人员开始创建新的 JSF 组件库和实现。Oracle 的 ADF Faces 是一个完全符合 JSF 规范的组件库,它为 JSF 应用程序开发提供了一组广泛的增强 UI 组件。这些组件包括针对每种客户端类型的多种呈现器、高级表格、颜色和日期选择器以及大量通用组件(如菜单、命令按钮、转移选择器和进度指示计)。

    图 2:Oracle 的 ADF Faces JSF UI 组件

    除了 Oracle 的 ADF Faces 之外,还有其他新的 JSF 组件库开始从开放源代码社区和软件供应商社区中出现。MyFaces 就是一个新 JSF UI 组件库的例子,它通过 Apache 作为一个开放源代码项目提供的。Myfaces 还是对 JSF 基本 UI 组件的增强,它拥有更广泛的 UI 功能,如集成的 Tiles 支持、支持 Javascript 的菜单和树控件。

    图 3:开放源代码的 MyFaces 实现和 UI 组件库

    JSF UI 组件的可插入呈现技术

    JSF UI 组件技术最引人注目一个方面就是它的可插入呈现功能。JSF UI 组件能够根据查看组件的客户端的类型来以不同方式呈现自身。例如,HTML 浏览器将看到特定 UI 组件的“HTML 浏览器友好”版本,而支持无线或 WAP 的微型设备将看到同一 UI 组件的“WML 友好”版本!JSF 通过解除 UI 组件与其呈现逻辑之间的耦合从而能够为同一 UI 组件创建多个呈现器实现了这一功能。不同的呈现器可以与 UI 组件相关联,在运行时 UI 组件可以根据请求的客户端类型决定使用哪个呈现器。

    图 5:一个 ADF Faces 表格组件针对无线客户端和 HTML 客户端进行了不同的呈现

    还应当指出的是,由于 JSF 的可插入呈现功能,使得 JSF UI 组件能够显示任何类型的数据,无论它是标记数据(如 HTML、XML、WML 等)还是二进制数据。例如,UI 组件还可以显示二进制数据,如图像流或不同的文档类型,如 SVG、PDF 和 Word。

    一个新的 JSF 组件开发人员社区

    随着 JSF 开发人员和拥护者社区的不断壮大,现在有几个网站致力于进一步推动独立的 JSF 开发。JSFCentral 就是一个完全为 JSF 开发社区服务的新网站。它包含 JSF 技术信息、产品/组件信息以及大量与 JSF 相关的文章。

    图 4:JSFCentral — 一个免费的 Javaserver Faces 社区

    (JSFCentral 的地址是:http://jsfcentral.com

    JSF 开发工具

    因为 JavaServer Faces 是一种标准的 Java 技术,因此软件开发工具完全能够为 JavaServer Faces 提供高级的集成开发工具支持。多个供应商现在不同程度地支持 JSF 开发,这大大提高了 JSF 的易用性和功能。Oracle、Sun、Borland 和 IBM 都为 JavaServer Faces 提供了开发环境。由于开发工具供应商在竞相提供更好、更简单和更多的开发环境,因此基于 IDE 的 JSF 开发拥有美好的前景!

    图 6:Oracle 的 JDeveloper 提供高效、可视化的 JSF 开发体验

    总结

    JavaServer Faces 通过提供模型-视图-控制器设计模式的一个简洁实现,同时在不牺牲开发能力和灵活性的前提下提供高效的以组件为中心的开发,解决了 Java Web 开发的许多历史问题。此外,因为 JSF 是一种 Java 标准,因此多个软件供应商将继续提供始终高效的开发环境,这些开发环境毫无疑问将达到或很可能超过专有的可视化开发环境。请继续关注!

    17 juin

    WAP 手机及开发技术调研

    1描述
    WAP(无线通讯协议)是在数字移动电话、因特网或其他个人数字助理机(PDA)、计算机应用之间进行通讯的开放全球标准。这一标准的诞生是WAP论坛成员努力的结果,WAP论坛是在1997年6月,由诺基亚、爱立信、摩托罗拉和无线星球(Unwired Planet)就共同组成的。WAP的目标就是通过WAP这种技术,就可以将Internet的大量信息及各种各样的业务引入到移动电话、PALM等无线终端之中。无论你在何地、何时只要你需要信息,你就可以打开你的WAP手机,享受无穷无尽的网上信息或者网上资源。如:综合新闻、天气预报、股市动态、商业报道、当前汇率等。电子商务、网上银行也将逐一实现。
    随着移动商务的兴起,对移动数据传输的需求越来越迫切,一些大的设备制造商试图把WAP 1.x推向市场,作为从服务器向移动设备传送信息的标准方式。但是,WAP 1.x协议在很大程度上基于Internet技术,开发WAP 1.x的动因在于把Internet技术应用至无线网络的传送载体和设备。由于Internet本身的局限性,致使WAP 1.x存在着效率低、传送内容受限制等缺陷,因而越来越不受业界欢迎。这种情况下WAP 2.0应运而生。
           2001年8月,WAP论坛公布了WAP2.0版本。WAP2.0在WAP1.x的基础上做了很大的改进,对WAP协议的结构作了重大变革,采用了一些最新的标准和协议,以适应无线环境的变化和预期的市场需求。同时还定义了很多新的业务和应用。随着移动运营商移动数据网络带宽的不断增大以及用户移动数据消费习惯的养成,这些新业务和新应用也具备了推出的基本条件。可以预计WAP2.0将大大推动移动互联网的发展
    2市场应用
    其实每个人一天当中空当的时间很多,等车、等人、等开会、等上菜……这些片段的时间也许只是几分钟,让你来不及去一趟银行、来不及打开笔记本电脑(还要等一段漫长的开机时间),有时也受限于环境因素,让你无法随身带一本杂志、带一份报纸去打发时间。这时候,我发现无线上网真的蛮好。只要打开WAP手机(手机一定会随身携带嘛),按几个钮,就可以看新闻、查今日股价、线上下单、银行转账,不用出门、不用开电脑、不用讲话,事情就办妥当。
    大部分在互联网上成功的互动服务可望在WAP世界中进行,例如信息服务,新闻、报价、线上购物、互动游戏和广告等等;WAP也同样可用于企业内部应用,如公司电话指南,或使在办公室以外的人员索取数据或资料;无线接入还应带来其它机会,如与位置有关的服务或复杂的电话应用,比如,渡假人士可以从手机上找到合适的餐馆,随即自动致电订位。
    3基于WAP2.0的移动互联网业务
    移动浏览业务(Mobile Browsing)
    随着移动运营商2.5G甚至是3G网络的建成并投入商用,大量的内容和业务提供商(CP/SP)迅速崛起以及彩色移动终端的普及率不断提高,使用WAP 方式进行移动浏览的用户数量也在急剧增长。据法国ORANGE电信公司统计从2002年5月至同年11月6个月的时间里用户使用WAP进行浏览的每个月的平均时间增长了130%。同时每用户每月平均数据业务使用量达到1Mb/月。In-Stat 集团预测到2004年WAP用户将超过2亿;而著名的Strategy Analytics也预测到2006使用WAP移动浏览器的用户将占到总移动用户数的65%。对于移动浏览而言怎样才能为用户提供快捷、方便和有趣的内容体验是最为重要也是最为关键的。使用WAP2.0能够实现多种形式的内容体验:内容检索、多媒体消息、下载甚至是在线流媒体。由此也就产生了大量受用户欢迎尤其是年轻用户欢迎的和旋铃音下载、屏保/壁纸下载、JAVA应用和在线音视频欣赏等。
    同时WAP2.0特有的直接HTTP通信、移动友好技术、标记语言XHTMLMP以及对WML1.0的完全向后兼容等技术也使得WAP2.0能有更好的图形展现及控制能力;更容易针对不同的终端做出相应的内容优化;能够无线传送流媒体;使用缓存,业务处理速度更快;对大型文件的下载也更加迅速。
    2、WAP PUSH业务
    以往移动用户都是采用PULL(点播)方式来获取他们所需要的无线数据内容。然而对于那些信息更新速度快、信息产生频度高而且用户需求相对较为稳定的无线数据内容而言,再采用PULL方式无论对于用户还是内容提供商来说都过于烦琐和浪费资源。现在采用WAP PUSH技术即可方便地实现相关内容的及时传送和用户的快捷获取(single click to wap content)。WAP PUSH技术可以把多种媒体格式的数据整合为一个完整的WAP应用,从而产生了MMS等新的消息模式。对于移动用户而言,他们可以订购他们所感兴趣的内容也可以收到那些直接由内容提供商“推送”下来的有价值的消息(例如促销或打折信息),从而进一步养成移动数据消费习惯。同时对于内容提供商或公司而言他们可以把那些重要的或用户感兴趣的信息第一时间就推送给用户,从最大程度上避免了由于时间过长而导致无效信息的产生。
    例如对于股民来说,通过PUSH技术那些实时变化的股票信息(股价、成交量、公告消息等)可以实时地传送到移动用户的终端上并被用户及时浏览。一般来说对于两类消息都可以采用PUSH方式来进行传送。定期出现但随时间而变化的信息,例如:每天早晨7:30的天气预报和交通路况通报;每星期天晚上的“开心一笑”;每月一次的新片预告等。不定期出现但内容每次都不一样的信息-例如:最后一分钟打折的飞机票或电影票的票价;“我最喜爱的零售店”的促销信息通知,当然这条消息可以以电子折扣券的形式推送到用户的移动终端上;足球比赛的最终比赛结果等。
    目前在一些移动互联网较为发达的国家WAP PUSH 已经被应用在一些新的领域。
    社团服务- 例如:预约服务:当搜索信息得到匹配时将直接把对方的信息PUSH给用户,当需要更多信息时甚至可以与对方进行URL链接;公告栏:当有新用户加入或有用户进行基本信息更改时把公告PUSH给用户;家庭购物清单:为家庭成员提供及时更新的购物确认通知;会员服务:最新上市的商品信息通知及促销信息通知;足球俱乐部:赛事预告、比赛结果、本场最佳球员等。
    拍卖服务 - 例如:其他人的竞价消息通知;中标通知;拍卖原则通知(如起拍价、每次递增价等)等。
    航空俱乐部(主要针对航空旅客)- 例如:航班延迟通知;登机通知;里程累计可获取某地免费旅行的通知;目的地机场的外汇兑换率;到达欢迎信息和入城大巴乘坐地点通知等。
    另外WAP PUSH业务也正在被更多地应用于E-MAIL到达通知、集团信息通知以及和定位技术结合后基于位置的PUSH业务。

    移动商务应用
    由于WAP2.0具备多媒体和PUSH的特性,同时现有带WAP浏览器的彩色移动终端普及率不断提高,WAP在移动商务中的应用也越来越多。在这其中尤其以移动折扣券(Mobile coupon)的应用最有代表意义。目前移动折扣券的应用每年增长200%,而且它直接带动了整个移动商务的迅速发展。从最初的发送商品条形码到现在直接发送多媒体信息内容,WAP技术功不可没。韩国移动运营商KTF已经和上百家国内外著名的供应商和连锁店联手进行了移动折扣券的合作。这其中包括TGIF, Wal-Mart等著名的大型零售百货商。用户可以方便地下载或直接收到零售商推送来的移动折扣券,使用这些折扣券将能享受到各种各样的商品优惠及打折服务。KTF已经将移动折扣券应用于6个领域:货运、音像/书籍、电影票/戏票、服装、演唱会/体育比赛售票、会员服务等。移动折扣券一方面为用户提供了实实在在的优惠以提高用户满意度。
    另一方面用户或许通过回答一些简单的问题才可以获得这些折扣券。这在无形当中也为商家收集了大量珍贵的用户资料。同时通过WAP PUSH方式把企业的徽标、商品图案、简短的企业动画等多媒体信息推送给用户,又借助了这种移动的“第五媒体”宣传提升了企业或是商品的形象。
    另外由于WAP2.0采用了WTLS(Wireless Transport Layer Security)无线传送层安全技术和WIM(Wireless Identity Module)无线身份识别模块技术。使得其支持多种鉴权方式(匿名访问、客户端鉴权和服务器端鉴权)、安全会话控制和数字签名等多种安全措施,比较WAP1.x能够提供更为完善和有效的端到端的安全机制。因此在认证支付、银行交易、搏彩、移动购票、移动拍卖和股票交易等多个领域都有着越来越多的应用。
    4上网方式
    GSM、GPRS、EDGE、CDMA和3GPP2 cdma2000 1X,3GPP W-CDMA

    5理论上网速度
    GSM(9.6Kbps)、GPRS(2.5G技术168Kbps)、EDGE(384Kbps)
    CDMA2000(284Kbps or 144Kbps、视不同厂商),W-CDMA(3G技术)
    6硬件要求
    支持WAP的手机就可以叫做wap手机
        手机功能价格
    7  原理
    WAP是Wireless Application Protocol(即无线应用协议)的缩写。 这是一个使用户借助无线手持设备,如掌上电脑,手机,呼机,双向广播,智能电话等,获取信息的安全标准。 WAP支持绝大多数无线网络,包括GSM, CDMA, CDPD, PDC, PHS, TDMA, FLEX, ReFLEX, iDen, TETEA, DECT, DataTAC, 和Mobitex。 所有操作系统都支持WAP,其中专门为手持设备设计的有PalmOS, EPOC, Windows CE, FLEXOS, OS/9, 及JavaOS。 一些手持设备,如掌上电脑,安装微型浏览器后,可借助WAP接入Internet。 微型浏览器文件很小,可较好的解决手持设备内存小和无线网络带宽不宽的限制。 虽然WAP能支持HTHL和XML,但WML才是专门为小屏幕和无键盘手持设备 服务的语言。WAP也支持WMLScript。这种脚本语言类似与JavaScript,但 对内存和CPU的要求更低,因为它基本上没有其他脚本语言所包含的无用功能
    WAP设计模型有点象WWW的设计模型.它给应用程序开发人员提供了很多 方便,包括一个熟悉的设计模型,一个 已证明的体系机构,和使用现有工具(如网络服务器,XML工 具等)的能力.为了与无线的环境相匹配进行了优化和扩 充.无论再哪里,只要有可能,现有的标 准都会被作为工作
    分析程序的起点来使用.

    WAP程序设计模型
    WAP被列入一组基于熟悉的WWW的众所周知的内容开本.内容通过一组基于WWW通讯协议的通讯 协议来传送.接线端 的小型浏览器可调整界面,且类似标准的网络浏览器. WAP定义了一组能促进流动终端和网络服务器之间的传达的标准元件.包括:
    ------标准命名模型: 利用WWW来识别起点服务器上的工作分析程序的内容,识别装置上的局 部, 命令控制功能.
    ------内容的键入: WAP内容拥有与WWW键入一致的特殊形式,这允许WAP用户代理 在其形式 的基础上进行正确的 处理.
    ------标准内容开本: WAP基于WWW技术上,包括了显示涨价幅度,日历信息,电子名片图象和脚 本语言.
    ------标准通信协议: WAP通信协议促进了从流动终端到网络服务器的传达要求.为了大规模的 市场,无线手柄装 置,WAP内容和协议已经过优化
    .WAP利用代理技术连接WWW和无线领域.
    WAP规范主要定义了以下几种组件:
      1. WAP编程模型:这个模型在很大程度上利用了现有的WWW编程模型,这样可以给应用开发人员带来许多好处,可以最大限度地利用他们原来掌握的经验和各种开发工具。WAP编程模型还针对无线环境的通信特点对原有的WWW编程模型进行了优化和扩展。
      2. 无线标记语言(WML):遵守XML标准的WML特别适合于在性能方面严重受限的手持设备。WML和WML Script并不要求用户使用传统的PC机键盘或鼠标进行输入,而且它设计时就考虑到了手机的屏幕尺寸限制。WML将页面文件分割成一套用户交互操作单元,一个交互操作单元被称为一个卡,用户在进行Internet访问时需要在一个或多个WML文件产生的各个卡之间来回导航。使用WAP网关,所有的WML内容都可以通过Internet使用HTTP 1.1请求进行访问,因此传统的Web服务器、工具和技术可以继续使用。

      3.  
    微浏览器规范:这个规范与标准的Web浏览器规范类似,它定义了一个适合于手持设备的功能强大的用户接口模型。这个规范定义手机如何解释WML和WMLScript并且显示给用户。
      用户通过上移键和下移键而不是鼠标在各个卡之间来回进行导航。为了保持与标准浏览器的一致,微浏览器还提供了各种导航功能如Back、Home、书签等。微浏览器允许具有较大屏幕和更多特性的设备自动显示更多的内容,就像传统的浏览器当浏览窗口扩大时能显示更多的信息一样。

      4.轻量级协议栈:这个协议栈将无线手机访问Internet的带宽需求降到最低,保证了各种无线网络都可以使用WAP规范。
      通过使用WAP协议栈可以节省大量的无线带宽。要完成同样一个访问操作,使用WAP协议栈涉及到的包数量不到使用全标准的HTTP/TCP/IP协议栈的一半,这对于带宽严重受限的无线网络来讲无疑是十分有用的。

      5.无线电话应用(WTA)框架:它允许无线手机访问各种电话功能如呼叫控制和来自WML Script applet中的信息。这允许商家开发各种电话应用并且将其集成到WML/WML Script服务中。如呼叫转移这样的服务,商家可以提供一个用户接口,提醒用户是准备接受呼叫、转移到他处还是将其转发成一个语音邮件。

      6.WAP网关:WAP规范使用标准的Web代理技术来将无线网络与Web连接起来。通过将处理功能集中在WAP网关中,WAP结构大大减少了手机上的操作负载,因此为手机实现价廉物美提供了基础。如,一个WAP网关一般可以使用所有的DNS服务来解析URL中使用的域名,因此就不再需要手机来完成这个计算任务。还可以利用WAP网关来为用户提供各种服务并且可以帮助网络服务商防止诈骗和服务利用。
      一个WAP网关一般包括以下功能:
      ①协议网关:协议网关将来自WAP协议栈的请求翻译到WWW协议栈(HTTP和TCP/IP)中;
      ②内容编码器和解码器:内容编码器将Web内容翻译成紧密编码的格式,以减少通过无线数据网络传输的数据包的大小和数量。
    8开发环境
    Wap可以在Windows系列,linux,unix等系统上进行开发
    编辑工具:
           Waptor工具(DotWap工具、WAP Page)
    图形工具:
           WAP Pictures工具,WAPDraw工具
    模拟器
          Openwave模拟器,Nokia Mobile Internet Toolkit,UP模拟器
    它可以和ASP、PHP、Perl、JSP/Java Servlet等结合使用
    9优缺点
    WAP对服务提供商的好处 :
    服务提供商可以通过在无线网络中WAP方案在话音服务的基础上增加新的服务。允许通过手机访问Web内容只是使用WAP的一种最基本的好处。由于可以通过使用WAP可视化接口为手机增加新的特性并且减少操作成本,服务商将可以通过改进服务增加自己的竞争力。 通过在无线数据网络中部署WAP方案,网络操作者将可以实现以下功能。 1.与用户之间产生一种全新的通信方式。服务提供商现在可以使用虚拟接口来与他们的用户保持接触并为其提供新的服务。这为改进客户服务并且让更多的用户可以享受到这些服务提供了新的机遇。
    2.控制与用户的数据连接。通过使用基于WAP的方案,服务提供商可以像他们现在管理话音服务一样通过WAP网关来对手机进行Internet访问服务的跟踪和计费、进行特性控制等。
    3.很容易的部署电信服务应用,如呼叫特性控制、预付费无线服务和自动化客户服务等。既然应用是存储在服务提供商的标准Web服务器上,当增加新的服务或特性发生变化时,都可以立即通知到网络上的每一个用户。
    4.访问所有的WAP无线内容。既然WAP是一个许多开发者都共同使用的规范,服务提供商将可以获得大量的可用内容。
    5.自由选择各厂商的产品。服务提供商可以从一个厂商那里购买他们的WAP网关,而使用来自其他厂商的WAP手机。这种竞争有利于各个厂商不断提高自己的产品性能价格比,并且促使厂商不断为手机提供新的特性和服务。
    6.自由使用和集成新的无线接口技术。既然WAP是一个开放的规范,服务提供商不必担心在增加或修改无线接口时会破坏原来的无线Internet服务方案。
    WAP对手机制造商的好处 :
    将微浏览器集成到手机中允许手机制造商满足如今服务提供商希望不断改进服务的要求。通过提供一个基于WAP的方案,手机制造商可以: 1.以低成本将微浏览器集成到手机中,因为WAP规范在设计时就考虑到微浏览器只需要较小的内存或较低速的CPU就可以运行,以减少对手机成本的影响。
    2.提供一个在所有的WAP服务器上及所有提供WAP服务的网络上工作的微浏览器并因此增加手机对用户的吸引力。 WAP对开发者的好处 因为WML是一个通用的工业标准,应用开发者使用它开发的应用可以被尽可能多的用户访问和使用。
    对开发者也有很多好处。
    1.开辟了一个全新而且极具发展潜力的应用领域。
    2..因为WML是一个基于XML的语言,现在的Web开发人员很容易学习和掌握它。
    3. 统一内容服务技术是未来Web服务的发展方向,WML是这种技术的一个不可分割的部分。应用开发者使用现在的WML是很值得的,因为它代表了未来的发展方向。
    4..使用WML开发的应用可以在支持WAP的任何网络和设备上使用,WML和WAP规范真正实现了“编写一次,到处运行”的愿望。
    5.WML为应用开发者提供了充分利用用户接口的好处。应用可以提供软键盘供用户进行输入并且在手机有限的屏幕上实现最佳的显示效果
    6..WML允许应用开发者将开发的应用与设备的网络电话功能集成起来。这样就可以真正利用话音和数据设备集成带来的好处。
    7.WML既允许使用图标,也允许在支持图像显示的设备中使用图形。如果一个手机不支持图像显示,那么可以只显示文本。因此不管手机是否支持图像功能,使用WML开发的应用都可以同样好的工作。
    8.一个用WML编写的应用将可以在任何兼容WAP的设备上很好的显示。如果一个设备比另一个设备具有更大的显示屏,那么微浏览器将自动显示更多的内容。

    WAP对用户的好处 :
    用户是WAP规范最终的受益者。WAP规范是由那些不仅理解有关的技术而且了解实际的用户需求的电信专家们开发的,因此WAP规范十分注意为最终的手机用户着想。用户通过WAP可以享受到的好处包括:
    1.通过无线手机能够更快更有效的访问Internet信息;
    2.WAP的用户接口非常易于使用,而且能够满足用户在资源受限的无线网络和设备中使用的要求;
    3.广泛的设备选择,除了具有不同特性和外形的手机外,用户还能够使用支持WAP的各种PDA和寻呼机;
    4.大量的应用选择,由于WAP将被服务提供商、手机制造商和应用开发者广泛采用,因此用户将可以很快得到大量的WAP应用服务。
    WAP的缺点
    首先,移动电话用户对WAP业务的模糊认识。到目前为止,我国手机用户已超过4300万,但绝大多数并不是很清楚通过WAP业务,究竟可享受到哪些服务。这可能是受制于传统思想意识的影响,所以大部分人获取信息的习惯手段仍是报纸、电视、电话等传统的媒体。
    其次,从技术角度来说,
    无线数据网络有如下不足: a. 低带宽,b. 更高的隐蔽行, c. 较少的联系稳定行 , d. 较低的可预测的获得性。 随着带宽的增加,手机能量消耗也会增加,这样就使移动通信器件中有限的电池寿命负荷更重。
    手持配件有如下不足: a. 不甚强大的CPU(主机), b. 较小的内存(ROM和RAM), c. 能量消耗受到严格限制, d. 较小的显示屏 ,e. 不同的输入设备(例如:电话按键盘,声音输入器等)
      最后,最关键的问题,就是为WAP手机用户提供无线互联网增值服务的内容不能令人满意。目前,从事WAP手机增值服务的内容服务商少之又少,仅有Linktone.com、byair.com、any8.com、 wapdm.com、wap.sina.com等少数几个网站,网站服务的内容也仅局限于新闻、股票的行情等方面的内容。笔者曾访问过几个网站,感到“做秀”的太多,真正有实用价值的太少。最让笔者感到哭笑不得的是:某网站所推出的所谓“搜索引擎”,实际上只是该网站的网页制作者根据自己的主观判断,随意将目前中国的几个WAP网站罗列出来,作为用户的搜索结果。比如说,当你输入关键字“天气预报”时,你会得到几个提供天气预报的无线网站。但实际上,罗列出来的网站,有的的根本不具备天气预报这一项服务。更离奇的是,有的无线网站虽已大张旗鼓地宣传,但尚未开通,当然更谈不上服务了。
    10前景分析
    人们不由得想起2000年曾在全球热闹了一阵子的“WAP”业务。然而,功能欠佳、时常掉线以及缺乏吸引力的内容使“WAP”业务成为了通信市场的一个败笔。商家们预期的移动上网、电子商务并未出现预期的盛况。出人意料的是,“短消息”成为唯一有利润的业务。
    对于人们心中 GPRS 会不会取代 WAP 的疑问,有关专家告诉记者,GPRS不会取代WAP,两者属于不同范畴。GPRS和现在的CSD(电路交换数据)方式的GSM数据业务都是马路,WAP则是马路上的汽车,现在行驶在两车道上,GPRS提高了数据传送速度,是8车道。可以说,GPRS增强了WAP业务,现有WAP上的内容一样可以通过GPRS进行浏览和应用。所以,从所提供的服务范围上来看,GPRS技术使WAP有了更大的发挥空间。
    手机下载市场前景诱人
      位于美国波士顿的全球知名电信咨询公司“金字塔调查研究公司”最新调查数字显示,亚洲手机下载市场已发展为年产值13亿美元的新兴产业。亚洲手机下载市场迅速发展的主要原因是该地区手机用户越来越多,手机可下载的内容越来越丰富,技术越来越方便快捷。
    目前,国内提供手机下载服务的有两种方式:一种为移动通信运营商与内容提供商合作,通过移动运营商提供的表单格式为手机用户提供下载服务,大部分下载服务以此为主;另一种为独立的内容服务商通过WAP网站直接为手机用户提供下载服务,此类内容服务商数量极少。
    在目前的预付费用户中,只有动感地带用户能够实现WAP方式下载手机资源,而联通网络中,目前只有CDMA用户能够实现WAP方式下载,网络支持问题也成为手机下载市场发展的一个瓶颈。
    手机银行前景展望
    手机银行的开展将推进移动运营商数据业务的进一步发展:SMS(Short Message Service,短信息服务)是实现无线通信数据业务的重要载体之一,现在也被广泛应用为手机银行业务的通信手段
    而虽然目前WAP(Wireless Application Protocol,无线应用协议)由于安全问题长时间坐在手机银行通信手段的替补席上,但是随着时间的推移和WAP技术的不断完善及成本的逐渐降低,WAP完全有可能支持甚至取代SMS成为移动支付系统的核心载体,移动支付系统也必将促使WAP成为引人注目的移动数据业务并创造巨大的市场价值。
    WAP 2.0虽然是在WAP1.x的基础上作了一些发展和改进。但是由于它采用了最新的标准和协议,对无线环境变化的适应性大大增强。尤其是在今天CDMA1X和GPRS已经大量建成,无线数据网络带宽不断增加、传送速度得到极大提高的情况下,WAP2.0极强的处理能力、对多种内容的传送能力以及对各种新业务的支撑能力就显得尤为重要了。
    当然用户在应用体验过程的满意程度将最终决定WAP 2.0的前景。一般来说,一项技术能否成功走向市场,其决定因素不仅仅是技术本身,而是它能为用户满足需求的程度。WAP技术最早出现时,糟糕的市场表现就是明证。只有众多的内容和服务提供商基于WAP 2.0进一步开发大量的丰富多彩的移动数据应用。用户在使用的过程中能够获得比较满意的用户体验用户才愿意再次使用。而运营商也才能不断扩大运营网络,增加服务内容、提高服务水平。WAP设备制造商和集成商也就能获取稳定的回报和良好的发展前景。由此才能形成一个良性发展的产业价值链,从而进一步推动WAP技术的不断向前发展。
    当前,随着运营商中高速移动数据网的建成,含WAP浏览器的彩色移动终端普及率直线上升,用户已经初步感受到有趣、方便、实用和快捷的用户体验。与此同时设备制造商和内容、业务提供商热情高涨,新应用、新业务层出不穷。国际电联和WAP论坛正在进一步研究WAP2.0的推广应用。我们有理由相信WAP技术必将有着美好的明天。

    应用java技术开发wap应用程序

    我们还是采用Tomcat作为web服务器,如果你对如何使用tomcat还不熟悉请参考相关资料。通常我们开发WAP应用程序的时候都是手写wml脚本,其实我们可以借助java的Servlet/jsp技术开发WAP应用程序。通常我都是使用Lomboz插件在eclipse的环境下写servlet/jsp文件的。先看下面的waptest.jsp文件和WapServlet.java文件

    <?xml version="1.0"?>
    <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
    "http://www.wapforum.org/DTD/wml_1.1.xml">
    <%
    response.setContentType("text/vnd.wap.wml");
    out.println("<wml>");
    out.println("<card title=\"MobileDate\">");
    out.println(" <p align=\"center\">");
    out.println("Date and Time Service<br/>");
    out.println("Date is: "+ new java.util.Date());
    out.println("</p>");
    out.println("</card>");
    out.println("</wml>");
    %>

    package com.j2medev.mingjava;

    import java.io.IOException;
    import java.io.PrintWriter;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;


    public class WapServlet extends HttpServlet
    {

    protected void doGet(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException
    {

    response.setContentType("text/vnd.wap.wml");

    PrintWriter out = response.getWriter();

    out.println("<?xml version=\"1.0\"?>");
    out.println("<!DOCTYPE wml PUBLIC\"-//WAPFORUM//DTD WML 1.1//EN\"");
    out.println("\"http://www.wapforum.org/DTD/wml_1.1.xml\">");
    out.println("<wml>");
    out.println("<card title=\"MobileDate\">");
    out.println(" <p align=\"center\">");
    out.println("Date and Time Service<br/>");
    out.println("Date is: " + new java.util.Date());
    out.println("</p>");
    out.println("</card>");
    out.println("</wml>");

    }

    protected void doPost(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException
    {
    doGet(request,response);
    }
    }

      这两个文件实现的功能是一样的,显示服务器当前的时间。我们的web.xml的内容如下:

    <?xml version="1.0" ?>
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
    <servlet>
    <servlet-name>WapServlet</servlet-name>
    <servlet-calss>com.j2medev.mingjava.WapServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>WapServlet</servlet-name>
    <url-pattern>/wapservlet</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <error-page>
    <error-code>404</error-code>
    <location>/error.jsp</location>
    </error-page>

    </web-app>

      使用Lomboz我们可以很方便的把这个应用程序发布到tomcat的webapps目录,通过WinWap我们可以直接通过下面两个URL访问到他们

    http://localhost:8088/wap/wapservlet
    http://localhost:8088/wap/waptest.jsp

    15 juin

    Hibernate 一对多例

     

    SQL(数据库使用的MySQL):
    CREATE TABLE room (
      ROOM_ID int NOT NULL auto_increment,
      ADDRESS varchar(32) NOT NULL default '',
      PRIMARY KEY  (ROOM_ID)
    ) TYPE=INNODB;
    CREATE TABLE user (
      USER_ID int NOT NULL auto_increment,
      NAME varchar(16) NOT NULL default '',
      ROOM_ID int NOT NULL default '',
      INDEX (ROOM_ID),
      FOREIGN KEY (ROOM_ID) REFERENCES Room(ROOM_ID),
      PRIMARY KEY  (USER_ID)
    ) TYPE=INNODB;

    User.java
    package ivan.hibernate.one2many;
    public class User {
        private long id;
        private String name;
        private Room room;
        ...
    }

    User.hbm.xml
    <hibernate-mapping>
        <class name="ivan.hibernate.one2many.User" table="USER">
            <id name="id" column="USER_ID" unsaved-value="0">
                <generator class="increment"/>
            </id>
            <property name="name">
                <column name="NAME" length="16" not-null="true"/>
            </property>    
            <many-to-one name="room"
                         column="ROOM_ID"
                         class="ivan.hibernate.one2many.Room"/>
        </class>
    </hibernate-mapping>

    Room.java
    package ivan.hibernate.one2many;
    public class Room {
       private long id;
       private String address;
       private Set users = new HashSet();
       ...
    }

    Room.hbm.xml
    <hibernate-mapping>
        <class name="ivan.hibernate.one2many.Room" table="ROOM">
            <id name="id" column="ROOM_ID" unsaved-value="0">
                <generator class="increment"/>
            </id>
            <property name="address" type="string"/>      
            <set name="users" table="USER" inverse="true" cascade="all">
                <key column="ROOM_ID"/>
                <one-to-many class="ivan.hibernate.one2many.User"/>
            </set>
        </class>
    </hibernate-mapping>
    //注意这里需要设定 inverse=true。

    Test.java
    public class Test {
     public static void main(String[] args) throws HibernateException {
            SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
          
            Room room = new Room();
            room.setAddress("China-10-911");      
          
            User user1 = new User();
            user1.setName("ivan");      
          
            User user2 = new User();
            user2.setName("mada");

            user1.setRoom(room);
            user2.setRoom(room);
          
            room.getUsers().add(user1);
            room.getUsers().add(user2);

          
            Session session = sessionFactory.openSession();
            Transaction tx= session.beginTransaction();
            session.save(room);
            tx.commit();
            session.close();

            sessionFactory.close();
        }
    }

    9 juin

    用于模板和组合组件的Facelets

    您是否正在使用JSF?听说过Facelets(它具有与JSF协作良好的、方便的HTML-风格的模板和可重用组合组件)吗?Facelets不是JSF正式规范的组成部分,但它可能对未来的JSF规范产生影响。

      Facelets也可与Apache MyFaces协同使用。对于正在使用JSP和JSTL进行web开发的开发人员来说,JSF和Facelets比起Tapestry之类的东西来说更容易接受。
    虽然Tiles是一个很好的模板框架,但Facelets的模板看起来比Tiles更好。还可以混搭使用JSF、JSTL和常规HTML标签。在创建自定义组件而没有编写java代码的时候,这是很有用的。

      JSF、Facelets和AJAX的加入使得Java环境中的富web应用程序开发成为可能。

    BEA Workshop Studio支持JSF/Facelets,您可以从以下网址下载15天的试用版:
    http://workshopstudio.bea.com/downloadNitroX.do?banner_bea_bea

    Facelets文章:
    http://www.jsfcentral.com/facelets/
    http://hookom.blogspot.com/2005/05/facelets.html
    http://www-128.ibm.com/developerworks/java/library/j-facelets/

    StrutsToFacelets:
    http://wiki.java.net/bin/view/Projects/Struts2Facelets

    JSF与Tapestry:
    http://www.theserverside.com/articles/article.tss?l=JSFTapestry

    Apache MyFaces:
    http://myfaces.apache.org/

    Facelets Project页面:
    http://facelets.dev.java.net/

    Facelets 0.8 发布,在jsf世界中和Tapestry有一拼!

    Facelets 是一个以JavaServer Faces支持作为工业标准的 轻量级的模版框架。任何人就像创建一个jsp页面一样可以使用Facelets 和类似 XML-tag的标签。不同之处在于其强大外表的下面,它去除了所有jsp提供的api带来的负担以更大的增强作为平台的JSF,并提供了简单的可插入式开发,不需要任何JSP标签的开发就能够和JSF整合。

    Facelets 有以下关键的特色:

    • Works with JSF 1.1 and JSF 1.2, including Sun's RI and Apache MyFaces.
    • Zero Tag development time for UIComponents
    • Fast Templating/Decorators for Components and Pages
    • The ability to specify <code>UIComponent</code> trees in separate files (<code>UICompositions</code>)
    • Line/Tag/Attribute precise Error Reporting
    • Specify Tags in Separate Files, even packaged with Jars
    • Full EL support, including Functions
    • Developer-mode for Easy Error resolution
    • Build-time EL Validation
    • XML configuration files aren't necessary
    • Reserves the '<code>jsfc</code>' attribute which acts the same as Tapestry's jwcid (Example: <code><input id="bar" type="text" jsfc="h:inputText" value="#{foo.bar}"/></code>)
    • Plugable Decorators to really make designer's job easy (Example: transform <code><input type="text"/></code> to <code><h:inputText/></code> at compile time)
    • Works with any <code>RenderKit</code>
    • Facelets could be used outside of a Web Container with JSF

      Home Page: http://facelets.dev.java.net

      Documentation: http://facelets.dev.java.net/nonav/docs/dev/docbook.html

      Development Error Pages: http://facelets.dev.java.net/nonav/docs/dev/error.html

    2 juin

    XDoclet 与Hibernate 映射-

    在POJO 中融合XDoclet 的映射文件自动生成机制,提供了除手动编码和由数据库导出
    基础代码的第三种选择。

          XDoclet已经广泛运用在EJB开发中,在其最新版本里,包含了一个为Hibernate提供支
    持的子类库Hibernate Doclet,其中包含了生成Hibernate映射文件所需的ant构建支持以及
    java doc tag支持。
         XDoclet实现基本原理是,通过在Java代码加入特定的JavaDoc tag,从而为其添加特定
    的附加语义,之后通过XDoclet工具对代码中JavaDoc Tag进行分析,自动生成与代码对应
    的配置文件,XDoclet。
        在Hibernate-Doclet中,通过引入Hibernate相关的JavaDoc tag,我们就可以由代码生成
    对应的Hibernate映射文件。
    下面是一个代码片断,演示了Hibernate-Doclet的使用方式:
    /**
    * @hibernate.class
    * table="TUser"
    */
    public class TUser implements Serializable {
    ......
    /**
    * @hibernate.property
    * column="name"
    * length="50"
    * not-null="true"
    *
    * @return String
    */
    public String getName() {
    return this.name;
    }
    ......
    }
    以上是使用Hibernate-Doclet 描述POJO(TUser)及其对应表(TUser)之间映射关系
    的一个例子。

    其中用到了两个hibernate doclet tag,@hibernate.class和@hibernate.property
    这两个tag分别描述了POJO所对应的数据库表信息,以及其字段对应的库表字段信息。
    之后Hibernate Doclet就会根据这些信息生成映射文件:
    <hibernate-mapping>
    <class
    name="net.xiaxin.xdoclet.TUser"
    table="TUser"
    >
    <property
    name="name"
    type="java.lang.String"
    column="name"
    not-null="true"
    length="50"
    >
    </class>
    </hibernate-mapping>
    这样我们只需要维护Java 代码,而无需再手动编写具体的映射文件即可完成Hibernate
    基础代码。

    下面我们就Hibernate Doclet 中常用的Tag 进行探讨,关于Tag 的详细参考,请参见
    XDoclet 的官方指南(http://xdoclet.sourceforge.net/xdoclet/tags/hibernate-tags.html)以及
    Hibernate Reference(http://www.hibernate.org)。

    常用Hibernate-Doclet Tag介绍:
    1. Class 层面:
    1) @hibernate.class
    描述POJO 与数据库表之间的映射关系,并指定相关的运行参数。
       参数                        描述                                                                                        类型             必须
      table                   类对应的表名,默认值:当前类名                                                          Text               N
    dynamic-update    生成Update SQL时,仅包含发生变动的字段,默认值: false                          Bool               N
    dynamic-insert      生成Insert SQL时,仅包含非空(null)字段,默认值:false                            Bool               N
    Proxy                   代理类,默认值:空                                                                            Text               N

    discriminator-value 子类辨别标识,用于多态支持。                                                            Text               N
    where                 数据甄选条件,如果只需要处理库表中某些特定数据的时候,可通过此选项设定结果集限定条件。如用户表中保存了全国所有

                            用户的数据,而我们的系统只是面向上海用户,则可指定where="location='Shanghai'"    Text   N

    典型场景:
    /**
    * @hibernate.class
    * table="TUser" (1)
    * dynamic-update="true" (2)
    * dynamic-insert="true" (3)
    * proxy="" (4)
    * discriminator-value="1" (5)
    */
    public class TUser implements Serializable {
    ......
    }
    本例中:
    1 table参数指定了当前类(TUser)对应数据库表"TUser"。
    2 dynamic-update 参数设定为生成Update SQL 时候,只包括当前发生变化的字段(提高DB Update性能)。
    3 Dynamic-insert 参数设定为生成Insert SQL 时候,只包括当前非空字段。(提高DB Insert性能)
    4 Proxy 参数为空,表明当前类不使用代理(Proxy)。代理类的作用是为Lazy.Loading提供支持,请参见下面关于Lazy Loading的有关内容。
    5 discriminator-value参数设为"1"。discriminator-value 参数的目的是对多态提供支持。请参见下面关于@hibernate.discriminator的说明。

    2) @hibernate.discriminator
    @hibernate.discriminator(识别器) 用于提供多态支持。
         参数            描述                                                            类型          必须
    column    用于区分各子类的字段名称。默认值:当前类名                text           Y
    type        对应的Hibernate类型                                               Bool           N
    length      字段长度                                                               Bool           N
    如:
    TUser类对应数据库表TUser,并且User类有两个派生类SysAdmin、SysOperator。
    在TUser表中, 根据user_type字段区分用户类型。
    为了让Hibernate根据user_type能自动识别对应的Class类型(如 user_type==1
    则自动映射到SysAdmin类,user_type==2 则自动映射到SysOperator类),我们需要
    在映射文件中进行配置,而在Hibernate-Doclet中,对应的就是@hibernate.discriminator 标识和 @hibernate.class 以及 @hibernate.subclass 的discriminator-value属性。

    典型场景:
    /**
    *
    * @hibernate.class
    * table="TUser"
    * dynamic-update="true"
    * dynamic-insert="true"
    *
    * @hibernate.discriminator column="user_type" type="integer"
    */
    public class TUser implements Serializable {
    ......
    }
    根类TUser 中,通过@hibernate.discriminator 指定了以"user_type"字段
    作为识别字段。
    /**
    * @hibernate.subclass
    * discriminator-value="1"
    */
    public class SysAdmin extends TUser {
    ......
    }
    /**
    * @hibernate.subclass
    * discriminator-value="2"
    */
    public class SysOperator extends TUser {
    ......
    }
    SysAdmin 和SysOperator 均继承自TUser,其discriminator-value 分别设置
    为"1"和"2",运行期Hibernate 在读取t_user 表数据时,会根据其user_type 字段进行
    判断,如果是1 的话则映射到SysAdmin类,如果是2 映射到SysOperator 类。

    上例中,描述SysAdmin 和SysOperator 时,我们引入了一个Tag:
    @hibernate.subclass,顾名思义,@hibernate.subclass与@hibernate.class
    不同之处就在于,@hibernate.subclass 描述的是一个子类,实际上,这两个Tag
    除去名称不同外,并没有什么区别。

    2. Method层面:
    1) @hibernate.id
    描述POJO 中关键字段与数据库表主键之间的映射关系。
      参数            描述                                  类型         必须
    column   主键字段名,默认值:当前类名        Text          N
    type       字段类型。Hibernate总是使用对象型数据类型作为字段类型,如int对应Integer,因此这里将id设为基本类型[如int]以避免对
    象创建的开销的思路是没有实际意义的,即使这里设置为基本类型,Hibernate内部还是会使用对象型数据对其进行处理,只是返回数据的时候再转换为基本类型而已。                               Text          N
    length      字段长度                                 Text          N
    unsaved-value     用于对象是否已经保存的判定值。详见"数据访问"章节的相关讨论。 Text     N
    generator-class   主键产生方式(详见Hibernate QuickStart中关于MiddleGen的相关说明)取值可为下列值中的任意一个:
                             assigned,hilo,seqhilo, increment, identity, sequence, native, uuid.hex, uuid.string, foreign         Text    Y


    2) @hibernate.property
    描述POJO 中属性与数据库表字段之间的映射关系。
        参数                                  描述                                                   类型          必须
    column    数据库表字段名,默认值:当前类名                                           Text            N
    type                    字段类型                                                               Text            N
    length                  字段长度                                                               Text           N
    not-null              字段是否允许为空                                                      Bool          N
    unique               字段是否唯一(是否允许重复值)                                   Bool           N
    insert Insert       操作时是否包含本字段数据,默认:true                            Bool          N
    update Update    操作时是否包含本字段数据,默认:true                           Bool          N


    典型场景:
    /**
    * @hibernate.property
    * column="name"
    * length="50"
    * not-null="true"
    *
    * @return String
    */
    public String getName() {
    return this.name;
    }
            注意:在编写代码的时候请,对将POJO的getter/setter方法设定为public,如果
    设定为private,Hibernate将无法对属性的存取进行优化,只能转而采用传统的反射机制
    进行操作,这将导致大量的性能开销(特别是在1.4之前的Sun JDK版本以及IBM JDK中,
    反射所带来的系统开销相当可观)。
      

    Notice:*****************如何使用XDoclet生成映射文件      

      包含XDoclet Tag的代码必须由xdoclet程序进行处理以生成对应的映射文件,
    xdoclet的处理模块可通过ant进行加载,下面是一个简单的hibernate xdoclet的ant
    构建脚本(注意实际使用时需要根据实际情况对路径和CLASSPATH设定进行调整):
    <?xml version="1.0"?>
    <project name="Hibernate" default="hibernate" basedir=".">
    <property name="xdoclet.lib.home" value="C:\xdoclet-1.2.1\lib"/>
    <target name="hibernate" depends="" description="Generates Hibernate class descriptor files.">
    <taskdef name="hibernatedoclet" classname="xdoclet.modules.hibernate.HibernateDocletTask">
    <classpath>
    <fileset dir="${xdoclet.lib.home}">
    <include name="*.jar"/>
    </fileset>
    </classpath>
    </taskdef>
    <hibernatedoclet destdir="./src/" excludedtags="@version,@author,@todo" force="true" verbose="true" mergedir=".">
    <fileset dir="./src/">
    <include name="**/hibernate/sample/*.java"/>
    </fileset>
    <hibernate version="2.0"/>
    </hibernatedoclet>
    </target>
    </project>
    除了上面我们介绍的Hibernate Doclet Tag,其他还有:
    Class层面;
    @hibernate.cache
    @hibernate.jcs-cache
    @hibernate.joined-subclass
    @hibernate.joined-subclass-key
    @hibernate.query
    Method层面
    @hibernate.array
    @hibernate.bag
    @hibernate.collection-cache
    @hibernate.collection-composite-element
    @hibernate.collection-element
    @hibernate.collection-index
    @hibernate.collection-jcs-cache
    @hibernate.collection-key
    @hibernate.collection-key-column
    @hibernate.collection-many-to-many
    @hibernate.collection-one-to-many
    @hibernate.column
    @hibernate.component
    @hibernate.generator-param
    @hibernate.index-many-to-many
    @hibernate.list
    @hibernate.many-to-one
    @hibernate.map
    @hibernate.one-to-one
    @hibernate.primitive-array
    @hibernate.set
    @hibernate.timestamp
    @hibernate.version
                 具体的Tag描述请参见XDoclet官方网站提供的Tag说明1。