<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>Ihavegotyou</title>
    <description>an hourly worker</description>
    <link>http://ihavegotyou.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>设计模式在gwt中的应用</title>
        <author>Ihavegotyou</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ihavegotyou.javaeye.com">Ihavegotyou</a>&nbsp;
          链接：<a href="http://ihavegotyou.javaeye.com/blog/147419" style="color:red;">http://ihavegotyou.javaeye.com/blog/147419</a>&nbsp;
          发表时间: 2007年12月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong><span style="font-size: 18pt">设计模式在gwt中的应用</span></strong><br /><br /><br /><span style="color: olive">本文主要介绍gwt中的模式,或模式的应用。结合近一段时间项目的开发,演示一些示例。部分代码可能不够完整,但尽量保证能够阅读清晰。<br /><br />    按四人组对模式的分类:创建型1(1.1SingleTon,1.2Builder,ProtoType,Abstrct Factory,Factory Method),结构型2(2.1Decorator,2.1Composite,Proxy,Facade,Adapter,2.2Bridge,Flyweight),行为型3(3.1Observer,3.2Command,Strategy,State,Template Method,Visitor,Mediator,Memento,Chain of Responsibility,Interpreter,Iterator)<br />顺序进行描写。不求一一覆盖,只为抛砖引玉,期望和大家一起交流</span><br /><br /><br /><ul><span style="color: blue">1.1 SingleTon</span></ul><br />    问题: 目前项目有一个带分页功能的电影浏览,用户在页面间切换频率很大。造成server traffic.<br />    情景: 点上一页，下一页,都需要到服务器去取数据。<br />    解决方案: 在客户端设置cache,第一次访问后，存储当前页数据。当存储满100页数据时，清掉最早存储的数据,以更新数据和防止memory out.<br /><br /><br /><br /><pre name="code" class="java">/**
 * GWT of this version have no class LinkedHashMap,so class OrderedMap
 * implements much of LinkedHashMap's function. The class be used in cache
 * data. Attetion,the OrderedMap has only a global instance.
 * 
 */
public class OrderedMap implements IsSerializable {

	private static ArrayList keys = new ArrayList();

	private static HashMap map = new HashMap();
	
	private static OrderedMap singleton=new OrderedMap();
	
	private OrderedMap(){}
	
	public static OrderedMap getInstance(){
		return singleton;
	}

	public ArrayList getKeys() {
		return keys;
	}

	public Object put(Object key, Object value) {
		if (keys.contains(key)) {
			keys.remove(key);
		}
		keys.add(key);
		return map.put(key, value);
	}

	public Object remove(Object key) {
		keys.remove(key);
		return map.remove(key);
	}

	public Object remove(int index) {
		Object o = keys.get(index);
		return remove(o);
	}
	
	public void clear(){
		keys.clear();
		map.clear();
	}

	public Object get(Object key) {
		return map.get(key);
	}

	public boolean containsKey(Object key) {
		return map.containsKey(key);
	}

	public int size() {
		return map.size();
	}
}


/* &lt;p>
 *  first visit the data, store it.Then second visit,using the cache data.
 *  cached data when setMovieElement,using cache when click "cmdPreviousMovie","cmdNextMovie"
 *  and fetch more page once to reduce server traffic.
 *  attention,the first entry page per genre will not use cache forever!
 *&lt;/p>
 */
public class MovieGridWithCache extends MovieGrid {

	// use the symbol to decide to use cache or not
	protected class Symbol implements Cloneable {
		private String genreid; // movie grenre id

		private String currentpage;

		private String languageid; // moveie language id

		public String getCurrentpage() {
			return currentpage;
		}

		public void setCurrentpage(String currentpage) {
			this.currentpage = currentpage;
		}

		public String getGenreid() {
			return genreid;
		}

		public void setGenreid(String genreid) {
			this.genreid = genreid;
		}

		public String getLanguageid() {
			return languageid == null ? "" : languageid;
		}

		public void setLanguageid(String languageid) {
			this.languageid = languageid;
		}

		public Symbol(String genreid, String currentpage, String languageid) {
			this.genreid = genreid;
			this.currentpage = currentpage;
			this.languageid = languageid == null ? "" : languageid;
		}

		public Symbol() {
		}

		public Object clone() {
			Symbol o = new Symbol();
			o.genreid = new String(this.genreid == null ? "" : this.genreid);
			o.languageid = new String(this.languageid == null ? ""
					: this.languageid);
			o.currentpage = new String(this.currentpage == null ? ""
					: this.currentpage);
			return o;
		}

		public boolean equals(Object o) {
			if (this == o)
				return true;
			if (o == null)
				return false;
			if (o instanceof Symbol) {
				Symbol symbol = (Symbol) o;
				return (symbol.genreid.equals(this.genreid)
						&& symbol.languageid.equals(this.languageid) && symbol.currentpage
						.equals(this.currentpage));
			} else
				return false;
		}

		// define the hashCode because of using as a Map key,otherwish, the
		// map.get(key) get the null value.
		public int hashCode() {
			int hash = 1;
			hash = hash * 31 + genreid == null ? 0 : genreid.hashCode();
			hash = hash * 29 + languageid == null ? 0 : languageid.hashCode(); 
			hash = hash * 23 + currentpage == null ? 0 : currentpage.hashCode();
			return hash;
		}
	}
	
	protected final static int PAGE_NUMBER=3; // fetch more page to reduce server traffic

	protected final static int maxCacheSize = 100; // that's to say: store 100 page data.

	// the map store pageId,genreid,languageid and _movieList
	protected static OrderedMap cache = OrderedMap.getInstance();

	public MovieGridWithCache(ScreenData screenData, String genreid,
			String movielanguageid) {
		super(screenData, genreid, movielanguageid);
	}

	// it's a Callback,be used in class MovieDataAccess
	public void setMovieElement(JSONValue jsonMovies) {
			_movieList = MovieDataAccess.JSON2MovieDTO(jsonMovies);
			if (_currentPage ==0)
			showPage();
			cachePage();
	}

