浏览 29641 次
锁定老帖子 主题:挖掘dwr
该帖已经被评为精华帖
作者 正文
   发表时间:2006-09-13  
DWR
等不及dwr2.0了。

     精巧的设计使DWR很容易被java开发人员接受;对传统web程序的无侵害性让它被引入更多的项目。与服务器端通信,DWR很有代表性,并很好的隐藏的xmlhttp对象,也基本可以满足我们要求。如果我们想抛弃传统的webwork/spring mvc等MVC框架,全部数据由DWR来实现的话,也有一定风险。没办法,只能挖掘DWR深层次的应用了。

一、业务层设计
    为了讨好传统的,用户量惊人的传统web应用。可能更准确的说是webwork/jsf为了和火热的AJAX套上关系,主动和dwr联系。dwr可以与Struts/JSF/PageFlow....集成。webwork最先干这个事,效果不好,用户根本不满足那一点点ajax应用。我认为与DWR的服务器端业务层最合适的是spring.也就是DWR的creator最好的是spring IOC框架.
     前段时间考虑,想在service层前面再有一外观层,因为dwr/ajax在浏览器端可能有很多细粒度的方法,以防破坏service层OO特性.(太教条了). 我们设计service层时,完全可以考虑,我们正在为DWR设计服务层,该注意的都应该注意.例如方法不能重载,不能用javascript关键字delete......
     设计要点:
          细粒度方法,粒度划分由浏览器业务决定.void updateName(id,name);  void updateUser(user);???
          方法的参数能用基本类型就用基本类型,可能性能会好点???
          避免方法重载
          关键字
          //todo
二、关于PO/VO....
      如果你用hibernate,如果把PO让dwr的HibernateBeanConverter处理,可以看http://getahead.ltd.uk/dwr/server/hibernate .
好象也有问题,尤其是hibernate3属性的lazyload.
      User.getRoles();
      roles.getUsers();
      logic.getUser();
      logic.getUserList();
      logic.getRolesList();
      ........

好象VO/DTO又有出头之日了.

另外还有一个问题.
logic.java
    User logic.find(int id);
    logic.save(User user);
action.java
    User user=logic.find(id);
    user.setName("");
    .....
    ....
     logic.save(user);

如果在ajax应用中,我相信会有logic.updateProper();这些细粒度方法,如果还象以前那样,那AJAX还有什么意思.

我现在意见是AJAX为主的应用中放弃hibernate,用spring template,不考虑OO.
毕竟不是所有的应用都适合AJAX为主.
    ajax portal
    http://my.msn.com
    Window对象
     改变它的位置
     填加连接
     ......
这些细粒度方法.OO不见得有多合适.


三、DWR服务器端扩展
1 、htmlConverter
   DWR最让人称道的是java方法可以由javascript调用,并把java对象和"json"互换.如果一个特点特别亮的话,那它肯定会有更大的不足.
     ajax可能传递  xml/json/html片段等.这里我觉得json基本可以替代xml,但html片段,dwr几乎没有支持,虽然可以由json包含html片段,但注意,这个html有java生成.html片段我任何还是很有必要的.
      如何生成这些html?由java实现?freemarker?htmlConverter?如何简单配置?值得考虑一下!
2、如果简化converter
     dwr提供的converter功能已经很不错了,但是扩展.编写自己类型的converter还是很麻烦.
     现在服务器端生成javascript也挺热闹,虽然偶不是很感兴趣,但如果dwr能把converter弄简单一些,包括配置,扩展,所见既所得.那就完美了.
     另外对于java反射感觉不爽,如果在正式运行环境下,把具体对象bean/object converter重写一下也是方便的.
四、客户端开发
     通过服务器生成javascript,与service函数对应.方便确实方便,但这也成了众多人的批判点.其实这些js不下载,dwr也可以运行的很好.
     其实dwr的这个封装没有必要,限制的dwr的开发.比如偶想在客户端做个cache,nnd,函数类型,不爽.编写无聊的,可能层次很深的callback函数.让代码很乱.
      另外dwr能称为ajax framework真有些牵强,如果不是j2ee程序员喜欢赶时髦,唉,这帮不知疲倦的人啊.
