《设计模式》一书对Decorator是这样描述的:
 动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式比生成子类更为灵活。
也就是说:动态地给对象添加一些额外的功能。它的工作原理是:创建一个始于Decorator对象(负责新功能的对象)终止于原对象的一个对象的“链”。例如,我们要为超市的收银台设计一个打印票据的程序,有的需要打印票据的头信息,有的需要打印票据的页脚信息,有的只需要打印票据的内容。如果针对每一种情况都修改一次程序,势必会很麻烦。这时我们可以考虑使用Decorator模式。其结构类图如下:
 

代码如下:
abstract class Component{
 abstract public void printTicket();
}
class SalesTicket extends Component{
 public void printTicket() {
  System.out.println("打印出salesTicket的内容");
 }
}
abstract class TicketDecorator extends Component{
 private Component myTrailer;
 public TicketDecorator(Component myComponent){
  myTrailer=myComponent;
 }
 public void callTrailer(){
  if(myTrailer!=null)
   myTrailer.printTicket();
 }
}
class Header extends TicketDecorator{
 public Header(Component myComponent){
  super(myComponent);
 }
 public void printTicket(){
  System.out.println("打印salesTicket的头信息");
  super.callTrailer();
  
 }
}
class Footer extends TicketDecorator{
 public Footer(Component myComponent){
  super(myComponent);
 }
 public void printTicket(){
  super.callTrailer();
  System.out.println("打印salesTicket的页脚信息");
 }
}
public class Client {

 public static void main(String[] args) {
  System.out.println("====================================");
  new Header(new Footer(new SalesTicket())).printTicket();
  System.out.println("====================================");
  new Footer(new Header(new SalesTicket())).printTicket();
  System.out.println("====================================");
 }

}
输出结果如下:
====================================
打印salesTicket的头信息
打印出salesTicket的内容
打印salesTicket的页脚信息
====================================
打印salesTicket的头信息
打印出salesTicket的内容
打印salesTicket的页脚信息
====================================
从这个例子我们可以看出,Decorator模式把问题分为两部分:
1) 如何实现提供新功能的对象。
2) 如何为每种特殊情况组织对象。
这样能够将Decorator对象的实现与决定如何使用Decorator的对象分离开来,从而提高了内聚性,因为每个Decorator对象只用关心自己添加的功能,无需关心自己是如何被加入到对象链中。还可以任意地重排Decorator的顺序,无需改变其任何代码。
小结:Decorator模式的适用场合是,各种可选的功能在另一个肯定要执行的功能之前或之后执行。

 

posted @ 2007-11-28 20:31 flustar 阅读(1170) | 评论 (0)编辑 收藏

          GOF《设计模式》一书对Abstract Factory模式是这样描述的:

    为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。
  大致意思是说:我们在创建这些对象的时候,并不需要指定它们的具体类,这些具体类的对象是由工厂对象负责实例化的。下面是《Design Patterns Explained》一书的例子,有关计算机系统的显示和打印程序,用来显示和打印的分辨率取决于当前运行的系统。低端机使用低分辨率的显示和打印驱动程序,高端机使用高分辨率的显示和打印驱动程序。其结构图如下:


代码如下:

abstract class ResFactory{

    abstract public DisplayDriver getDisplayDrvr();

    abstract public PrintDriver getPrintDrvr();

}

class LowResFact extends ResFactory{

    public DisplayDriver getDisplayDrvr() {

        returnnew LRDD();

    }

    public PrintDriver getPrintDrvr() {

        returnnew LRPD();

    }

   

}

class HighResFact extends ResFactory{

    public DisplayDriver getDisplayDrvr() {

        returnnew HRDD();

    }

    public PrintDriver getPrintDrvr() {

        returnnew HRPD();

    }

   

}

abstract class DisplayDriver{

   

}

abstract class PrintDriver{

}

class HRDD extends DisplayDriver{
    
public HRDD() {
        
System.out.println("使用高端机的显示驱动程序")
 } 

}

class LRDD extends DisplayDriver{

    public LRDD(){

        System.out.println("使用低端机的显示驱动程序");

    } 

}

class HRPD extends PrintDriver{

    public HRPD() {

        System.out.println("使用高端机的打印驱动程序");

    }

   

}

class LRPD extends PrintDriver{

    public LRPD() {

        System.out.println("使用低端机的打印驱动程序");

    } 

}

public class ApControl {

    public static ResFactory getResFactory(ResFactory factory){

        return factory;

    }

    public static void main(String[] args) {

        ResFactory highResFact=ApControl.getResFactory(new HighResFact());

        highResFact.getDisplayDrvr();

        highResFact.getPrintDrvr();

        ResFactory lowResFact=ApControl.getResFactory(new LowResFact());

        lowResFact.getDisplayDrvr();

        lowResFact.getPrintDrvr();

    }

}输出结果:

使用高端机的显示驱动程序

使用高端机的打印驱动程序

使用低端机的显示驱动程序

使用低端机的打印驱动程序

    在这个例子中ApControl使用派生自两个不同的服务类(DisplayDriver和PrintDriver)的对象。这个设计非常简化,隐藏了实现细节,系统的可维护性也更好。ApControl不知道自己拥有的服务对象的那个特定具体实现,因为创建对象是工厂的职责。ApControl也不知道自己使用的是哪个特定工厂,因为它只知道自己有一个ResFactory对象。它可能是一个HighResFact也可能是一个LowResFact,但它不知道到底是哪一个。

    小结:在必须协调一组对象的创建时,可以应用Abstract Factory模式。它提供了一种方式,将如何执行对象实例化的规则从使用这些对象的客户对象中提取出来。首先,找出实例化的规则,定义了一个带接口的抽象类,其中的接口为每种需要实例化的对象提供一个方法。然后,从这个类为每个组实现具体类。最后,由客户对象决定使用具体工厂来创建所需的对象。它主要适用于以下几种情况:

1)     一个系统要独立于它的产品的创建、组合和表示时。

2)    可以对系统进行配置,以便系统可以使用多个产品系列中的某一个。

3)    当需要强调一系列相关产品对象的设计以便进行联合使用时。

4)    当希望提供一个产品类库,而只想显示他们的接口而不是实现时。

posted @ 2007-11-28 20:23 flustar 阅读(787) | 评论 (0)编辑 收藏

   《设计模式》一书对Bridge是这样描述的:

将抽象与其实现解耦,使它们都可以独立地变化。

大致意思是说:将一组实现与另一组使用他们的对象分离。这里的实现指的是抽象类及其

派生类用来实现自己的对象(而不是抽象类的派生类,这些派生类被称为具体类)。下面

是《Design Patterns Explained》书中的例子。其结构图如下:
  

下面是它的实现:

abstract class Shape{