	public void showPage(int page) {
		super.showPage(page);
	}

	public void showPage() {
		showPage(0);
	}

	/**
	 * Attention! As the first entry of page ,it will not use the cache!!
	 * 
	 * @param genreid
	 * @param movielanguageid:
	 *            if null or blank,fetch all movielanguage
	 */
	public void ShowPageByGenreWithCache(String genreid, String movielanguageid) {
		_currentPage = 0;
		this._genreID = genreid;
		this._movielanguageID = movielanguageid;
		_movieDataAccess = new MovieDataAccess(this, Integer.toString(_currentPage), Integer
						.toString(PAGE_SIZE), _genreID, movielanguageid,Integer.toString(PAGE_NUMBER));
		//showPage();
	}

	protected void nextPage() {
		_currentPage++;
		Symbol symbol = (Symbol) new Symbol(_genreID, _movielanguageID, Integer
				.toString(_currentPage)).clone();
		if (!cache.containsKey(symbol)) {
			_movieDataAccess = new MovieDataAccess(this, Integer.toString(_currentPage), Integer
							.toString(PAGE_SIZE), _genreID, _movielanguageID,Integer.toString(PAGE_NUMBER));
		} else {
			_movieList = (ArrayList) cache.get(symbol);
			cmdPreviousMovie.setLabel("&lt;(" + (_currentPage + 1) + "/"
					+ _totalPage + ")");
			cmdNextMovie.setLabel(">(" + (_currentPage + 1) + "/" + _totalPage
					+ ")");
			cmdPreviousMovie.setVisible(_currentPage > 0);
			cmdNextMovie
					.setVisible((_currentPage + 1) * PAGE_SIZE &lt; _totalSize);
		}
		showPage(_currentPage);
	}

	protected void prevPage() {
		// prevent access to -ve item number
		if (_currentPage > 0) {
			_currentPage--;
			Symbol symbol = (Symbol) new Symbol(_genreID, _movielanguageID,
					Integer.toString(_currentPage)).clone();
			if (!cache.containsKey(symbol)) {
				_movieDataAccess = new MovieDataAccess(this,  Integer.toString(_currentPage), Integer
								.toString(PAGE_SIZE), _genreID,
						_movielanguageID,Integer.toString(PAGE_NUMBER));
			} else {
				_movieList = (ArrayList) cache.get(symbol);
				cmdPreviousMovie.setLabel("&lt;(" + (_currentPage + 1) + "/"
						+ _totalPage + ")");
				cmdNextMovie.setLabel(">(" + (_currentPage + 1) + "/"
						+ _totalPage + ")");
				cmdPreviousMovie.setVisible(_currentPage > 0);
				cmdNextMovie
						.setVisible((_currentPage + 1) * PAGE_SIZE &lt; _totalSize);
			}
			showPage(_currentPage);
		}
	}

	protected class NextPageCommand implements Command {

		public void execute() {
			nextPage();

		}
	}

	protected class PreviousPageCommand implements Command {

		public void execute() {
			prevPage();
		}
	}

	// save the movielist when have got data,storing much page once!
	protected void cachePage() {
		Iterator it = _movieList.iterator();
		int iPageNum=_movieList.size()/MovieGrid.PAGE_SIZE;
		if(_movieList.size()%MovieGrid.PAGE_SIZE>0)
			iPageNum++;
		ArrayList[] list = new ArrayList[iPageNum];
		for(int i=0;i&lt;list.length;i++)
			list[i]=new ArrayList();
		int iMovieNum=0;
		int iCurrentPage=_currentPage;
		int index=0;
		while (it.hasNext()) {
			MovieData movieData = (MovieData) ((MovieData) it.next()).clone();
			index=iMovieNum /MovieGrid.PAGE_SIZE;
			iCurrentPage=_currentPage+index;
			list[index].add(movieData);
			if (iMovieNum%MovieGrid.PAGE_SIZE==0){
				Symbol symbol = (Symbol) new Symbol(_genreID, _movielanguageID, Integer
						.toString(iCurrentPage)).clone();
				//if stored beyond maxCacheSize page data,remove the earliest page.
				if(cache.size()>=maxCacheSize)
					cache.remove(0);
				cache.put(symbol, list[index]);
				
			}
			iMovieNum++;
		}
		if (_movieList.size()%MovieGrid.PAGE_SIZE!=0){
			Symbol symbol = (Symbol) new Symbol(_genreID, _movielanguageID, Integer
					.toString(iCurrentPage)).clone();
			//if stored beyond maxCacheSize page data,remove the earliest page.
			if(cache.size()>=maxCacheSize)
				cache.remove(0);
			cache.put(symbol, list[index]);
			
		}
	}
	
}
</pre><br /><br />上述构造和应用一个全局的Cache实例(OrderedMap)。<br /><br /><br /><br /><ul><span style="color: blue">1.2 Builder</span></ul><br /><br /><pre name="code" class="java">public void call() {
        // Establish an Async service call
        //final ServiceAsync service = (ServiceAsync) GWT.create(Service.class);
        //ServiceDefTarget target = (ServiceDefTarget) service;

        //target.setServiceEntryPoint(GWT.getModuleBaseURL()+ROI_SERVICE_URL);

        //service.call(instr, timeout, dataParameterName, jsonROIParam.toString() , roih );
        if ( roiCallback != null ) {
            roiHandler = new ROIResponseHandler(getProxyInstruction(),
                                                roiCallback);

            RequestBuilder builder = new RequestBuilder(
                    RequestBuilder.POST,
                    GWT.getModuleBaseURL()+ROI_SERVICE_URL);

            try {
                String URLParam;

                // setup the proxy instruction
                URLParam = ROI.PROXY_INSTRUCTION + "=" +
                           URL.encodeComponent(proxyInstruction) + "&";

                URLParam += JSON_REQUEST_DTO + "="
                         +  URL.encodeComponent(jsonROIParam.toString()) + "&";

                // setting up necessary parameters
                builder.setTimeoutMillis(DEFAULT_TIME_OUT);
                builder.setHeader(HTTP_CONTENT_TYPE, HTTP_CONTENT_TYPE_VALUE);
                builder.setHeader(HTTP_CONNECTION, HTTP_CONNECTION_TYPE);

                httpResponse = builder.sendRequest(URLParam, roiHandler);

            } catch (RequestException e) {
                // if I have an exception, on client side, there is nothing I can do!
                // Window.alert("Failed to send the request: " + e.getMessage());
            }
        } // else - callback is not defined, don't do the call

    }
    </pre><br />    <br />上述描述了Rpc call 采用 RequestBuilder,以方便统一处理.<br /><br /><br /><ul><span style="color: blue">2.1 Decorator && Composite</span></ul><br /><pre name="code" class="java">/**
 * Page is the abstract class that handles displaying and validation of a page.
 * Each page is a singleton object and has an associated PageInfo class.  This
 * PageInfo class is responsible for instantiating each Page.
 */
public abstract class Page extends Composite implements HasDataListeners {
    
    protected String     _token        = "";		// _token is the associated history token for this page
    protected Screen     _parent       = null;		// _parent is the screen that contains this page
    protected ScreenData _data         = null;		// _data contains all of the server variables for this page
    protected ArrayList  _dataNames    = new ArrayList();	    // _dataNames is all the names of the maintained variables for this page

    ...
    
    
    /**
     * PageInfo is an abstract class that is responsible for accessing each Page
     * object.  Each page should have it's own PageInfo derived class that
     * implements createInstance.  If the page is an entry point for the
     * associated screen, it should overload isEntryPage(), returning true.  For
     * example, the first step in the SignUpMember screen is the only entry page
     * for that screen.
     */
    public abstract static class PageInfo {
        protected Page   _instance;
        protected String _token;				// history token display on the browser's address bar
        protected Screen _parent;				// the screen that owns this...

        public PageInfo(String token, Screen parent) {
            _token  = token;
            _parent = parent;
        }

        public abstract Page createInstance();

        public String getToken() {
            return _token;
        }

        public String getFullHistoryToken() {
            return _parent.getName() + CommonDefn.HTML_SCREEN_SEPERATOR + getToken();
        }

        public final Page getInstance() {
            if (_instance == null) {
                _instance = createInstance();
            }
            return _instance;
        }

        /**
         * Indicates whether or not the associated page can be navigated to
         * directly from another screen.
         * Override this method for all entry pages.
         * 
         * Basically, if 'false' it also means that the page is not allowed to be book-marked. 
         */
        public boolean isEntryPage() {
            return false;
        }
    }

}</pre><br /><br /><br />   在Screen class也有上述类似代码,每个Page属于一个相关Screen, 一个Screen有当前Page,Screen也负责show / hide Page.<br />充分利用了组合和装饰。<br /><br /><br /><ul><span style="color: blue">2.2 Bridge</span></ul><br /><pre name="code" class="java">public class DataTable extends Composite {
    private static final String CSS_DATATABLE            = "datatable";
    private static final String CSS_DATATABLE_ROW_HEADER = "datatable-row-header";
    private static final String CSS_DATATABLE_ROW_EVEN   = "datatable-row-even";
    private static final String CSS_DATATABLE_ROW_ODD    = "datatable-row-odd";

    public class ColumnInfo {
        private static final int COL_LABEL  = 0;
        private static final int COL_BUTTON = 1;
        private String  _name;
        private String  _styleName;
        private String  _dataName;
        private int     _colType;
        private HashMap _dataMap;

        public ColumnInfo(String  name,
                          String  styleName,
                          String  dataName,
                          int     colType,
                          HashMap dataMap) {
            _name      = name;
            _styleName = styleName;
            _dataName  = dataName;
            _colType   = colType;
            _dataMap   = dataMap;
        }

        public String getDataName() {
            return _dataName;
        }

        public String getName() {
            return _name;
        }

        public String getStyleName() {
            return _styleName;
        }

        public String getLabel(String value) {
            if (_dataMap != null) {
                return (String)_dataMap.get(value);
            }
            return value;
        }

        public boolean isButton() {
            return _colType == COL_BUTTON;
        }

        public boolean isLabel() {
            return _colType == COL_LABEL;
        }
    }

    public interface DataTableButtonCommand extends Command {
        public DataTableButtonCommand clone();
        public String getParam();
        public void setParam(String param);
    }

    protected int       _tableSize = 0;
    protected ArrayList _columnInfo  = null;
    protected FlexTable _table = null;

    public DataTable(int tableSize) {
        _tableSize = tableSize;
        _columnInfo = new ArrayList();

        _table = new FlexTable();

        // Insert the header row
        _table.insertRow(0);
        _table.getRowFormatter().addStyleName(0, CSS_DATATABLE_ROW_HEADER);

        _table.setStyleName(CSS_DATATABLE);

        initWidget(_table);
    }

    public void addColInfo(String name, String styleName, String dataName) {
        addColInfo(name, styleName, dataName, (HashMap)null);
    }

    public void addColInfo(String name, String styleName, String dataName,
                           HashMap dataMap) {
        ColumnInfo colInfo = new ColumnInfo(name, styleName,
                                            dataName, ColumnInfo.COL_LABEL,
                                            dataMap);
        _columnInfo.add(colInfo);

        int newColNum = _table.getCellCount(0);

        OverflowLabel headerLabel = new OverflowLabel(name,
                                                      OverflowLabel.LABEL_NONE);
        _table.setWidget(0, newColNum, headerLabel);
        String cellStyleName = CSS_DATATABLE + "-" + colInfo.getStyleName();
        setStyleName(headerLabel.getElement(), cellStyleName, true);

        for (int row=1; row&lt;=_tableSize; ++row) {
            OverflowLabel label
                    = new OverflowLabel("",
                                          OverflowLabel.LABEL_ELLIPSES
                                        | OverflowLabel.LABEL_POPUP);
            _table.setWidget(row, newColNum, label);
            _table.getCellFormatter().addStyleName(row, newColNum, styleName);

            if (newColNum == 0) {
                String rowStyle =   (row % 2 == 0)
                                  ? CSS_DATATABLE_ROW_EVEN
                                  : CSS_DATATABLE_ROW_ODD;
                _table.getRowFormatter().addStyleName(row, rowStyle);
                label.setHTML(" ");
            }
        }
    }

    public void addColInfo(String label, String styleName, String dataName, DataTableButtonCommand command) {

        ColumnInfo colInfo = new ColumnInfo(label, styleName,
                                            dataName, ColumnInfo.COL_BUTTON,
                                            null);
        _columnInfo.add(colInfo);
        int newColNum = _table.getCellCount(0);

        OverflowLabel headerLabel = new OverflowLabel(label,
                                                      OverflowLabel.LABEL_NONE);
        _table.setWidget(0, newColNum, headerLabel);
        String cellStyleName = CSS_DATATABLE + "-" + colInfo.getStyleName();
        setStyleName(headerLabel.getElement(), cellStyleName, true);

        for (int row=1; row&lt;=_tableSize; ++row) {
            CommandPushButton button = new CommandPushButton(label);
            button.setCommand(command.clone());
            button.setVisible(false);
            _table.setWidget(row, newColNum, button);
            _table.getCellFormatter().addStyleName(row, newColNum, styleName);

            if (newColNum == 0) {
                String rowStyle =   (row % 2 == 0)
                                  ? CSS_DATATABLE_ROW_EVEN
                                  : CSS_DATATABLE_ROW_ODD;
                _table.getRowFormatter().addStyleName(row, rowStyle);
            }
        }

    }

    protected void populateRow(int rowNum, JSONValue rowValue) {
        JSONObject row = rowValue.isObject();
        assert(row != null);

        for (int col=0; col&lt;_columnInfo.size(); ++col) {
            ColumnInfo colInfo = (ColumnInfo)_columnInfo.get(col);
            String value = JSONHelper.getString(row, colInfo.getDataName());
            if (colInfo.isLabel()) {
                OverflowLabel label = null;
                label = (OverflowLabel)_table.getWidget(rowNum+1, col);
                value = colInfo.getLabel(value);
                label.setHTML(value);
            } else if (colInfo.isButton()) {
                CommandPushButton button = null;
                button = (CommandPushButton)_table.getWidget(rowNum+1, col);
                button.setVisible(true);
                DataTableButtonCommand command = null;
                command = (DataTableButtonCommand)button.getCommand();
                command.setParam(value);
            } else {
                assert false;
            }
        }
    }

    public void populateTable(JSONValue rowValues) {
        JSONArray rows = rowValues.isArray();
        assert(rows != null);
        for (int row=0; row&lt;rows.size() && row&lt;20; ++row) {
            populateRow(row, rows.get(row));
        }
        clearEmpties(rows.size());
    }

    protected void clearEmpties(int emptyStart) {
        for (int emptyRow=emptyStart; emptyRow&lt;_tableSize; ++emptyRow) {
            for (int col=0; col&lt;_columnInfo.size(); ++col) {
                ColumnInfo colInfo = (ColumnInfo)_columnInfo.get(col);
                Widget widget = _table.getWidget(emptyRow+1, col);
                if (colInfo.isButton()) {
                    widget.setVisible(false);
                } else if (colInfo.isLabel()) {
                    OverflowLabel label = (OverflowLabel)widget;
                    label.setHTML(" ");
                }
            }
        }
    }
}
</pre><br /><br /><br />上述的CommandPushButton has-a push command,通过这个桥,就把实现类和DataTableButtonCommand 连接起来了.<br /><br /><br /><br /><ul><span style="color: blue">3.1 Observer</span></ul><br />    该模式是UI中最常见的,凡是xxxListern基本都是.<br />    <br />    问题: 在页面数据较多的页面，当用户Forward first,then go back,将被迫再次从server取数据.<br />    情景: 再我们的preShowPage中，写有很多fetch data from server. 这里在go back 时也会执行。<br />    解决方案: hook go back! Add history listern. 当前浏览地址发生变化的时候通知我。<br />    <br />    <br />  <pre name="code" class="java">public class MovieByGenrePage extends Page implements HistoryListener {
	private static final String CSS_RENTAL_MOVIEBYGENRE = "rental-moviebygenre";
	private static final String CSS_RENTAL_MOVIEBYRENREGRID = "rental-moviebygenregrid";

	private  MovieGrid _movieGrid = null;
	private HTML _title;
	private String _from = ""; //record the html referrer.
	
	private static final String FROM = CommonDefn.SCREEN_RENTAL + CommonDefn.HTML_SCREEN_SEPERATOR + CommonDefn.PAGE_MOVIE_GENRE;
	private static final String CHECKOUT=CommonDefn.SCREEN_RENTAL + CommonDefn.HTML_SCREEN_SEPERATOR +CommonDefn.PAGE_COMPLETED_RENTAL;
	
	public static PageInfo init(final Screen parent,final ScreenData data) {
		return new PageInfo( CommonDefn.PAGE_MOVIE_BY_GENRE, parent ) {
			public Page createInstance() {
				return new MovieByGenrePage( CommonDefn.PAGE_MOVIE_BY_GENRE,parent, data );
			}
		};
	}

    public MovieByGenrePage(String token, Screen parent, ScreenData data) {
        super(token, parent, data);
        History.addHistoryListener(this); //i want to know this page came from which.

        // A vertical layout.  
        VerticalPanel pageContentPanel = new VerticalPanel();

        // Title
    	{
    		_title = new HTML("");
	        pageContentPanel.add( _title );
	        pageContentPanel.setCellHorizontalAlignment( _title, VerticalPanel.ALIGN_CENTER );
	        
	        _movieGrid = new MovieGrid(data,data.getValue( Rental.DATA_RENTAL_GENRESELECTION_GENREID ),_data.getValue( Rental.DATA_RENTAL_MOVIELANGUAGESELECTION_MOVIELANGUAGEID ) );
	        _movieGrid.setStyleName( CSS_RENTAL_MOVIEBYRENREGRID );
	        pageContentPanel.add( _movieGrid );
	        pageContentPanel.setCellHorizontalAlignment( _movieGrid, VerticalPanel.ALIGN_CENTER );
    	}    
    	
        initWidget( pageContentPanel );

        setStyleName( CSS_RENTAL_MOVIEBYGENRE );
    }
    
    //just implement the function of the html referrer
    public void onHistoryChanged( String historyToken ){
    	// from is the referrer of this page,to is this page!
    	_from=historyToken;
    	//System.out.println("_from="+_from);

    	// if the referrer page is mainmenu or the default screen, reset the genreid.
    	if ( _from.equals(CommonDefn.SCREEN_DEFAULT_STARTUP) ||
   			 _from.equals(CommonDefn.SCREEN_DEFAULT_STARTUP + CommonDefn.HTML_SCREEN_SEPERATOR) ||
    		 _from.equals(CommonDefn.SCREEN_MAIN_MENU)) {
    		_data.setValue(Rental.DATA_RENTAL_GENRESELECTION_GENREID,"",null);	
    		//System.out.println(_from);
    	}
    }
    

    
    public void preShowPageExecute() {
    	
    	if ( _data.getValue(Rental.DATA_RENTAL_GENRESELECTION_GENREID).equals("") ) {
    		// the first time I have not gotton it from server yet, that's why I hard-coded the default here...
      	  _data.setValue(Rental.DATA_RENTAL_GENRESELECTION_GENREID,CommonDefn.DEFAULT_GENRE_ID,null);
    	}
    	
    	if ( _data.getValue(Rental.DATA_RENTAL_MOVIELANGUAGESELECTION_MOVIELANGUAGEID).equals("") ) {
      	  _data.setValue( Rental.DATA_RENTAL_MOVIELANGUAGESELECTION_MOVIELANGUAGEID,CommonDefn.DEFAULT_MOVIE_LANGUAGE_ID,null );
    	}

    	if ( _from.length()&lt;1 || _from.equals(FROM) || _from.equals(CHECKOUT) || _from.equals(CommonDefn.SCREEN_MAIN_MENU)) {
    		//_from.length()&lt;1,it's screen redire to this page! another flow is from search to this page, otherwise it's goto this page.
        	//for goto we do nothing,just show it's orignal model nor fetch data from server. 
	        _movieGrid.updateGenreAndLanguageID( _data.getValue( Rental.DATA_RENTAL_GENRESELECTION_GENREID ),_data.getValue( Rental.DATA_RENTAL_MOVIELANGUAGESELECTION_MOVIELANGUAGEID ) );
    	}
    	
     
   
    
}
</pre><br /><br />另外利用ChangeListener,ChangeListenerCollection,fireChange 制作一个mvc模式的Validator组件也是必要的.<br /><br /><br />[list=]<span style="color: blue">3.2 Command</span>[/list]<br />   原型: Interface Command {<br />      public void execute();<br />   }<br /><br /><br />    问题: 可能需要定时任务.<br />    情景: Context help content -tips 需要定时关闭(其他地方也需要定时任务,但任务可能未知:( )<br />    解决方案: 只要任务实现 Command,然后动态传入Command 实例即可.<br />    <br />    <br />    <br />    <pre name="code" class="java">public Trigger extends Timer implements Command{
      private int _delay;
      private Command _command;
      
      public Trigger(int delay,Command command){
        _delay = delay;
        _command = command;
      }
      
      public void run() {
          _command.execute();
      }
      
      
      public void execute(){
        this.schedule(_delay);
      }
    
    }</pre><br />    <br />   Trigger既实现了一个对外的公开接口,也提供一个constructor 接口.所以，有时候方便别人也是方便自己. <img src="/images/smiles/icon_biggrin.gif"/>
          <br/>
          <span style="color:red;">
            <a href="http://ihavegotyou.javaeye.com/blog/147419#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 10 Dec 2007 23:31:16 +0800</pubDate>
        <link>http://ihavegotyou.javaeye.com/blog/147419</link>
        <guid>http://ihavegotyou.javaeye.com/blog/147419</guid>
      </item>
      <item>
        <title>从DOM 看gwt</title>
        <author>Ihavegotyou</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ihavegotyou.javaeye.com">Ihavegotyou</a>&nbsp;
          链接：<a href="http://ihavegotyou.javaeye.com/blog/137759" style="color:red;">http://ihavegotyou.javaeye.com/blog/137759</a>&nbsp;
          发表时间: 2007年11月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div align="center"><span style="background-color: rgb(204, 153, 255);"><span style="background-color: rgb(204, 153, 255);"></span><strong>从DOM 看gwt</strong></span><br />
<span style="background-color: rgb(204, 153, 255);"></span></div>
<span style="background-color: rgb(204, 153, 255);"> <br />
</span><hr size="2" width="100%" />
<span style="background-color: rgb(204, 153, 255);"><span style="background-color: rgb(204, 153, 255);"><span style="background-color: rgb(192, 192, 192);"><br />
<br />
<font color="#c0c0c0">序言:这篇文章首先介绍DOM(Document Object Model),然后进入GWT的DOM 对象主题。进而说明gwt构建于&quot;one page application&quot;之上与传统Web构建以及带UI 的Application的联系与区别。然后重点转移到我们能够利用DOM做点什么,最后分析总结:DOM对组件设计人员、组件使用人员,美工设计师 (deal wtih Image &amp;&amp; CSS)引起的微妙变化。</font></span></span></span><br />
<br />
<ul>
    <li>What is the DOM?</li>
</ul>
<font color="#0000ff">&quot;The W3C Document Object Model (DOM) is a platform and language-neutral interface that allows programs and scripts to dynamically access and update the content, structure, and style of a document.&quot;</font><br />
<br />
The W3C DOM provides a standard set of objects for HTML and XML documents, and a standard interface for accessing and manipulating them.<br />
<br />
The W3C DOM is separated into different parts (Core, XML, and HTML) and different levels (DOM Level 1/2/3):<br />
<br />
Core DOM - defines a standard set of objects for any structured document<br />
XML DOM - defines a standard set of objects for XML documents<br />
HTML DOM - defines a standard set of objects for HTML documents<br />
<br />
更多参考资料:<a href="http://www.w3schools.com/dom/default.asp">www.w3schools.com/dom/default.asp</a><br />
<br />
<ul>
    <li>How about the gwt DOM?</li>
</ul>
<font color="#0000ff">It's a class.This class provides a set of static methods that allow you to manipulate the browser's Document Object Model (DOM). It contains methods for manipulating both elements and events.<br />
简单说,它就是把HTML DOM 封装成了Java 对象, 进而可以处理html 元素和事件。</font><br />
<br />
<ul>
    <li> gwt==one page application?</li>
</ul>
是的,gwt是构建于one page application之上.这里暂不讨论gwt这样设计的原委。有人就会怀疑,既然这样,还能指望他做出复杂的应用? 答案是肯定的。<br />
<br />
首先,它和我们传统的做法(web or application)是一样的,gwt是从the host page开始的(它也是the only page),和我们的welcome page一样,或者 application(mainForm or loginEntry)一样。From a entrance into the world.<br />
<br />
其次,gwt依赖DOM动态创建web组件。熟悉DOM的应该清楚,一个Element里面可以含有一个另一个异常复杂的Element,比如 Iframe,InnerHtml。有过Application UI 编程经验的，也应该知道 a container 能放入一个复杂的control, 或 another container 。<br />
<br />
所以，尽管看起来gwt是one page application,但你要做到多页的效果其实也是不难的。<br />
<br />
<ul>
    <li>What can we do by using DOM?</li>
</ul>
<font color="#0000ff">答案前面就说了,我们可以利用DOM处理 element and its events.</font>小到设置元素属性1),大到设计组件2)...下面举例说明.<br />
<br />
<br />
1) <span style="background-color: rgb(204, 153, 255);">
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<ol class="dp-j" start="1">
    <li class="alt"><span><span>Image logo = </span><span class="keyword">new</span><span> Image(aPATH);</span></span></li>
    <li class=""><span>DOM.setElementProperty(logo.getElement(), HTML_ID_TOKEN, HTML_LOGO_IDENTIFIER);  <br />
    </span></li>
</ol>
</div>
</span><br />
<br />
2)<br />
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar"> </div>
<ol class="dp-j" start="1">
    <li class="alt"><span><span> </span><span class="keyword">import</span><span> com.google.gwt.user.client.DOM;  </span></span></li>
    <li class=""><span><span class="keyword">import</span><span> com.google.gwt.user.client.Element;  </span></span></li>
    <li class="alt"><span><span class="keyword">import</span><span> com.google.gwt.user.client.ui.FlowPanel;  </span></span></li>
    <li class=""><span>  </span></li>
    <li class=""><span>  </span><span><span class="comment">/*</span></span></li>
    <li class=""><span class="postbody">     </span></li>
    <li class=""><span><span class="comment"> * The GroupBoxPanel is extend the flow panel and add </span></span><span><span class="comment">〈</span></span><span><span class="comment">fieldset</span></span><span><span class="comment">〉</span></span><span><span class="comment"> and </span></span><span><span class="comment">〈</span></span><span><span class="comment">legend</span></span><span class="postbody"><span><span class="comment">〉</span></span></span><span><span class="comment"> tags around the panel element. </span> </span></li>
    <li class="alt"><span><span class="comment"> * Add Control in the container,the Align is default as flow.</span> <br />
    </span></li>
    <li class=""><span class="postbody">     </span></li>
    <li class=""><span><span class="comment"> <fieldset>  <legend>some issue here <br />
    </legend></fieldset></span></span></li>
    <li class="alt"><span><span class="comment"> * </span> </span></li>
    <li class="alt"><span><span class="comment"> */</span><span>  </span></span></li>
    <li class=""><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> GroupBoxPanel </span><span class="keyword">extends</span><span> FlowPanel {  </span></span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">private</span><span> Element legend;  </span></span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> GroupBoxPanel() {  </span></span></li>
    <li class="alt"><span>        Element fieldset = DOM.createFieldSet();  </span></li>
    <li class=""><span>        <span class="keyword">this</span><span>.legend = DOM.createLegend();  </span></span></li>
    <li class="alt"><span>        DOM.appendChild(fieldset, legend);  </span></li>
    <li class=""><span>        setElement(fieldset);  </span></li>
    <li class="alt"><span>    }  </span></li>
    <li class=""><span>     </span></li>
    <li class="alt"><span>    <span class="keyword">public</span><span> GroupBoxPanel(String caption) {  </span></span></li>
    <li class=""><span>        <span class="keyword">this</span><span>();  </span></span></li>
    <li class="alt"><span>        setCaption(caption);  </span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>     </span></li>
    <li class=""><span>  </span></li>
    <li class="alt"><span>    <span class="keyword">public</span><span> String getCaption() {  </span></span></li>
    <li class=""><span>        <span class="keyword">return</span><span> DOM.getInnerText(</span><span class="keyword">this</span><span>.legend);  </span></span></li>
    <li class="alt"><span>    }  </span></li>
    <li class=""><span>  </span></li>
    <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setCaption(String caption) {  </span></span></li>
    <li class=""><span>        DOM.setInnerHTML(<span class="keyword">this</span><span>.legend, caption);  </span></span></li>
    <li class="alt"><span>    }  </span></li>
    <li class=""><span>}  </span></li>