主要是客户端代码太弱,还须努力.
       这部分我已经做了点点工作,过几天show一下.
五、后续努力
    dwr如此优秀,我们应用的却不是很好,只能当成一个方便的数据存取框架.
    如果在浏览器角度,我们把服务器当成数据库的话,dwr做的不错.但这些json数据如何与dojo/yui/qooxdoo 优秀试图框架结合,需要大家努力.




这几天准备试着基于dwr开发一客户端MVC实现.
有什么建议欢迎讨论.
   发表时间:2006-09-13  
不错,写的很棒!
0 请登录后投票
   发表时间:2006-09-14  
写得很好.
ps:没有任何人评分就自动精华了?
0 请登录后投票
   发表时间:2006-09-14  
已经做过类似项目了,但是并不是大并发量的项目。
框架设计采用spring + dwr
抛弃了spring mvc
采用javascript在客户端实现了一个mvc,主要是节省javasript代码量
大部分工作犬在页面脚本上

效果还不错
0 请登录后投票
   发表时间:2006-09-14  
不过我感觉,如果dwr可以胜任一般应用的话,mvc这东西还有多少年能撑?
0 请登录后投票
   发表时间:2006-09-14  
很不错

0 请登录后投票
   发表时间:2006-09-14  
DWR昨晚试用了一吧,总的来说对它没什么好感,我的配置文件件如下:
Province.java
/* Province.java
 * --------------------------------------
 * CREATED ON Jun 15, 2006 4:04:26 PM
 *
 * MSN arden.emily@msn.com
 * QQ 103099587(太阳里的雪)
 * MOBILE 13590309275
 *
 * ALL RIGHTS RESERVED BY ZHENUU CO,.LTD.
 * --------------------------------------
 */
package com.zhenuu.location.model;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

import com.zhenuu.framework.orm.hibernate.BaseEntity;

/**
 * 省份
 * 
 * Date: Jun 15, 2006 4:04:26 PM
 * @author <a href="arden.emily@gmail.com">arden</a>
 */
@SuppressWarnings("serial")
@Entity
@Table(name="provinces")
public class Province extends BaseEntity<Province> {
	private String name = "";
	
	private int listOrder = 0;
	
	// 系统需要的时候载入内存(只载入一次)
	private static List<Province> provinces = new ArrayList<Province>();
	
	@Column(name="list_order")
	public int getListOrder() {
		return listOrder;
	}