    protected Drawing myDrawing;

    abstract public void draw();

    Shape(Drawing drawing){

        myDrawing=drawing;

    }

    protected void drawLine(){

        myDrawing.drawLine();

    }

    protected void drawCircle(){

        myDrawing.drawCircle();

    }

}

class Rectangle extends Shape{

    public Rectangle(Drawing darw){

        super(darw);

    }

    public void draw(){

        drawLine();

        drawLine();

        drawLine();

        drawLine();

    }

}

 class Circle extends Shape{

    public Circle(Drawing draw){

        super(draw);

    }

    publicvoid draw(){

        myDrawing.drawCircle();

    }

}

abstract class Drawing{

    abstract public void drawLine();

    abstract public void drawCircle();

}

class V1Drawing extends Drawing{

    public void drawLine(){

        DP1.draw_a_line();

    }

    public void drawCircle(){

        DP1.draw_a_circle();

    }

}

class V2Drawing extends Drawing{

    public void drawLine(){

        DP2.drawLine();

    }

    public void drawCircle(){

        DP2.drawCircle();

    }

}

class DP1{

    public static void draw_a_line(){

        System.out.println("使用DP1的draw_a_line()画线");

    }

    public static void draw_a_circle(){

        System.out.println("使用DP1的draw_a_circle()画圆");

    }

}

class DP2{

    public static void drawLine(){

        System.out.println("使用DP2的drawLine()画线");

    }

    public static void drawCircle(){

        System.out.println("使用DP2的drawCircle()画圆");

    }

}

 public class BridgeClient {

    public static void main(String[] args) {

        Drawing draw1=new V1Drawing();

        Drawing draw2=new V2Drawing();

        Shape shape1=new Rectangle(draw1);

        shape1.draw();

        Shape shape2=new Circle(draw2);

        shape2.draw();

    }

}

输出结果如下

使用DP1draw_a_line()画线

使用DP1draw_a_line()画线

使用DP1draw_a_line()画线

使用DP1draw_a_line()画线

使用DP2drawCircle()画圆

在这个例子中Shape对象实际上是一个RetangleCircle对象Client并不知道到底是那个因为它们看起来都一样。Drawing实际上是一个V1DrawingV2Drawing,Shape对象并知道到底是哪个因为它们看起来都一样。DP1或DP2使用它的Drawing对象知道是哪一个。Shape是事物的抽象,Drawing是实现或者操作事物方法的抽象。他们两个都可以独立地变化。正如例子中所说那样,我们可以输出一个矩形可以使用V1Drawing也可以使用V2Drawing来完成,输出一个圆形也是一样都有两种方法。Bridge模式遵循了设计模式中两条基本策略:找出变化并封装之和优先使用对象聚集,而不是类继承。

    小结:Bridge模式是一种抽象与其实现相分离的模式。它主要应用于:当事物是一组变化量,和对这些事物的操作方法(实现)也是一组变化量的情况,也就是说它们都是多变的。

posted @ 2007-11-28 15:48 flustar 阅读(1192) | 评论 (0)编辑 收藏

GOF《设计模式》一书对Strategy模式是这样描述的:

    定义一系列的算法,把他们一个个封装起来,并且使它们可相互替换。Strategy模式使算法可独立于使用它的客户而变化。

    Strategy模式以下列几条原则为基础:

1) 每个对象都是一个具有职责的个体。

2) 这些职责不同的具体实现是通过多态的使用来完成的。

3) 概念上相同的算法具有多个不同的实现,需要进行管理。

下面我将通过一个实例来说明它的具体使用,这个例子是关于数据库连接的。代码如下:

interface DatabaseStrategy{

    public void process();

}

class MysqlDBStrategy implements DatabaseStrategy{

    public void process() {

       System.out.println("处理Mysql数据库连接");

    }

}

class OracleDBStrategy implements DatabaseStrategy{

    public void process() {

       System.out.println("处理Oracle数据库连接");

    }

}

class DataBaseManager{

    public void process(DatabaseStrategy dbStrategy){

       dbStrategy.process();

    }

}

publicclass StrategyClient {

    public static void main(String[] args) {

       MysqlDBStrategy mysql=new MysqlDBStrategy();

       DataBaseManager manager=new DataBaseManager();

       manager.process(mysql);

       OracleDBStrategy oracle=new OracleDBStrategy();

       manager.process(oracle);

    }

}

    在我们的实际编程中经常会遇到系统要连接的数据库可能不只一种,如果采用传统的方法,即修改连接Url的方法,这种方法确实可行,但是有一个问题要经常修改源代码,不利于以后的维护,那么有没有一种更好的方法呢?答案是有,使用Strategy模式,首先定义一个连接数据库通用的接口(在上面的例子中是DatabaseStrategy),然后再定义实现该接口的具体类(MysqlDBStrategy、OracleDBStrategy),在这些具体类,实现具体的逻辑。最后再定义一个管理数据库连接的类(DataBaseManager),它的内部有一个方法可以接受具体类实例的参数。我们可以看到这个参数是DatabaseStrategy类型的,也就是说它可以接受任何一个实现了DatabaseStrategy接口的类的具体实例(这里运用了对象替换机制,多态的一种),从而完成数据库连接的处理。如果我们还需要处理另外一种数据库如sqlserver,我们只需要建立一个SqlserverDBStrategy类实现DatabaseStrategy接口,把该类的实例传给DatabaseManager的process方法即可。

    小结:Strategy模式是一种定义一系列算法的方法。概念上看,这些算法完成的都是相同的工作,只是实现不同。

posted @ 2007-11-23 18:43 flustar 阅读(1079) | 评论 (0)编辑 收藏

GOF《设计模式》一书对Adapter模式是这样描述的:
  
 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使原本由于接口不兼容而不能一起工作的类可以一起工作。

    这段话大致是说:我们需要一种方式,为一个功能正确但接口不合的对象创建一个新接口。例如,客户给我们如下需求:

1) 为都有“显示”(display)行为的点、线、正方形分别创建类。

2) 客户对象不必知道自己到底拥有点、线、还是正方形。它只需知道拥有这些形状中的一个。

也就是说,我们要用一个更高层次的概念将这些具体形状都涵盖进去,这个高层概念可以称为:“可显示的形状”。因此,我们需要创建一个接口Shape:

interface Shape{

    publicvoid display();

}

现在客户忽然间有让我们给这个系统增加一个画圆的功能。这个看起来很简单,只需定义一个Circle类来实现Shape接口,但是我们要给它编写display方法,这可不是件简单的事,假如此时我们正好发现一个XXCircle类,它有一个方法刚好可以完成这个功能,那么有没有更好的方法来利用它呢,这时我们就要用到Adapter模式了。XXCircle代码如下:

class XXCircle{

    public void displayCircle(){

       System.out.println("通过XXCircle.displayCircle()画圆");

    }

}

    Adapter模式有两种类型:

1)    对象Adapter模式,它依赖于一个对象(适配器)包含另一个对象(被适配的对象)

class CircleObject implements Shape{

    public XXCircle circle;

    public CircleObject(XXCircle xxcircle){

    circle=xxcircle;

    }

    public void display() {

       circle.displayCircle(); 

    }

}

public class Client {

    public static void main(String[] args) {

       XXCircle circle=new XXCircle();

       CircleObject co=new CircleObject(circle);

       co.display();

    }

}

2)     类Adapter模式,它是通过多重继承来实现的(java中没有多继承,是通过接口来实现的)。

class CircleClass extends XXCircle implements Shape{

    public void display() {

       super.displayCircle();  

    }

}

public class Client {

    public static void main(String[] args) {

       CircleClass cc=new CircleClass();

       cc.display();

    }

}

    小结:Adapter模式是一个很常用的模式,它将一个(或多个)类的接口转换成我们需要类所具备的一个接口。它的实现方式是:创建一个具备所需接口的类,然后包装原有类的方法,这样实际上就包含了被适配的对象。它主要适用于以下几种情况:

1) 你希望使用他人编写的子程序或方法,因为你需要它所执行的功能。

2) 你无法将这个子程序直接加入程序中。

3) 子程序的接口或调用方式与需要使用它的相关对象不完全相同。

posted @ 2007-11-23 18:40 flustar 阅读(1211) | 评论 (0)编辑 收藏

        GOF《设计模式》一书对Facade模式是这样描述的:

       为子系统中的一组接口提供一个统一接口。Facade模式定义了一个更高层的接口,使子系统更加容易使用。

       大致意思是说:使用一种比原有方式更简单的办法与系统交互。例如,我们把一个很文件的文件,放在了第二抽屉里,而第二个抽屉的钥匙放在了第一个抽屉里,我们要想取出这个文件,第一步肯定要拿到第一个抽屉的钥匙,然后打开它再拿出第二个抽屉的钥匙,最后打开第二个抽屉取出文件。

       我就上面说的那个情形写一下实现代码,首先我们要实现二个子系统,呵呵,把抽屉比喻成系统,有点夸张了(DrawerOneDrawerTwo):

class DrawerOne {

    public void open(){

       System.out.println("第一个抽屉被打开了");

       getKey();

    }

    public void getKey(){

       System.out.println("得到第二个抽屉的钥匙");

    }

}

class DrawerTwo{

    public void open(){

       System.out.println("第二个抽屉被打开了");

       getFile();

    }

    public void getFile(){

       System.out.println("得到这个重要文件");

    }

}

public class Client{

    public static void main(String []args){

       DrawerOne darwerOne=new DrawerOne();

       DrawerTwo darwerTwo=new DrawerTwo();

       darwerOne.open();

       darwerTwo.open();

    }

}

由于没有使用Façade模式,可以看到要想得到这个文件要首先打开第一个抽屉,然后再打开第二个抽屉,在我们实际所开发的系统中,有时候客户要实现某一操作,并不需要知道实现这一操作的详细步骤,而是简单地点击某一个按钮就可以得到自己想要的结果。下面对上面的代码使用Façade模式进行改进,建立一个FacadeDrawer类:

class DrawerFacade{

    DrawerOne darwerOne=new DrawerOne();

    DrawerTwo darwerTwo=new DrawerTwo();

    public void open(){

       darwerOne.open();

       darwerTwo.open();

    }

}

修改Client类:

public class DrawerClient{

    public static void main(String []args){

       DrawerFacade drawer=new DrawerFacade();

       drawer.open();

    }

}

输出结果如下:

第一个抽屉被打开了

得到第二个抽屉的钥匙

第二个抽屉被打开了

得到这个重要文件

正如上面所说,客户端client,它并不需要关心子系统,而是关心DrawerFacade所留下来的和外部交互的接口,而子系统在DrawerFacade的聚合。

以上只是个人拙见,哪里有不正确的地方,希望大家多多批评指正。^_^

    Facade模式主要适用于以下几种情况:

1)    不需要使用一个复杂系统的所有功能,而且可以创建一个新的类,包含访问系统的所有规则。如果只需要使用系统的部分功能,那么你为新类所创建的API将比原系统的API简单的多。

2)    希望封装或者隐藏系统原系统。

3)    希望使用原系统的功能,而且还希望增加一些新的功能。

4)    编写新类的成本小于所有人学会使用或者未来维护原系统上所需的成本。

posted @ 2007-11-23 01:45 flustar 阅读(2818) | 评论 (1)编辑 收藏

一、建立xml的数据结构,文件名为:vote.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<votes voteTotalCount="0">

    <vote voteId="1" name="c语言 " voteCount="0" percentum="0" />

    <vote voteId="2" name="c++" voteCount="0" percentum="0" />

    <vote voteId="3" name="java" voteCount="0" percentum="0" />

    <vote voteId="4" name="汇编语言" voteCount="0" percentum="0" />

 </votes>

在你的web应用的根目录建立xml文件夹,将其拷贝到该目录下。

二、建立xml对应的bean

/**

 * @author flustar

 * @version 创建时间:Jul 11, 2007 5:17:53 PM

 * 类说明

 */

……………………………………………………………………….

……………………………………………………………………….

public class VoteBean {

    private String voteId;

   private String name;

    private String voteCount;

    private String voteTotalCount;

    private String percentum;

    public VoteBean() {

      

    }

    public String getPercentum() {

       return percentum;

    }

    public void setPercentum(String percentum) {

       this.percentum = percentum;

    }

    public String getVoteId() {

       return voteId;

    }

 

    public void setVoteId(String voteId) {

       this.voteId = voteId;

    }

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

    public String getVoteCount() {

       return voteCount;

    }

 

    public void setVoteCount(String voteCount) {

       this.voteCount = voteCount;

    }

}

三、建立处理具体逻辑的service

package com.flustar.service;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.text.NumberFormat;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

import org.jdom.Attribute;

import org.jdom.Document;

import org.jdom.Element;

import org.jdom.input.SAXBuilder;

import org.jdom.output.Format;

import org.jdom.output.XMLOutputter;

import org.jdom.xpath.XPath;

import com.flustar.web.beans.VoteBean;

import com.flustar.web.config.ContextConfig;

public class VoteService {

       private Element root, vote;

       private Document doc;

      private Attribute voteTotalCount;

       private VoteBean voteBean;

       private List<VoteBean> voteBeanList;

       private String path = ContextConfig.getContextPath()

                     + "/xml/vote.xml";

       public void buildDoc() throws Exception {

              FileInputStream fi = null;

              fi = new FileInputStream(path);

              SAXBuilder sb = new SAXBuilder();

              doc = sb.build(fi);

       }

       public void formatDoc() throws Exception {

              Format format = Format.getCompactFormat();

              format.setEncoding("UTF-8");// 设置xml文件的字符为UTF-8

              format.setIndent("    ");// 设置xml文件缩进为4个空格

              XMLOutputter xmlOut = new XMLOutputter(format);

              xmlOut.output(doc, new FileOutputStream(path));

       }

 

       public String floatToPercentum(Double doubleNum) {

              NumberFormat numberFormat = NumberFormat.getPercentInstance();

              numberFormat.setMinimumFractionDigits(2);

              // numberFormat.setMaximumIntegerDigits(2);

              String str = numberFormat.format(doubleNum);

              //System.out.println(str);

              return str;

       }

 

       public void updateVoteCount(String voteId) throws Exception {

              buildDoc();

              root = doc.getRootElement();

              vote = (Element) XPath.selectSingleNode(root, "//vote[@voteId='"

                            + voteId + "']");

              int voteCount = Integer.parseInt(vote.getAttributeValue("voteCount")) + 1;

              //System.out.println(voteCount);

              vote.setAttribute("voteCount", String.valueOf(voteCount));

              int totalCount = Integer.parseInt(root

                            .getAttributeValue("voteTotalCount")) + 1;

              voteTotalCount = new Attribute("voteTotalCount", String

                            .valueOf(totalCount));

              root.setAttribute(voteTotalCount);

              System.out.println(totalCount);

              formatDoc();

              updateAllVoteCount();//更新所有的百分比

 

       }

    public void updateAllVoteCount()throws Exception{

           buildDoc();

           root=doc.getRootElement();

           int totalCount = Integer.parseInt(root

                            .getAttributeValue("voteTotalCount"));

           List voteList=XPath.selectNodes(root,"/votes/vote");

           for(int i=0;i<voteList.size();i++){

                  vote=(Element)voteList.get(i);

                  int voteCount = Integer.parseInt(vote.getAttributeValue("voteCount"));

                  System.out.println(voteCount);

                  vote.setAttribute("voteCount", String.valueOf(voteCount));

                  vote.setAttribute("percentum", floatToPercentum(1.0 * voteCount

                                / totalCount));

           }

           formatDoc();

    }

       public List getAllVote() throws Exception {

              buildDoc();

              voteBeanList = new ArrayList();

              root = doc.getRootElement();

              String totalCount = root.getAttributeValue("voteTotalCount");

              List voteList = root.getChildren();

              Iterator i = voteList.iterator();

 

              while (i.hasNext()) {

                     voteBean = new VoteBean();

                     voteBean.setVoteTotalCount(totalCount);

                     vote = (Element) i.next();

                     String name = vote.getAttributeValue("name");

                     String voteCount = vote.getAttributeValue("voteCount");

                     String percentum = vote.getAttributeValue("percentum");

 

                     voteBean.setName(name);

                     voteBean.setVoteCount(voteCount);

                     voteBean.setPercentum(percentum);

                     voteBeanList.add(voteBean);

              }

              return voteBeanList;

       }

 

}

 

    public String getVoteTotalCount() {

       return voteTotalCount;

    }

 

    public void setVoteTotalCount(String voteTotalCount) {

       this.voteTotalCount = voteTotalCount;

    }

}

 

四、获取上下文路径的listener

package com.flustar.web.listener;

import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;

import com.flustar.web.config.ContextConfig;

public class ConfigLoadContextListener implements  ServletContextListener{

    public void contextDestroyed(ServletContextEvent arg0) {

       // TODO Auto-generated method stub

           }

    public void contextInitialized(ServletContextEvent contextEvent) {

       // TODO Auto-generated method stub

              String contextPath = contextEvent.getServletContext().getRealPath("/");

       ContextConfig.setContextPath(contextPath);

           }

}

………………………………………………………..

……………………………………………………………

 

public class ContextConfig {

    private static String contextPath;

 

    public static String getContextPath() {

       return contextPath;

    }

 

    public static void setContextPath(String contextPath) {

       ContextConfig.contextPath = contextPath;

    }

……………………………………………………………………

………………………………………………………………..

}

五、在applicationContext-service.xml中注册VoteService

<bean name="voteService" class="com.flustar.service.imp.VoteService"/>

六、注册xml,在你的web应用的WEB-INFO目录下建立applicationContext-dwr.xml文件,内容为:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr/dwr20.dtd">

<dwr>

    <allow>

      <create  creator="spring" javascript="VoteService" >

         <param name="beanName" value="voteService"></param>

         <include method="updateVoteCount"/>

         <include method="getAllVote"/>

      </create>

      <convert converter="bean"  match="com.flustar.web.beans.VoteBean" />

           </allow>

</dwr>

 

七、修改web.xml

<?xml version="1.0" encoding="UTF-8"?>

<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">

    …………………………………………………………………………………………………………………………

………………………………………………………………………………………………………………………………..

    <context-param>

       <param-name>contextConfigLocation</param-name>

       <param-value>

…………………………………..

       /WEB-INF/classes/applicationContext-service.xml

</param-value>

    </context-param>

 …………………………………………………………………………………………………………………………………………….     <listener-class>com.flustar.web.listener.ConfigLoadContextListener</listener-class>

    …………………………………………………………………………………………………………………………………………….   

  <servlet>

    <servlet-name>dwr-invoker</servlet-name>

    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>

    <init-param>

      <param-name>debug</param-name>

      <param-value>true</param-value>

    </init-param>

  </servlet>

 

  <servlet-mapping>

    <servlet-name>dwr-invoker</servlet-name>

    <url-pattern>/dwr/*</url-pattern>

  </servlet-mapping> 

…………………………………………………………………………………………………………………………………………….   

</web-app>

八、jsp页面

1)

<%@ page contentType="text/html; charset=gbk" language="java" import="java.sql.*" errorPage="" %>

<html>

<head>

<title>投票系统</title>

       <script type='text/javascript' src='dwr/engine.js'> </script>

        <script type='text/javascript' src='dwr/util.js'> </script>

        <script type='text/javascript' src='dwr/interface/VoteService.js'> </script>

       <script type='text/javascript'>

function vote(){

       

     var   obj=document.getElementsByName('radio'); 

    

         if   (obj!=null){ 

         var j=0;

           for   (var   i=0;i<obj.length;i++){ 

             if   (obj[i].checked)  

              {  

               

                   VoteService.updateVoteCount(obj[i].value);

                   alert("投票成功!");

                  obj[i].checked=false;

                  break;

               }

              }

               j=j+1;

             

          }

         if(j==obj.length){

                alert("请选中其中的一项,再投票!");

               }

          

      }

   

    }

  function showwin(){

    window.open('voteresult.htm','voteresult','height=400, width=400, top=0, left=0, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no');

   }

 }

</script>

</head>

<body>

<div >

    <h1 >

       你使用最多的一门语言是?

    </h1>

</div>

<div>

<div>

        <span>     <h1><input type="radio" name="radio" id="radio" value="1" />

       C语言</h1>

        </span>

       <span> <h1 ><input type="radio" name="radio" id="radio" value="2" />c++ </h1> </span>

       <span ><h1 ><input type="radio" name="radio" id="radio" value="3" />java </h1> </span>

       <span><h1 ><input type="radio" name="radio" id="radio" value="4"/>汇编语言</h1> </span>

</div>

</div>

<div id="toupiao"><input class="btn" type="button" value="投票" onClick="vote()" /><input class="btn" type="button" value="查看" onClick="showwin()"/></div>

</body>

</html>

2)

<html>

<head>

<meta http-equiv="content-type" content="text/html; charset=gb2312">

<title>投票结果</title>

       <script type='text/javascript' src='dwr/engine.js'> </script>

        <script type='text/javascript' src='dwr/util.js'> </script>

        <script type='text/javascript' src='dwr/interface/VoteService.js'> </script>

        <script type='text/javascript' >

function showresult(){

             VoteService.getAllVote(function(data){

             document.getElementById("totalCount").innerHTML=data[0].voteTotalCount;

             for(var i=0;i<data.length;i++){

                  var voteBean=data[i];

                  document.getElementById("xuanshou"+i).innerHTML=voteBean.name;

                  document.getElementById("baifenbi"+i).innerHTML=voteBean.percentum;

                  document.getElementById("piaoshu"+i).innerHTML=voteBean.voteCount;

                  document.getElementById("img"+i).width=voteBean.voteCount/data[0].voteTotalCount*310;

                                   

      }

    });

          

}

</script>

</head>

<body onLoad="showresult()">

<div id="voteRs">

<table border="0" cellpadding="0" cellspacing="0">

  <CAPTION valign="top" class="subject">

投票结果

    </CAPTION>

  <tbody>

  <tr >

    <th>语言</th>

    <th>百分比</th>

    <th>票数</th>

  </tr>

  <tr>

    <td><span id="xuanshou0"></span></td>

    <td><span id="baifenbi0"></span><img id="img0" src='images/voteprogress.gif' width=0 height=10></td>

    <td><span id="piaoshu0"></span></td>

  </tr>

  <tr>

    <td><span id="xuanshou1"></span></td>

    <td><span id="baifenbi1"></span><img id="img1" src='images/voteprogress.gif' width=0 height=10></td>

    <td><span id="piaoshu1"></span></td>

  </tr>

  <tr>

    <td><span id="xuanshou2"></span></td>

    <td><span id="baifenbi2"></span><img id="img2" src='images/voteprogress.gif' width=0 height=10></td>

    <td><span id="piaoshu2"></span></td>

  </tr>

   <tr>

    <td><span id="xuanshou3"></span></td>

    <td><span id="baifenbi3"></span><img id="img3" src='images/voteprogress.gif' width=0 height=10></td>

    <td><span id="piaoshu3"></span></td>

  </tr>

 

  </tbody>

</table>

共<span id="totalCount"></span>条投票<br/>

[<span onClick="javascript:window.close();">关闭窗口</span>]

</div>

</body>

</html>

 

posted @ 2007-11-19 18:04 flustar 阅读(1348) | 评论 (0)编辑 收藏

最近发现使用prototype来做表单的前台验证感觉非常不错,prototype.js 是由 Sam Stephenson 写的一个 javascript 类库。这个构思奇妙,而且兼容标准的类库,能帮助你轻松建立有高度互动的 Web 2.0 特性的富客户端页面。下面是一个使用它做前台表单验证的例子。

var flag=[true,true,true,true,true,true,true,true,true,true];
       var userNameInfo=["用户名不能为空","用户名必须为6~20位","用户已存在","恭喜用户名可以使用"];
       var passwordInfo=["密码不能为空","密码长度不能小于6位","请再次输入密码","两次密码输入不一致,请重新输入"];
       function changeImage()
    {
    var timenow=new Date().getTime();
          $('checkcode').src = "image/loading.gif";
          $('checkcode').src = "random.jsp?d="+timenow;
       }
       function checkUserName()
    {
    if ($F("userName").match(/^\s*$/g)) {
           $("userNameErr").innerHTML =userNameInfo[0];
     flag[0]=false;
      }else{
  
    var re=/^(\w){6,20}$/;
    var tt = re.test($F("userName"));
    if(tt==false){
   $("userNameErr").innerHTML = userNameInfo[1];
   flag[0]=false;
       }else{
     $("userNameErr").innerHTML = "<img src='image/loading.gif'>";
       isExsitUsername(); 
   }
    }
   }
    function checkPassword()
    {
     
    if ($F("password").match(/^\s*$/g)) {
           $("pwdErr").innerHTML =passwordInfo[0];
           flag[1]=false;
  }else if($F("password").length<6){
      $("pwdErr").innerHTML=passwordInfo[1];
      flag[1]=false;
  }else{
      $("pwdErr").innerHTML="";
      flag[1]=true;
  }
  
    }
    function checkRePassword(){
      if ($F("password2").match(/^\s*$/g)) {
          $("repwdErr").innerHTML =passwordInfo[2];
          flag[2]=false;
  }else if($F("password2")!=$F("password")){
   $("repwdErr").innerHTML=passwordInfo[3]; 
   flag[2]=false; 
   }else{
      $("repwdErr").innerHTML="";
      flag[2]=true;
   }
    }
    function checkName(){
       if($F("name").match(/^\s*$/g)){
      $("nameErr").innerHTML="昵称不能为空";
      flag[3]=false;
    }else{
     $("nameErr").innerHTML="";
     flag[3]=true;
    }
    }
    function checkQuestion(){
       if($F("question").match(/^\s*$/g)){
          $("questionErr").innerHTML="请选择一个安全问题";
          flag[4]=false;
       }else{
          $("questionErr").innerHTML="";
          flag[4]=true;
       }
    }
    function checkAnswer(){
      if($F("answer").match(/^\s*$/g)){
         $("answerErr").innerHTML="安全回答不能为空";
         flag[5]=false;
      }else if($F("answer").length<4){
         $("answerErr").innerHTML="安全回答问题不能少于4个字符";
         flag[5]=false;
      }else{
          $("answerErr").innerHTML="";
         flag[5]=true;
      }
    }
    function checkEmail()
    {
     var reEmail =/(\S)+[@]{1}(\S)+[.]{1}(\w)+/;
      if($F("email").match(/^\s*$/g)){
         $("emailErr").innerHTML="Email不能为空";
         flag[6]=false;
      }else{
           var temp=reEmail.test($("email").value);
           if(temp==false){
             $("emailErr").innerHTML= "Email必须符合要求!";
                flag[6]=false;
              }else{
                $("emailErr").innerHTML="<img src='image/loading.gif'>";
                             isExsitEmail();
             
              }
         }

    }
    function checkMobile(){
    var patrn=/^(?:13\d|15[89])-?\d{5}(\d{3}|\*{3})$/;
    if($F("mobile").match(/^\s*$/g)){
         $("mobileErr").innerHTML="";
      flag[7]=true;
    }else{
      if (!patrn.test($F("mobile"))) {
         $("mobileErr").innerHTML="请输入正确的手机号码";
         flag[7]=false;
      }else{
        $("mobileErr").innerHTML="";
        flag[7]=true;
      }
      
    }  
      
   }
   function checkPID(){
     var patrn=/(^\d{15}$)|(^\d{17}([0-9]|X|x)$)/;
     if($F("PID").match(/^\s*$/g)){
       $("PIDErr").innerHTML="";
       flag[8]=true;
     }else{
      if (!patrn.test($F("PID")))  
         {
         $("PIDErr").innerHTML="身份证号码有误!";
         flag[8]=false;
      }else{
       $("PIDErr").innerHTML="";
       flag[8]=true;
    }
   }
       
    }
   
  function isExsitUsername(){
     var username=$F("userName");
     var url='user_checkUsername.do';
     var pars="username="+username;
     var usernameAjax=new Ajax.Request(
       url,
       {method:'get',parameters:pars,onComplete:showUResult}
       );
  }
  function showUResult(result){
  
       if(result.responseText.indexOf("true")!=-1){
          
          $("userNameErr").innerHTML=userNameInfo[2];
          flag[0]=false;
       }else{
          $("userNameErr").innerHTML="<font color='green'>"+userNameInfo[3]+"</font>";
          flag[0]=true;
       }
  }
  function isExsitEmail(){
     var email=$F("email");
     var url='user_checkEmail.do';
     pars="email="+email;
     var emailAjax=new Ajax.Request(
        url,
        {method:'get',parameters:pars,onComplete:showEResult}
        );
  }
  function showEResult(result){
   if(result.responseText.indexOf("true")!=-1){
       $("emailErr").innerHTML="这个Email已经有人使用,请换一个";
       flag[6]=false;
   }else{
       $("emailErr").innerHTML="<font color='green'>已通过验证</font>";
       flag[6]=true;
   }
  }
  function checkCode(){
      if($("code").value.match(/^\s*$/g)){
         $("codeErr").innerHTML="验证码不能为空";
         flag[9]=false;
    }else{
      isCorrectCode();
    }
    }
  function isCorrectCode(){
     var code=$F("code");
     var url='checkcode.jsp';
     pars="code="+code+"&ram="+Math.random();
     var codeAjax=new Ajax.Request(
     url,
     {method:'get',parameters:pars,asynchronous:false,onComplete:showCResult}
     );
    
  }
  function showCResult(result){
     if(result.responseText.indexOf("validate_successful")!=-1){
       $("codeErr").innerHTML="";
       flag[9]=true;
     }else{
       $("codeErr").innerHTML="错误的验证码";
       flag[9]=false;
     }
  }
 function checkform(){
      checkUserName();
      checkPassword();
      checkRePassword();
      checkName();
      checkQuestion();
      checkAnswer();
      checkEmail();
      checkMobile();
      checkPID();
      checkCode();
      for(var i=0;i<flag.length;i+=1){
        if(flag[i]==false)
          return false;
     }
     return true;
     
   }
其中

$(): 函数是在 DOM 中使用过于频繁的 document.getElementById() 方法的一个便利的简写,就像这个 DOM 方法一样,这个方法返回参数传入的 id 的那个元素。
$F() :函数是另一个大收欢迎的“快捷键”,它能用于返回任何表单输入控件的值,比如文本框或者下拉列表。这个方法也能用元素 id 或元素本身做为参数。
Ajax.Request 类:如果你不使用任何的帮助程序包,你很可能编写了整个大量的代码来创建 XMLHttpRequest 对象并且异步的跟踪它的进程,然后解析响应并处理它。当你不需要支持多于一种类型的浏览器时你会感到非常的幸运,反之你就要考虑使用prototype的Ajax.Request类。你也许注意到了在使用它做无刷新验证用户名,Email以及验证码时,使用'get'方法把参数传递给url,后面都带有一个参数,这个参数值是当前系统时间或是一个随机参数的一个数,这样做是为了避免浏览器的从它的缓存中读取响应信息,影响结果的正确性。


 

posted @ 2007-11-15 15:43 flustar 阅读(1119) | 评论 (0)编辑 收藏

    时间过得真快,已经半年没有更新自己的博客了。    好了,言归正传。大家都知道网上广为流传的一个分页类是:PaginationSupport.java其源代码如下:
    

public class PaginationSupport{

 public final static int PAGESIZE = 30;

 private int pageSize = PAGESIZE;

 private List items;

 private int totalCount;

 private int[] indexes = new int[0];

 private int startIndex = 0;

 public PaginationSupport(List items, int totalCount) {
  setPageSize(PAGESIZE);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(0);
 }

 public PaginationSupport(List items, int totalCount, int startIndex) {
  setPageSize(PAGESIZE);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(startIndex);
 }

 public PaginationSupport(List items, int totalCount, int pageSize,
   int startIndex) {
  setPageSize(pageSize);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(startIndex);
 }

 public List getItems() {
  return items;
 }

 public void setItems(List items) {
  this.items = items;
 }

 public int getPageSize() {
  return pageSize;
 }

 public void setPageSize(int pageSize) {
  this.pageSize = pageSize;
 }

 public int getTotalCount() {
  return totalCount;
 }

 public void setTotalCount(int totalCount) {
  if (totalCount > 0) {
   this.totalCount = totalCount;
   int count = totalCount / pageSize;
   if (totalCount % pageSize > 0)
    count++;
   indexes = new int[count];
   for (int i = 0; i < count; i++) {
    indexes[i] = pageSize * i;
   }
  } else {
   this.totalCount = 0;
  }
 }

 public int[] getIndexes() {
  return indexes;
 }

 public void setIndexes(int[] indexes) {
  this.indexes = indexes;
 }

 public int getStartIndex() {
  return startIndex;
 }

 public void setStartIndex(int startIndex) {
  if (totalCount <= 0)
   this.startIndex = 0;
  else if (startIndex >= totalCount)
   this.startIndex = indexes[indexes.length - 1];
  else if (startIndex < 0)
   this.startIndex = 0;
  else {
   this.startIndex = indexes[startIndex / pageSize];
  }
 }

 public int getNextIndex() {
  int nextIndex = getStartIndex() + pageSize;
  if (nextIndex >= totalCount)
   return getStartIndex();
  else
   return nextIndex;
 }

 public int getPreviousIndex() {
  int previousIndex = getStartIndex() - pageSize;
  if (previousIndex < 0)
   return 0;
  else
   return previousIndex;
 }

 public int getPageCount() {
  int count = totalCount / pageSize;
  if (totalCount % pageSize > 0)
   count++;
  return count;
 }

 public int getCurentPageNum() {
  return getStartIndex() / pageSize + 1;
 }

}
在这个分页类中设定了每页要显示的记录数以及开始索引,如果用普通的jsp来取这个分页类的数据还可以,但是使用spring+hibernate这种架构就显得比较麻烦(原因是spring MVC返回的是一个 PaginationSupport的对象,使用jstl作为前端显示的话,会在jsp页面中掺杂大量的计算,像下一页索引,共多少条记录,当前第几页,共多少页等等会使jsp很难维护)下面是对这个类的改进:

public class  PaginationSupport {
 public final static int PAGESIZE = 30;

 private int pageSize = PAGESIZE;
 
 private int totalCount;

 private int currentPage;

 private int startIndex;
 
 private int[] indexes = new int[0];
 
 private int nextIndex;

 private int previousIndex;

 private int pageCount;

 private List items;
 
 private int lastIndex;
 
 public  PaginationSupport(int pageSize,
   int startIndex) {
  setPageSize(pageSize);
  setStartIndex(startIndex);
  
 }

 public  PaginationSupport(List items, int totalCount) {
  setPageSize(PAGESIZE);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(0);
 
 }

 public  PaginationSupport(List items, int totalCount, int startIndex) {
  setPageSize(PAGESIZE);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(startIndex);
  
 }

 public  PaginationSupport(List items, int totalCount, int pageSize,
   int startIndex) {
  setPageSize(pageSize);
  setTotalCount(totalCount);
  setItems(items);
  setStartIndex(startIndex);
  
 }

 
 public void setTotalCount(int totalCount) {
  if (totalCount > 0) {
   this.totalCount = totalCount;
   int count = totalCount / pageSize;
   if (totalCount % pageSize > 0)
    count++;
   indexes = new int[count];
   for (int i = 0; i < count; i++) {
    indexes[i] = pageSize * i;
   }
    } else {
   this.totalCount = 0;
  }
 }
 public int getTotalCount() {
  return totalCount;
 }
 public void setIndexes(int[] indexes) {
  this.indexes = indexes;
 }
 public int[] getIndexes() {
  return indexes;
 }

 
 public void setStartIndex(int startIndex) {
  if (totalCount <= 0)
   this.startIndex = 0;
  else if (startIndex >= totalCount)
   this.startIndex = indexes[indexes.length - 1];
  else if (startIndex < 0)
   this.startIndex = 0;
  else {
   this.startIndex = indexes[startIndex / pageSize];
  }
   }
 public int getStartIndex() {
  return startIndex;
 }

 
 public void setNextIndex(int nextIndex) {
  this.nextIndex = nextIndex;
 }
 public int getNextIndex() {
  int nextIndex = getStartIndex() + pageSize;
  if (nextIndex >= totalCount)
   return getStartIndex();
  else
   return nextIndex;
 }
 public void setPreviousIndex(int previousIndex) {
  this.previousIndex = previousIndex;
 }
 
 public int getPreviousIndex() {
  int previousIndex = getStartIndex() - pageSize;
  if (previousIndex < 0)
   return 0;
  else
   return previousIndex;
 }
 public void setPageCount(int pageCount) {
  this.pageCount = pageCount;
 }
 public int getPageCount() {
  int count = totalCount / pageSize;
  if (totalCount % pageSize > 0)
   count++;
  return count;
 }
 

 public int getCurrentPage() {
  return getStartIndex() / pageSize + 1;
 }

 public void setCurrentPage(int currentPage) {
  this.currentPage = currentPage;
 }

 public void setLastIndex(int lastIndex) {
  this.lastIndex =lastIndex ;
 }
 public int getLastIndex() {
  return indexes[indexes.length-1];
 }

 
 public int getPageSize() {
  return pageSize;
 }

 public void setPageSize(int pageSize) {
  this.pageSize = pageSize;
 }

 

 public List getItems() {
  return items;
 }

 public void setItems(List items) {
  this.items = items;
 }


}
以上是分页的封装类,下面是支持分页查询的方法:
1)
public PaginationSupport findPageByCriteria(
   final DetachedCriteria detachedCriteria, final int pageSize,
   final int startIndex) {
  return (PaginationSupport) getHibernateTemplate().execute(
    new HibernateCallback() {
     public Object doInHibernate(Session session)
       throws HibernateException {
      Criteria criteria = detachedCriteria
        .getExecutableCriteria(session);
      int totalCount = ((Integer) criteria.setProjection(
        Projections.rowCount()).uniqueResult())
        .intValue();
      criteria.setProjection(null);
      List items = criteria.setFirstResult(startIndex)
        .setMaxResults(pageSize).list();
      PaginationSupport ps = new PaginationSupport(items,
        totalCount, pageSize, startIndex);
      return ps;
     }
    }, true);
 }
2)
public  PaginationSupport findPageByQuery( final  String hsql,  final int pageSize,final int startIndex){
     return (PaginationSupport)getHibernateTemplate().execute(
     new  HibernateCallback() {
       public  Object doInHibernate(Session session)  throws  HibernateException, SQLException {
             Query query  =  session.createQuery(hsql);
             int totalCount=query.list().size();
             query.setFirstResult(startIndex);
             query.setMaxResults(pageSize);
             List items  = query.list();
          PaginationSupport ps = new PaginationSupport(items,
       totalCount, pageSize, startIndex);
          return ps;
            
             }
       },true);
  }
你也许会问分页查询为什么会提供两个方法,这两个方法有区别吗?其实这两个方法并无本质区别,DetachedCriteria 也是构造查询语句的与Query功能一致,但是它提供了更加面向对象的方法来写hsql语句。一般人们都倾向第一种方法,但是这种方法并不通用,它有一种查询并不支持,那就是当你要查询的对象并不是一个单一对象的话(例如 你在数据库中有两个表,一个是user,另一个是userinfo,这两个表所对应的对象在hiberante中被指定为共享主键的话,在执行查询的时候就会报类型转换异常,原因是查询出来的对象并不是user而是一个包含user 和userinfo的Object,你若强制把它转换成user类型,肯定会出错),这时你不得不采用第二个方法。当然这只是我个人见解,也许还有地方说的不是很准确,希望大家多多批评指正。
最后是这个分页类的前台显示源代码:
<%@ page language="java" contentType="text/html; charset=gbk"
    pageEncoding="GBK"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <link type="text/css" rel="stylesheet" href="../css/panel.css">
    <title>显示所有用户</title>
  </head>
 
  <body>
    <div style="margin:20px auto 30px; width:70%;"><a href="index.jsp" class="btn2">返回首页</a></div>
    <div style="margin:10px auto 0; width:70%;">
    <table width="100%" border="0" cellpadding="0" cellspacing="0">
    <caption>
      显示所有用户
    </caption>
    <tr>
      <td>用户ID</td>
      <td>用户名</td>
   <td>用户昵称</td>
      <td>电子邮件</td>
      <td>注册时间</td>
      <td>详细信息</td>
      <td>用户充值记录</td>
      <td>用户定制服务信息</td>
    </tr>
<c:forEach var="user" items="${userPage.items}">
 <tr>
   <td>${user.intId}</td>
      <td>${user.username}</td>
      <td>${user.name}</td>
      <td>${user.email}</td>
      <td><fmt:formatDate value='${user.creationTime}' pattern='yyyy-MM-dd HH:mm' /></td>
   <td><a href="user_getdetailUser.ado?userId=${user.intId}" class="btn">详细信息</a></td>
   <td><a href="orderService_getUserAccountAdds.ado?userId=${user.intId}" class="btn">用户充值记录</a></td>
   <td><a href="orderService_getUserChargeItems.ado?userId=${user.intId}" class="btn">用户定制服务信息</a></td>
 </tr>
</c:forEach>
  </table>
   <c:if test="${!empty userPage}">
     共${userPage.totalCount}记录
     <c:choose>
      <c:when test="${userPage.startIndex ne '0'}">
       <a href="user_getPage.ado?startIndex=0">首页</a>
      </c:when>
      <c:otherwise>
       首页
      </c:otherwise>
     </c:choose>
     <c:choose>
      <c:when test="${userPage.previousIndex lt userPage.startIndex}">
       <a href="user_getPage.ado?startIndex=${userPage.previousIndex }">上一页</a>
      </c:when>
      <c:otherwise>
       上一页
      </c:otherwise>
     </c:choose>
     <c:choose>
      <c:when test="${userPage.nextIndex>userPage.startIndex}">
       <a href="user_getPage.ado?startIndex=${userPage.nextIndex}">下一页</a>
      </c:when>
      <c:otherwise>
       下一页
      </c:otherwise>
     </c:choose>
     <c:choose>
      <c:when test="${userPage.lastIndex eq userPage.startIndex}">
       最后一页
      </c:when>
      <c:otherwise>
       <a href="user_getPage.ado?startIndex=${userPage.lastIndex}">最后一页</a>
      </c:otherwise>
     </c:choose>
     每页显示${userPage.pageSize}条记录
     当前第${userPage.currentPage }/${userPage.pageCount}页
  </c:if>
    </div>
  </body>
</html>


posted @ 2007-11-13 10:50 flustar 阅读(5346) | 评论 (6)编辑 收藏

dtree动态树+Javascript右键菜单(一)
1、从网上下载dtree控件。(好多地方都有的哦:P)
2、在Jbuilder中新建Web应用,命名为TreeLearing
3、解压缩dtree.rar包。
    把dtree目录拷贝至TreeLearing应用中。
    dtree目录下包括这些文件:example01.html 、 dtree.js 、 api.html 、 dtree.css 和img目录
    注意:除了api.html之外,其它的文件都是必须拷贝的。只有这个api.html是对dtree控件的函数介绍。
4、复制example01.html,并把粘贴后的文件重命名为Tree.jsp
:)  (保留原来的文件,以备参考是个好习惯哦~~)
注意dtree目录下的文件结构不要改变,否则树就不会正常显示
 
5、在Web应用中指定首页为Tree.jsp页面。
6、Tree.jsp中的代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
 <title>Destroydrop &raquo; Javascripts &raquo; Tree</title>
 <link rel="StyleSheet" href="dtree.css" type="text/css" />
 <script type="text/javascript" src="dtree.js"></script>
</head>
<body>
<h1><a href="/">Destroydrop</a> &raquo; <a href="/javascripts/">Javascripts</a> &raquo; <a href="/javascripts/tree/">Tree</a></h1>
<h2>Example</h2>
<div class="dtree">
 <p><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
 <script type="text/javascript">
  <!--
  d = new dTree('d');
  d.add(0,-1,'My example tree');
  d.add(1,0,'Node 1','example01.html');
  d.add(2,0,'Node 2','example01.html');
  d.add(3,1,'Node 1.1','example01.html');
  d.add(4,0,'Node 3','example01.html');
  d.add(5,3,'Node 1.1.1','example01.html');
  d.add(6,5,'Node 1.1.1.1','example01.html');
  d.add(7,0,'Node 4','example01.html');
  d.add(8,1,'Node 1.2','example01.html');
  d.add(9,0,'My Pictures','example01.html','Pictures I\'ve taken over the years','','','img/imgfolder.gif');
  d.add(10,9,'The trip to Iceland','example01.html','Pictures of Gullfoss and Geysir');
  d.add(11,9,'Mom\'s birthday','example01.html');
  d.add(12,0,'Recycle Bin','example01.html','','','img/trash.gif');
  document.write(d);
  //-->
 </script>
</div>
</body>
</html>
 
7、删除紫红色部分的代码,因为不需要哦。
8、注意看绿色和蓝色部分的代码,这才是真正为树添加节点的部分。
    d.add(0,-1,'My example tree');
    这一句为树添加了一个根节点,显示名称为'My example tree'
    d.add(1,0,'Node 1','example01.html');
    这一句在树的根节点下面添加了一个子节点。(d.add()方法的参数具体含义可参见api.html文件)
    常用的:
    第一个参数,表示当前节点的ID
    第二个参数,表示当前节点的父节点的ID
    第三个参数,节点要显示的文字
    第四个参数,点击该节点的超链接(注意也可以是某个servlet或是struts应用中的某个.do请求)
    第五个参数,鼠标移至该节点时显示的文字
    第六个参数,指定点击该节点时在哪个桢中打开超链接
    ……
9、运行应用程序。可以看到一棵漂亮的树。
原贴地址http://blog.sina.com.cn/u/4ae9618f010006y3

posted @ 2007-04-29 14:20 flustar 阅读(2084) | 评论 (0)编辑 收藏

仅列出标题
共6页: 上一页 1 2 3 4 5 6 下一页 

posts - 146, comments - 143, trackbacks - 0, articles - 0

Copyright © flustar