</ol>
</div>
<br />
<br />
从上面的例子,我们可以真正领略组件式编程的威力.<br />
<br />
<br />
<ul>
    <li>confuse,scare?</li>
</ul>
利用DOM进行扩展,多少会使得一些人迷惑或恐慌。gwt不是宣称简单即美么? 是的.你熟悉HTML DOM &amp;&amp; gwt DOM,你就可以构造出复杂，实用的组件。你熟悉the basic gwt widget library,你也可以构造出复杂应用。对于美工呢? 基于one page application的设计更方便美工设计images and css. 至少可以使得美工设计师不会再从一个页面跳到另一个页面去看html source(推荐使用firefox+firebug).方便了对界面的整体把握,也方便其对业务流程的了解(这里不再说明这些人员间的沟通)。<font color="#0000ff">总之,DOM 使得人尽其才，物尽其用，所司所长。<br />
<br />
<br />
</font>
<div align="right"><font color="#ff99cc">如果文章提到的相关环节有问题,请通知我</font></div>
          <br/>
          <span style="color:red;">
            <a href="http://ihavegotyou.javaeye.com/blog/137759#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 03 Nov 2007 13:31:31 +0800</pubDate>
        <link>http://ihavegotyou.javaeye.com/blog/137759</link>
        <guid>http://ihavegotyou.javaeye.com/blog/137759</guid>
      </item>
      <item>
        <title>gwt Client-Server 交互原形模型</title>
        <author>Ihavegotyou</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ihavegotyou.javaeye.com">Ihavegotyou</a>&nbsp;
          链接：<a href="http://ihavegotyou.javaeye.com/blog/132528" style="color:red;">http://ihavegotyou.javaeye.com/blog/132528</a>&nbsp;
          发表时间: 2007年10月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span class="postbody">gwt Client-Server 交互原形模型<br />
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-xml" start="1">
    <li class="alt"><span><span class="comments">&lt;!--web.xml--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="tag">&lt;?</span><span class="tag-name">xml</span><span>&nbsp;</span><span class="attribute">version</span><span>=</span><span class="attribute-value">&quot;1.0&quot;</span><span>&nbsp;</span><span class="attribute">encoding</span><span>=</span><span class="attribute-value">&quot;UTF-8&quot;</span><span class="tag">?&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">web-app</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">&quot;WebApp_ID&quot;</span><span>&nbsp;</span><span class="attribute">version</span><span>=</span><span class="attribute-value">&quot;2.4&quot;</span><span>&nbsp;</span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">&quot;http://java.sun.com/xml/ns/j2ee&quot;</span><span>&nbsp;</span><span class="attribute">xmlns:xsi</span><span>=</span><span class="attribute-value">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><span>&nbsp;</span><span class="attribute">xsi:schemaLocation</span><span>=</span><span class="attribute-value">&quot;http://java.sun.com/xml/ns/j2ee&nbsp;http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">display-name</span><span class="tag">&gt;</span><span>ccgwt</span><span class="tag">&lt;/</span><span class="tag-name">display-name</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">welcome-file-list</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>index.html</span><span class="tag">&lt;/</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>index.htm</span><span class="tag">&lt;/</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>index.jsp</span><span class="tag">&lt;/</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>default.html</span><span class="tag">&lt;/</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>default.htm</span><span class="tag">&lt;/</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>default.jsp</span><span class="tag">&lt;/</span><span class="tag-name">welcome-file</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">welcome-file-list</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">servlet</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">servlet-name</span><span class="tag">&gt;</span><span>dealwith</span><span class="tag">&lt;/</span><span class="tag-name">servlet-name</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">servlet-class</span><span class="tag">&gt;</span><span>response.DealWith</span><span class="tag">&lt;/</span><span class="tag-name">servlet-class</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">servlet</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">servlet-mapping</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">servlet-name</span><span class="tag">&gt;</span><span>dealwith</span><span class="tag">&lt;/</span><span class="tag-name">servlet-name</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">url-pattern</span><span class="tag">&gt;</span><span>*.do</span><span class="tag">&lt;/</span><span class="tag-name">url-pattern</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;/</span><span class="tag-name">servlet-mapping</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="tag">&lt;/</span><span class="tag-name">web-app</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span><span class="comments">&lt;!--index.jsp--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="tag">&lt;</span><span>%@&nbsp;page&nbsp;</span><span class="attribute">contentType</span><span>=</span><span class="attribute-value">&quot;text/html;&nbsp;charset=GBK&quot;</span><span>%</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">html</span><span>&nbsp;</span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">&quot;http://www.w3.org/1999/xhtml&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="tag">&lt;</span><span class="tag-name">head</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">title</span><span class="tag">&gt;</span><span>Ajax-Demo</span><span class="tag">&lt;/</span><span class="tag-name">title</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="tag">&lt;</span><span class="tag-name">script</span><span>&nbsp;</span><span class="attribute">type</span><span>=</span><span class="attribute-value">&quot;text/javascript&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;createXMLHttpRequest(){&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(window.ActiveXObject){&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="attribute">xmlHttp</span><span>&nbsp;=&nbsp;</span><span class="attribute-value">new</span><span>&nbsp;ActiveXObject(&quot;Microsoft.XMLHTTP&quot;);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if(window.XMLHttpRequest){&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="attribute">xmlHttp</span><span>&nbsp;=&nbsp;</span><span class="attribute-value">new</span><span>&nbsp;XMLHttpRequest();&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;sendRequest(){&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;createXMLHttpRequest();&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;url;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="attribute">url</span><span>=</span><span class="attribute-value">&quot;getServerTime.do?person=Ihavegotyou&quot;</span><span>;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xmlHttp.open(&quot;POST&quot;,url,true);&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="attribute">xmlHttp.onreadystatechange</span><span>&nbsp;=&nbsp;</span><span class="attribute-value">handleStateChange</span><span>;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xmlHttp.send();&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;handleStateChange(){&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(<span class="attribute">xmlHttp.readyState</span><span>&nbsp;==&nbsp;4){&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(<span class="attribute">xmlHttp.status</span><span>&nbsp;==&nbsp;200){&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.getElementById(&quot;serverTime&quot;)<span class="attribute">.value</span><span>=</span><span class="attribute-value">xmlHttp</span><span>.responseText;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li>
    <li class=""><span><span class="tag">&lt;/</span><span class="tag-name">script</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span><span class="tag">&lt;/</span><span class="tag-name">head</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">form</span><span>&nbsp;</span><span class="attribute">action</span><span>=</span><span class="attribute-value">&quot;#&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">input</span><span>&nbsp;disabled&nbsp;</span><span class="attribute">type</span><span>=</span><span class="attribute-value">&quot;TEXT&quot;</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">&quot;serverTime&quot;</span><span>&nbsp;</span><span class="attribute">value</span><span>=</span><span class="attribute-value">&quot;这里显示服务器时间&quot;</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">input</span><span>&nbsp;</span><span class="attribute">align</span><span>=</span><span class="attribute-value">&quot;absmiddle&quot;</span><span>&nbsp;</span><span class="attribute">type</span><span>=</span><span class="attribute-value">&quot;button&quot;</span><span>&nbsp;</span><span class="attribute">value</span><span>=</span><span class="attribute-value">&quot;点击获取服务器时间&quot;</span><span>&nbsp;</span><span class="attribute">onclick</span><span>=</span><span class="attribute-value">&quot;sendRequest();&quot;</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;<span class="tag">&lt;/</span><span class="tag-name">form</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="tag">&lt;/</span><span class="tag-name">body</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="tag">&lt;/</span><span class="tag-name">html</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<br />
<br />
<br />
</span><span class="postbody"><span class="postbody"><br />
</span><span class="postbody">DealWith.java<br />
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<ol class="dp-j" start="1">
    <li class="alt"><span><span class="keyword">package</span><span> response;  </span></span></li>
    <li class=""><span>  </span></li>
    <li class="alt"><span><span class="keyword">import</span><span> javax.servlet.*;  </span></span></li>
    <li class=""><span><span class="keyword">import</span><span> javax.servlet.http.*;  </span></span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> DealWith </span><span class="keyword">extends</span><span> HttpServlet {  </span></span></li>
    <li class="alt"><span>    <span class="keyword">private</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> String CONTENT_TYPE = </span><span class="string">&quot;text/xml; charset=GBK&quot;</span><span>;  </span></span></li>
    <li class=""><span>  </span></li>
    <li class="alt"><span>    <span class="keyword">private</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> String URIS[] = { </span><span class="string">&quot;getServerTime.do&quot;</span><span>, </span><span class="string">&quot;others.do&quot;</span><span> };  </span></span></li>
    <li class=""><span>  </span></li>
    <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> init() </span><span class="keyword">throws</span><span> ServletException {  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> doPost(HttpServletRequest request, HttpServletResponse response) {  </span></span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>        response.setContentType(CONTENT_TYPE);  </span></li>
    <li class="alt"><span>        <span class="keyword">if</span><span> (request.getRequestURI().indexOf(URIS[</span><span class="number">0</span><span>]) != -</span><span class="number">1</span><span>) {  </span></span></li>
    <li class=""><span>            <span class="keyword">try</span><span> {  </span></span></li>
    <li class="alt"><span>                java.util.Calendar cal = java.util.Calendar.getInstance();  </span></li>
    <li class=""><span>                java.text.SimpleDateFormat fmt = <span class="keyword">new</span><span> java.text.SimpleDateFormat(  </span></span></li>
    <li class="alt"><span>                        <span class="string">&quot;yyyy-MM-dd hh:mm:ss&quot;</span><span>);  </span></span></li>
    <li class=""><span>                String time = fmt.format(cal.getTime());  </span></li>
    <li class="alt"><span>                response.getWriter().print(time);  </span></li>
    <li class=""><span>            } <span class="keyword">catch</span><span> (Exception e) {  </span></span></li>
    <li class="alt"><span>                e.printStackTrace();  </span></li>
    <li class=""><span>            }  </span></li>
    <li class="alt"><span>        }  </span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> doGet(HttpServletRequest request, HttpServletResponse response) {  </span></span></li>
    <li class="alt"><span>        doPost(request, response);  </span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>  </span></li>
    <li class=""><span>    <span class="comment">// Clean up resources</span><span>  </span></span></li>
    <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> destroy() {  </span></span></li>
    <li class=""><span>    }  </span></li>
    <li class="alt"><span>}  </span></li>
</ol>
</div>
</span><span class="postbody"> 清楚上面的模型,就会更加理解GWT RPC(Remote Procedure Calls)的几个步骤：<br />
</span>
<ul>
    <li><span class="postbody"><font color="red">Creating Services</font> <br />
    How to build a service interface from scratch. </span></li>
    <li><span class="postbody"><font color="red">Implementing Services</font> <br />
    Implement your service interface as a servlet. </span></li>
    <li><span class="postbody"><font color="red">Actually Making a Call</font> <br />
    How to actually make a remote procedure call from the client.</span></li>
    <li><span class="postbody"> Serializable Types(不必要) <br />
    Using GWT's automatic serialization well. </span></li>
    <li><span class="postbody"><font color="red">Handling Exceptions</font> <br />
    Handle exceptions due to failed calls or thrown from the server. </span></li>
    <li><span class="postbody"><font color="red">Getting Used to Asynchronous Calls</font> <br />
    Asynchronous calls are tricky at first, but ultimately your users will thank you. </span></li>
</ul>
</span>
          <br/>
          <span style="color:red;">
            <a href="http://ihavegotyou.javaeye.com/blog/132528#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 16 Oct 2007 13:17:44 +0800</pubDate>
        <link>http://ihavegotyou.javaeye.com/blog/132528</link>
        <guid>http://ihavegotyou.javaeye.com/blog/132528</guid>
      </item>
  </channel>
</rss>