	public void setListOrder(int listOrder) {
		this.listOrder = listOrder;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	
	public Province() {}
	public Province(Long id) {
		this.id = id;
	}
		
	/**
	 * 获得指定省下面的所有城市
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@javax.persistence.Transient
	public List<City> getCitys() {
		String hql = "FROM City WHERE provinceId = " + this.getId();
		return entityManager.find(hql);
	}
	
	@SuppressWarnings("unchecked")	
	public static List<City> getCitys(long id) {
		String hql = "FROM City WHERE provinceId = " + id;
		return entityManager.find(hql);
	}
	
	/**
	 * 获得所有省份
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static List<Province> getProvinces() {
		String hql = "FROM Province ORDER BY listOrder";
		if (provinces.isEmpty()) {
			provinces = entityManager.find(hql);
		}		
		return provinces;
	}
}


City.java
/* City.java
 * --------------------------------------
 * CREATED ON Jun 15, 2006 4:21:00 PM
 *
 * MSN arden.emily@msn.com
 * QQ 103099587(太阳里的雪)
 * MOBILE 13590309275
 *
 * ALL RIGHTS RESERVED BY ZHENUU CO,.LTD.
 * --------------------------------------
 */
package com.zhenuu.location.model;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

import com.zhenuu.framework.orm.hibernate.BaseEntity;

/**
 * 城市(与Province是多对一的关系)
 * 
 * Date: Jun 15, 2006 4:21:00 PM
 * @author <a href="arden.emily@gmail.com">arden</a>
 */
@SuppressWarnings("serial")
@Entity
@Table(name="citys")
public class City extends BaseEntity<City> {
	/* 省的ID */
	private Long provinceId = 0L;
	/* 城市的区号,唯一 */
	private int number = 10;
	/* 城市名称 */
	private String name = "";
	
	private int listOrder = 0;
	
	public City() {};
	public City(Long cityid) {this.id = cityid;};
	
	@Column(name="list_order")
	public int getListOrder() {
		return listOrder;
	}

	public void setListOrder(int listOrder) {
		this.listOrder = listOrder;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}

	@Column(name="province_id")
	public Long getProvinceId() {
		return provinceId;
	}

	public void setProvinceId(Long provinceId) {
		this.provinceId = provinceId;
	}
	
	/**
	 * 获得指定城市下面的所有区
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@javax.persistence.Transient
	public List<Area> getAreas() {
		String hql = "FROM Area WHERE cityId = " + this.getId();
		return entityManager.find(hql);
	}
	
	@SuppressWarnings("unchecked")
	public static List<Area> getAreas(long id) {
		String hql = "FROM Area WHERE cityId = " + id;
		return entityManager.find(hql);
	}	
}


Area.java
/* Area.java
 * --------------------------------------
 * CREATED ON Jun 15, 2006 4:21:56 PM
 *
 * MSN arden.emily@msn.com
 * QQ 103099587(太阳里的雪)
 * MOBILE 13590309275
 *
 * ALL RIGHTS RESERVED BY ZHENUU CO,.LTD.
 * --------------------------------------
 */
package com.zhenuu.location.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

import com.zhenuu.framework.orm.hibernate.BaseEntity;

/**
 * 地区(与城市是多对一的关系)
 * 
 * Date: Jun 15, 2006 4:21:56 PM
 * @author <a href="arden.emily@gmail.com">arden</a>
 */
@SuppressWarnings("serial")
@Entity
@Table(name="areas")
public class Area extends BaseEntity<Area> {
	/* 城市ID */
	private int cityId = 0;
	
	/* 城市区号 */	
	private int citynumber = 10;
	
	/* 地区名 */
	private String name = "";
	
	@Column(name="city_number")
	public int getCitynumber() {
		return citynumber;
	}

	public void setCitynumber(int citynumber) {
		this.citynumber = citynumber;
	}

	@Column(name="city_id")
	public int getCityId() {
		return cityId;
	}

	public void setCityId(int cityId) {
		this.cityId = cityId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
    "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
    "http://www.getahead.ltd.uk/dwr/dwr10.dtd">

<dwr>
  <allow>
    <create creator="new" javascript="Province">
      <param name="class" value="com.zhenuu.location.model.Province"/>
      <include method="getCitys"/>      
    </create>
    <convert converter="bean" match="com.zhenuu.location.model.City"/>
    
    <create creator="new" javascript="City">
      <param name="class" value="com.zhenuu.location.model.City"/>
      <include method="getAreas"/>  
    </create>        
    <convert converter="bean" match="com.zhenuu.location.model.Area"/>
  </allow>
</dwr>


但是出现两个问题:
1:我在客户端只调用getCitys()时他却同时帮我调用了getAreas()方法。
2:不知道如何给Province,City设值,如调用:setId()方法给它们设一些相应的值进去!

不知哪位知道如何解决上面两个问题!
0 请登录后投票
   发表时间:2006-09-14  
对于你这样定义hibernate的domain我没什么话说。
还有那个static.

另外DWR很喜欢  贫血pojo.
0 请登录后投票
   发表时间:2006-09-14  
1 getAreas方法的名字太像javabean的getter了,又没有另行配置,dwr当然会自动调用了。
2 不知道给它们设值目的何在,都是new出来的。。
还是建议给远程调用单独设计一层,处理器很多问题都灵活的多
Arden 写道
DWR昨晚试用了一吧,总的来说对它没什么好感,我的配置文件件如下:
但是出现两个问题:
1:我在客户端只调用getCitys()时他却同时帮我调用了getAreas()方法。
2:不知道如何给Province,City设值,如调用:setId()方法给它们设一些相应的值进去!

不知哪位知道如何解决上面两个问题!
0 请登录后投票
   发表时间:2006-09-14  
原来DWR会自动调用getXXX方法啊,我再去试试看看!
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics