Posts Mentioning RSS Toggle Comment Threads | Keyboard Shortcuts

  • tin 3:21 pm on January 30, 2006 Permalink | Log in to leave a Comment
    Tags:   

    Generic Hibernate DAO试验 

    我们项目升级Weblogic 9.1,所以可以用JDK5的东西了。
    先试验一下GenericHibernateDAO,作为一个DAO的基类,实现了一些简单的方法,方便子DAO封装。

    使用方法类似:
     public class HibernateTownDAO extends GenericHibernateDAO<Town>
    implements ITownDAO{
     {
            public HibernateTownDAO() { super(Town.class); } }
     }

    这个东西基本上是从EclipseWork里面来的……

    IGenericDAO大家可以用Eclipse的抽出Interface……
    代码如下:
    package com.goldnet.dao.hibernateDAO;
    import org.apache.commons.beanutils.BeanUtils;
    import org.hibernate.Criteria;
    import org.hibernate.Session;
    import org.hibernate.criterion.Order;
    import org.hibernate.criterion.Restrictions;
    import org.springframework.orm.hibernate3.HibernateCallback;
    import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
    import com.goldnet.dao.IDAO.IGenericDAO;
    import java.io.Serializable;
    import java.util.Collection;
    import java.util.Iterator;
    /**
     * @author TIN
     * @comment
     * @param <E>
     *
     * 范型的抽象HibernateDAO,继承于Spring提供的HibernateDaoSupport,该DAO封装了大部分的Domain对象访问方法。
     * 使用范型的目的在于可以显示的规定传入/返回的类型。直接的目的在于减少使用DAO时的强行类型转换。
     *
     * TODO:getTopsByProperty(int, String)方法
     * TODO:execute(HibernateCallback callback)方法?
     * TODO:execute(HQL hql)方法?
     * TODO:execute(SQL sql)方法?
     * TODO:findByCriteria(Criterion… criterion)方法?
     * TODO:getAOfflineListCopy(List list)方法?获取一个离线list,可以在部分地方获取session无关的List,避免使用OpenSessionInView
     * TODO:String getPersistentObjectName()方法?
     * TODO:使用变长参数修改一些传入Properties和Value的地方,扩展一些方法
     * TODO:研究一下DetachedCreteria
     * 
     */
    public class GenericHibernateDAO<E> extends HibernateDaoSupport implements IGenericDAO<E> {
     private static final long serialVersionUID = 1312483055446936306L;
     private final Class clazz;
     public GenericHibernateDAO(final Class<E> clazz) {
      this.clazz = clazz;
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#saveOrUpdate(java.lang.Object,
      *      java.io.Serializable)
      * @deprecated
      *
      * @param newObject 持久化的类
      * @param id 持久化类的标识id
      *
      * 存储一个Entity,由于它的实现方式与HibernateDAO的saveOrUpdate雷同,都检测了id是否存在,但却多一个参数
      * 所以暂时部推荐,但是该实现对saveOrUpdate机理表现比较清晰,所以没有删除
      */
     public void saveOrUpdate(E newObject, Serializable id) {
      if ((id != null) && !getHibernateTemplate().contains(id)) {
       E dbObject = this.loadById(id);
       try {
        BeanUtils.copyProperties(dbObject, newObject);
       } catch (Exception e) {
        logger.error(e, e);
       }
       newObject = dbObject;
      }
      if (logger.isDebugEnabled()) {
       logger.debug("[saveOrUpdate with id Parameter] Entity<"
         + this.clazz.getName() + ">.");
       logger
         .debug("this method is deprecated! Please use saveOrUpdate(Object) instead.");
      }
      getHibernateTemplate().saveOrUpdate(newObject);
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#saveOrUpdate(java.lang.Object)
      *
      * @param newObject 持久化的类
      *
      * 持久化一个Entity,一般用在不知持久化的是VO或PO时
      */
     public void saveOrUpdate(E newObject) {
      if (logger.isDebugEnabled()) {
       logger
         .debug("[saveOrUpdate] Entity<" + this.clazz.getName()
           + ">.");
      }
      getHibernateTemplate().saveOrUpdate(newObject);
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#save(java.lang.Object)
      *
      * @param object 持久化的类
      *
      * 持久化一个Entity,用在持久化PO时
      */
     public void save(E object) {
      if (logger.isDebugEnabled()) {
       logger.debug("[save] Entity<" + this.clazz.getName() + ">.");
      }
      getHibernateTemplate().save(object);
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#update(java.lang.Object)
      *
      * @param object 持久化的类
      *
      * 持久化一个Entity,符合jsr-220规范,用在持久化一个VO的Entity(但是它已经在库中存在)时,持久化它并返回它的PO
      */
     @SuppressWarnings("unchecked")
     public E merge(E object) {
      if (logger.isDebugEnabled()) {
       logger.debug("[merge] Entity<" + this.clazz.getName() + ">.");
      }
      return (E) getHibernateTemplate().merge(object);
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#isEntityWithPropertyOfValueExist(java.lang.String,
      *      java.lang.Object)
      *
      * @param propertyName Entity属性的名称
      * @param value Entity属性的值
      * @return
      *
      * 具有propertyName的Entity是否存在?如果true则存在,如果false则不存在。
      */
     public boolean isEntityWithPropertyOfValueExist(String propertyName,
       Object value) {
      if (logger.isDebugEnabled()) {
       logger.debug("[isEntityWithPropertyOfValueExist] Entity<"
         + this.clazz.getName() + ">, propName=" + propertyName
         + ", value=" + value + ".");
      }
      if (getHibernateTemplate().find(
        "from " + this.clazz.getName() + " table where table."
          + propertyName + "=?", value).size() > 0) {
       return true;
      }
      return false;
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#isEntityIdExist(java.io.Serializable)
      *
      * @param id Entity的标识id
      * @return
      *
      * 具有该id的Entity是否存在?如果true则存在,如果false则不存在。用来检测一个VO是否已经有对应的PO存在
      */
     public boolean isEntityIdExist(Serializable id) {
      if (logger.isDebugEnabled()) {
       logger.debug("[isEntityIdExist] Entity<" + this.clazz.getName()
         + "> with id=" + id + ".");
      }
      return getHibernateTemplate().contains(id);
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#delete(java.lang.Object)
      *
      * @param object Entity对象
      *
      * 删除一个Entity
      */
     public void delete(E object) {
      if (logger.isDebugEnabled()) {
       logger.debug("[delete] Entity<" + this.clazz.getName() + ">.");
      }
      getHibernateTemplate().delete(object);
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#deleteById(java.io.Serializable)
      *
      * @param id Entity的标识id
      *
      * 根据Entity的标识id删除一个Entity
      */
     public void deleteById(Serializable id) {
      if (logger.isDebugEnabled()) {
       logger.debug("[deleteById] Entity<" + this.clazz.getName()
         + "> with id=" + id + ".");
      }
      getHibernateTemplate().delete(
        getHibernateTemplate().get(this.clazz, id));
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#deleteByProperty(java.lang.String,
      *      java.lang.Object)
      *
      * @param propertyName Entity属性的名称
      * @param value Entity属性的值
      *
      * 删除一组具有相同propertyName属性值(value)的Entity,用来批量删除
      */
     @SuppressWarnings("unchecked")
     public void deleteByProperty(String propertyName, Object value) {
      Iterator<E> result = listByProperty(propertyName, value).iterator();
      while (result.hasNext()) {
       delete(result.next());
      }
      if (logger.isDebugEnabled()) {
       logger.debug("[deleteByProperty] Entity<" + this.clazz.getName()
         + ">, propName=" + propertyName + ", value=" + value + ".");
      }
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#loadById(java.io.Serializable)
      *
      * @param id Entity的标识id
      * @return
      *
      * 根据Entity的标识id获取一个Entity的PO
      */
     @SuppressWarnings("unchecked")
     public E loadById(Serializable id) {
      if (logger.isDebugEnabled()) {
       logger.debug("[loadById] Entity<" + this.clazz.getName() + ">, id="
         + id + ".");
      }
      return (E) getHibernateTemplate().get(this.clazz, id);
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#loadByProperty(java.lang.String,
      *      java.lang.Object)
      *
      * @param propertyName Entity属性的名称
      * @param value Entity属性的值
      * @return
      *
      * TODO:判断结果是否是unique?
      * 获取一个具有相同propertyName属性值(value)的Entity,注意改属性必须是unique的,否则改方法将没有意义
      */
     @SuppressWarnings("unchecked")
     public E loadByProperty(String propertyName, Object value) {
      Collection result = getHibernateTemplate().find(
        "from " + this.clazz.getName() + " table where table."
          + propertyName + "=?", value);
      Iterator<E> it = result.iterator();
      if (logger.isDebugEnabled()) {
       logger.debug("[loadByProperty] Entity<" + this.clazz.getName()
         + ">, propName=" + propertyName + ", value=" + value + ".");
      }
      if (it.hasNext()) {
       return it.next();
      } else {
       return null;
      }
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#loadEntitySum()
      *
      * @return
      *
      * 获取一种Entity的总数
      */
     public int loadEntitySum() {
      if (logger.isDebugEnabled()) {
       logger.debug("[loadEntitySum] Entity<" + this.clazz.getName()
         + ">.");
      }
      return ((Integer) getHibernateTemplate().find(
        "select count(*) from " + this.clazz.getName()).iterator()
        .next()).intValue();
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#loadEntitySumByProperty(java.lang.String,
      *      java.lang.Object)
      *
      * @param propertyName Entity属性的名称
      * @param value Entity属性的值
      * @return
      *
      * 获取一组具有相同propertyName属性值(value)的Entity的个数
      */
     public int loadEntitySumByProperty(String propertyName, Object value) {
      if (logger.isDebugEnabled()) {
       logger.debug("[loadEntitySum] Entity<" + this.clazz.getName()
         + ">, propName=" + propertyName + ", value=" + value + ".");
      }
      return ((Integer) getHibernateTemplate().find(
        "select count(*) from " + this.clazz.getName()
          + " table where table." + propertyName + "=?", value)
        .iterator().next()).intValue();
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#loadLastEntity()
      *
      * @param orderByPropertyName 用来排序的属性的名称
      * @return
      *
      * TODO:和获取Tops是否重复?
      * 返回最后一个Entity,用来获取如最新加入的Entity这样的方法
      * 注意改方法实际上返回的是降序排列的list中的第一个!
      */
     @SuppressWarnings("unchecked")
     public E loadLastEntity(final String orderByPropertyName) {
      if (logger.isDebugEnabled()) {
       logger.debug("[listLastEntity] Entity<" + this.clazz.getName()
         + "> and orderByPropertyName=" + orderByPropertyName
         + ", Note:it’s DESC.");
      }
      return (E) getHibernateTemplate().execute(new HibernateCallback() {
       public Object doInHibernate(Session session) {
        Criteria criteria = session.createCriteria(clazz);
        criteria.addOrder(Order.desc(orderByPropertyName));
        releaseSession(session);
        try {
         return criteria.list().iterator().next();
        } catch (Exception e) {
         logger
           .warn("[listLastEntity] faild! the entity list is empty!");
         return null;
        }
       }
      });
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#listAll()
      *
      * @return
      *
      * 获取所有的Entity的list
      */
     @SuppressWarnings("unchecked")
     public Collection<E> listAll() {
      if (logger.isDebugEnabled()) {
       logger.debug("[listAll] Entity<" + this.clazz.getName() + ">.");
      }
      return getHibernateTemplate().find("from " + this.clazz.getName());
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#listAllOrderBy(boolean, java.lang.String)
      *
      * @param isAsc 是否使用升序
      * @param orderByPropertyName 排序的属性
      * @return
      *
      * 获取所有的Entity的list,结果按照orderByPropertyName属性升序/降序(isAsc true则升序,否则降序)
      */
     @SuppressWarnings("unchecked")
     public Collection<E> listAllOrderBy(final boolean isAsc,
       final String orderByPropertyName) {
      final Class clazztemp = this.clazz;
      if (logger.isDebugEnabled()) {
       logger.debug("[listAllOrderBy] Entity<" + this.clazz.getName()
         + ">, isAsc?=" + isAsc + ", orderByPropertyName="
         + orderByPropertyName + ".");
      }
      return (Collection<E>) getHibernateTemplate().execute(
        new HibernateCallback() {
         public Object doInHibernate(Session session) {
          Criteria criteria = session.createCriteria(clazztemp);
          criteria.addOrder(isAsc ? Order
            .asc(orderByPropertyName) : Order
            .desc(orderByPropertyName));
          releaseSession(session);
          return criteria.list();
         }
        });
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#listByPage(int, int)
      *
      * @param pagesize 页的大小,每页最多Entity个数
      * @param pageno 页码
      * @return
      *
      * 获取一页的Entity的list,该页是所有Entity中的第pageno页,每页最多有pagesize个Entity,分页显示Entity时使用
      */
     @SuppressWarnings("unchecked")
     public Collection<E> listByPage(final int pagesize, final int pageno) {
      final Class clazztemp = this.clazz;
      if (logger.isDebugEnabled()) {
       logger.debug("[listByPage] Entity<" + this.clazz.getName()
         + ">, pagesize=" + pagesize + ", pageno=" + pageno + ".");
      }
      return (Collection<E>) getHibernateTemplate().execute(
        new HibernateCallback() {
         public Object doInHibernate(Session session) {
          Criteria criteria = session.createCriteria(clazztemp);
          criteria.setFirstResult(pagesize * pageno);
          criteria.setMaxResults(pagesize);
          releaseSession(session);
          return criteria.list();
         }
        });
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#listByPageOrderBy(int, int, boolean,
      *      java.lang.String)
      *     
      * @param pagesize 页的大小,每页最多Entity个数
      * @param pageno 页码
      * @param isAsc 是否使用升序
      * @param orderByPropertyName 排序的属性
      * @return
      *
      * 获取一页的Entity的list,该页内容按照orderByPropertyName属性升序/降序(isAsc true则升序,否则降序),该页是所有Entity中的第pageno页,每页最多有pagesize个Entity
      * 分页显示排序过的Entity时使用
      */
     @SuppressWarnings("unchecked")
     public Collection<E> listByPageOrderBy(final int pagesize,
       final int pageno, final boolean isAsc,
       final String orderByPropertyName) {
      final Class clazztemp = this.clazz;
      if (logger.isDebugEnabled()) {
       logger.debug("[listByPageOrderBy] Entity<" + this.clazz.getName()
         + ">, pagesize=" + pagesize + ", isAsc?=" + isAsc
         + ", orderByPropertyName" + orderByPropertyName
         + ", pageno=" + pageno + ".");
      }
      return (Collection<E>) getHibernateTemplate().execute(
        new HibernateCallback() {
         public Object doInHibernate(Session session) {
          Criteria criteria = session.createCriteria(clazztemp);
          criteria
            .setFirstResult(pagesize * pageno)
            .setMaxResults(pagesize)
            .addOrder(
              isAsc ? Order.asc(orderByPropertyName)
                : Order
                  .desc(orderByPropertyName));
          releaseSession(session);
          return criteria.list();
         }
        });
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#listByProperty(java.lang.String,
      *      java.lang.Object)
      *     
      * @param propertyName Entity属性的名称
      * @param value Entity属性的值
      * @return
      *
      * 获取一组具有相同propertyName属性值(value)的Entity的列表list,返回一组符合条件的Entity
      */
     @SuppressWarnings("unchecked")
     public Collection<E> listByProperty(String propertyName, Object value) {
      if (logger.isDebugEnabled()) {
       logger.debug("[listByProperty] Entity<" + this.clazz.getName()
         + ">, propertyName" + propertyName + ", value=" + value
         + ".");
      }
      return getHibernateTemplate().find(
        "from " + this.clazz.getName() + " table where table."
          + propertyName + "=?", value);
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#listByPageByProperty(java.lang.String,
      *      java.lang.Object, boolean, java.lang.String)
      *     
      * @param pagesize 页的大小,每页最多Entity个数
      * @param pageno 页码
      * @param listByPropertyName Entity属性的名称
      * @param value Entity属性的值
      * @return
      *
      * 获取一页的Entity的list,该页内容为具有相同propertyName属性值(value)的Entity,该页是所有符合条件Entity中的第pageno页,每页最多有pagesize个Entity
      * 分页显示匹配某一属性值的Entity时使用
      */
     @SuppressWarnings("unchecked")
     public Collection<E> listByPageByProperty(final int pageno,
       final int pagesize, final String listByPropertyName,
       final Object value) {
      final Class clazztemp = this.clazz;
      if (logger.isDebugEnabled()) {
       logger.debug("[listByPageByProperty] Entity<"
         + this.clazz.getName() + ">, pageno=" + pageno
         + ", pagesize=" + pagesize + ", listByPropertyName="
         + listByPropertyName + ", value" + value + ".");
      }
      return (Collection<E>) getHibernateTemplate().execute(
        new HibernateCallback() {
         public Object doInHibernate(Session session) {
          Criteria criteria = session.createCriteria(clazztemp);
          criteria.setFirstResult(pagesize * pageno)
            .setMaxResults(pagesize).add(
              Restrictions.eq(listByPropertyName,
                value));
          releaseSession(session);
          return criteria.list();
         }
        });
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#listByPropertyOrderBy(java.lang.String,
      *      java.lang.Object, boolean, java.lang.String)
      *     
      * @param listByPropertyName Entity属性的名称
      * @param value Entity属性的值
      * @param isAsc 是否使用升序
      * @param orderByPropertyName 排序的属性
      * @return
      *
      * 获取所有的具有匹配propertyName属性值(value)的Entity的list,按照orderByPropertyName属性升序/降序(isAsc true则升序,否则降序)
      * 显示匹配属性值的列表且要求排序时使用
      */
     @SuppressWarnings("unchecked")
     public Collection<E> listByPropertyOrderBy(final String listByPropertyName,
       final Object value, final boolean isAsc,
       final String orderByPropertyName) {
      final Class clazztemp = this.clazz;
      if (logger.isDebugEnabled()) {
       logger.debug("[listByPropertyOrderBy] Entity<"
         + this.clazz.getName() + ">, listByPropertyName="
         + listByPropertyName + ", value" + value + ", isAsc?="
         + isAsc + ", orderByPropertyName=" + orderByPropertyName
         + ".");
      }
      return (Collection<E>) getHibernateTemplate().execute(
        new HibernateCallback() {
         public Object doInHibernate(Session session) {
          Criteria criteria = session.createCriteria(clazztemp);
          criteria
            .add(Restrictions.eq(listByPropertyName, value))
            .addOrder(
              isAsc ? Order.asc(orderByPropertyName)
                : Order
                  .desc(orderByPropertyName));
          releaseSession(session);
          return criteria.list();
         }
        });
     }
     /**
      * @see com.goldnet.dao.IDAO.IGenericDAO#listByPageByPropertyOrderBy(int, int,
      *      java.lang.String, java.lang.Object, boolean, java.lang.String)
      *     
      * @param pagesize 页的大小,每页最多Entity个数
      * @param pageno 页码
      * @param listByPropertyName Entity属性的名称
      * @param value Entity属性的值
      * @param isAsc 是否使用升序
      * @param orderByPropertyName 排序的属性
      * @return
      *
      * 获取一页的Entity的list,该页内容为具有相同propertyName属性值(value)的Entity,该页内容按照orderByPropertyName属性升序/降序(isAsc true则升序,否则降序),
      * 该页是所有符合条件Entity中的第pageno页,每页最多有pagesize个Entity
      * 分页显示匹配某一属性值的Entity时使用
      */
     @SuppressWarnings("unchecked")
     public Collection<E> listByPageByPropertyOrderBy(final int pagesize,
       final int pageno, final String listByPropertyName,
       final Object value, final boolean isAsc,
       final String orderByPropertyName) {
      final Class clazztemp = this.clazz;
      if (logger.isDebugEnabled()) {
       logger.debug("[listByPageByPropertyOrderBy] Entity<"
         + this.clazz.getName() + ">, pageno=" + pageno
         + ", pagesize=" + pagesize + ", listByPropertyName="
         + listByPropertyName + ", value" + value + ", isAsc?="
         + isAsc + ", orderByPropertyName=" + orderByPropertyName
         + ".");
      }
      return (Collection<E>) getHibernateTemplate().execute(
        new HibernateCallback() {
         public Object doInHibernate(Session session) {
          Criteria criteria = session.createCriteria(clazztemp);
          criteria
            .setFirstResult(pagesize * pageno)
            .setMaxResults(pagesize)
            .add(Restrictions.eq(listByPropertyName, value))
            .addOrder(
              isAsc ? Order.asc(orderByPropertyName)
                : Order
                  .desc(orderByPropertyName));
          releaseSession(session);
          return criteria.list();
         }
        });
     }
    }
     
  • tin 4:58 pm on January 28, 2006 Permalink | Log in to leave a Comment
    Tags:   

    生活的效率,累的是谁? 

    发现MSN Spaces升级了,满好玩的,不过好像是有Bug的,目前带着自己的信息给别人留言还有问题。
    如何提高效率呢?
    1、最好要有一个可以移动的工作平台。或者自己总结一个回复工作平台的步骤。自己经常对自己所做的事情做记录,并分享。
    2、关于信息的获取,除了使用搜索引擎,还可以考虑订阅RSS。通过FeedDeamon这样的Rss阅读器,可以定义自己的频道,在里面收藏关注的站点(尤其是技术Blog),如此通过适时的跟踪,可以保证信息获取的及时。
    3、使用一个文章收藏工具,如CyberArticle(网文快捕)。通过它的分类收藏功能,可以将自己关注或者有用的技术文章保存下来,并且可以方便的制作电子书。它的最大优点是可以将你所有的技术文章(网页)保存为一个统一的book文件,方便管理和备份。
    4、掌握一个拿手的编辑器。用Windows的朋友可能习惯使用NotePad(记事本),但是它并不怎么好用。推荐习惯UltraEdit或者EditPlus这样的强大的编辑器的功能,使用批量替换,字符显示,文件编码等问题的解决(如果感兴趣,用UltraEdit的16进制编辑功能可以帮你发现更多的隐藏的编码问题)。我偏好EditPlus……
    5、这个年代要掌握eMule和BT的基本使用方法。BT对于获得流行的资源非常有帮助,而eMule则对获得非流行的资源(如eBook、冷门mp3等)非常重要。注意不少eMule Client有积分,注意积攒,对排队有效。
    6、如果你还没有Blog,最好有一个,可以催促你积累和共享你的收获。
    祝大家新春快乐,狗年吉祥!
     
    • (no name) 11:40 am on February 8, 2006 Permalink

      很高兴认识你
      看到你对Webwork、Spring和hibernate的理解,希望可以交个朋友,大家交流交流
      我的MSN是:hk_akai@hotmail.com
                             祝 狗年走狗运~ ^_^
  • tin 9:24 pm on January 19, 2006 Permalink | Log in to leave a Comment
    Tags:   

    Webwork 2.2的form tag在使用jsp view时onsubmit不工作 

    起因是使用Michael Chen的JSValidation,需要手动写onsubmit,结果居然发现webwork 2.2的正式版本里面的form tag里面的onsubmit在使用jsp view的时候没法输出,苦恼于此。暂时通过修改模板修改了一下,但是如此很不爽。所以就想测试一下到底是不是我们项目的问题还是ww 2.2的问题。但一直太忙,今天才抽出功夫测。以下是测试纪录,希望知道缘由的朋友帮我指点一下。

    测试使用Webwork发行包中演示的starter项目,其中使用了ftl模板作为表现层,我按它的方式制造了newPerson.jsp。
    下面是两个页面的源文件:
    newPerson.jsp

    java代码: 
    <%@ page language="java" contentType="text/html; charset=utf-8"%>
    <%@ taglib uri="webwork" prefix="ww"%>
    <html>
    <head>
        <title>New Person</title>
        <link href="<ww:url value="/webwork/jscalendar/calendar-blue.css" />" rel="stylesheet" type="text/css" media="all"/>
    </head>

    <body>
    <ww:form action="newPerson" onsubmit="dosomething" validate="false">
        <ww:textfield label="Name" name="person.name"/>
        <ww:datepicker  name="date" id="ecoInf.turninDate" template="datepicker.ftl" language="en" format="%Y-%m-%d" label="Time
    "/>
        <ww:submit value="Create person"/>
    </ww:form>
    </body>
    </html>

    newPerson.ftl

    java代码: 
    <html>
    <head>
        <title>New Person</title>
        <link href="<@ww.url value="/webwork/jscalendar/calendar-blue.css" />" rel="stylesheet" type="text/css" media="all"/>
    </head>

    <body>
    <@ww.form action="newPerson" onsubmit="dosomething">
        <@ww.textfield label="Name" name="person.name"/>
        <@ww.datepicker  name="date" id="ecoInf.turninDate" template="datepicker.ftl" language="en" format="%Y-%m-%d" label="Time"/>
        <@ww.submit value="Create person"/>
    </@ww.form
    >
    </body>
    </html>


    程序逻辑继续使用starter项目里面的内容。
    xwork中配置如下:

    java代码: 
    <action name="newPerson" class="com.acme.CreatePerson">
                <result name="success" type="redirect">listPeople.action</result>
                <!–
                <result name="input" type="dispatcher">newPerson.jsp</result>
                –>
                <result name="input" type="freemarker">newPerson.ftl
    </result>
            </action>

    两个"success"的result轮流切换。

    试验结果如下:
    1、webwork.properties配置如下,使用vm的template,此时使用两种result的结果是相同的:

    java代码: 
    webwork.ui.theme=simple
    webwork.ui.templateDir=template/archive
    webwork.ui.templateSuffix
    =vm

    显示结果,显然onsubmit没有输出,此时datapicker标签没有输出(因为老的vm模板没有提供datapicker标签):

    java代码: 
    <form namespace="/" id="newPerson" name="newPerson" action="/starter/newPerson.action">

    2、webwork.properties配置如下,此时使用ftl的result和ftl的template:

    java代码: 
    webwork.ui.theme=simple
    webwork.ui.templateDir=template
    webwork.ui.templateSuffix
    =ftl

    显示结果,onsubmit输出正常:

    java代码: 
    <form id="newPerson" name="newPerson" onsubmit="dosomething" action="/starter/newPerson.action">


    3、webwork.properties配置如下,此时使用jsp的result和ftl的template:

    java代码: 
    webwork.ui.theme=simple
    webwork.ui.templateDir=template
    webwork.ui.templateSuffix
    =ftl


    显示结果,onsubmit没有输出:

    java代码: 
    <form namespace="/" id="newPerson" name="newPerson" action="/starter/newPerson.action">


    此时尝试使用theme="xhtml"还是没有输出。

    从上面的测试来看,似乎是个bug,可是在webwork网站却没有查到相关issue,怀疑是我这里的环境问题。以上测试在tomcat 5.5.12 or Weblogic 9.1 @ SUN JDK 1.5b6上面进行。希望哪位解决了上面问题指导一下我,谢谢。

     
  • tin 9:22 pm on January 19, 2006 Permalink | Log in to leave a Comment
    Tags:   

    Spring+Hibernate中使用Mysql存储过程初步 

    Hibernate中使用Mysql存储过程
    1、我使用了mysql-connector-java-5.0.0-beta-bin.jar(其实用老的mysql-connector-java-3.1.8-bin.jar也可以调用存储过程的)这个最新的mysql驱动。
    2、数据库我使用了mysql-5.0.18-win32,安装后建立了一个简单的数据表。
    sql如下:

    java代码: 
    create database testprocedure;
    use testprocedure;
    create table testtable (id int(11) AUTO_INCREMENT, content varchar(255), readcount int(11) DEFAULT 0,primary key (id));
    desc testtable;(查看是否建立正确)


    3、建立一个专用的用户(可选,建立时请使用具有grant权限的用户如root):

    java代码: 
    grant select,delete,update,create,alter,execute on testtable.* to testprocedure@"localhost" identified by "test";

    用户名为testprocedure,密码test。注意权限中的execute,它就是执行call procedure的权限。在你的Hibernate配置中使用该帐户。
    4、建立一个存储过程:
    sql如下:

    java代码: 
    delimiter //
    (注意//是新的命令结束符,方便我们建立procedure)
    create procedure readcountplusone (inputid int)
    begin
    update testtable set readcount = readcount + 1 where id = inputid;
    end//

    (建立存储过程完毕)
    delimiter ;
    (恢复命令结束符为;)

    5、测试一下存储过程:

    java代码: 
    insert into testtable values (null,‘test’,0);
    select * from testtable;
    call readcountplusone(1)
    ;
    select * from testtable;

    应该看到原先readcount为0,call以后变成1,而且每次call都加1。
    如果执行有错,可以删除procedure重新建立。
    删除的命令为drop procedure readcountplusone;
    6、开始在我们的Hibernate+Spring support项目中使用procedure:
    HBM映射我们不说了,这里没有使用named query。Hibernate+Spring的配置这里也不多说了,应该可以搜寻到很多文章。
    我的DAO是extends HibernateDAO,具体的使用方法可以参照其他很多讲Spring hibernate support的文章。
    我们建立一个方法,比较丑陋(只是测试,大家有好方法可以提),假设对应testtable的pojo为TestPojo,它的getId()返回id对应的值:

    java代码: 
    public void readCountPlusOne(final TestPojo pojo) {
            getHibernateTemplate().execute(new HibernateCallback() {
    public Object doInHibernate(Session session) {
    try {
    Connection conn = session.connection();

    String sql = "{call readcountplusone(?)}";
    CallableStatement stmt = conn.prepareCall(sql);
                            stmt.setLong(1, pojo.getId().longValue());
                            stmt.execute();
    } catch (Exception e) {
    if(log.isDebugEnable){
                                    log.debug("call DAO
    ‘s readCountPlusOne() faild, with Exception:");
                                    e.printStackTrace();
                            }
                        }

                        return null;
                    }
                });
        }

    7、然后我们在我们的bussiness中调用readCountPlusOne方法既可实现通过Hibernate调用一个简单的Mysql存储过程。

    有点走马观花,主要是把口舌都放在mysql部分,hibernate部分则用的比较简单,我想把调用方法改为Named Query,这样不会这么丑陋。
    抛砖引玉,谢谢。

     
    • shmily52322 9:27 pm on January 19, 2006 Permalink

      是搞软件的?/
      看的我眼花缭乱!
      厉害!

  • tin 8:48 pm on January 16, 2006 Permalink | Log in to leave a Comment
    Tags:   

    2006.1.16 工作总结 

    我们使用的JSValidation升级为1.0b4以后就不工作了,我本想放弃。后来下午灵机一动,把新的1.0b4用UTF-8转存一下就OK了,靠!而且同时发现我们使用的已经是1.0b4了,我去年就……靠靠!
    发现比较有趣的地方:
    1、Webwork封装的sessionMap其实就是Map,使用起来完全相同。使用map.put map.get即可,自己放什么类型就是什么类型。
    2、Webwork的OGNL里面自动set回来的parameter是String[]类型,遍历时使用((String[])session.get("somekey"))[0]即可访问到,注意先检测是否contains那个key。原理是由于html的form的name允许重复,所以返回的可能是parameter或者parameters,后者就是一个数组,所以OGNL的setter会自动把你的结果全部以数组方式保存。直接使用就有点麻烦了,不过无所谓了。所以webwrok里面ModelDriven风格才是推荐。
    所以我们的需要使用Session的UserAuthenticationManagerjiu只需map.get即可。
    而后就是漫长的实现,发现了global-results,这个需要配置在package里面。发现它可以覆盖,即在子package的global-results会覆盖父package的global-results,方便。
    不过要注意,在package里面,global-results要在action前面声明。
    然后还发现一个非常重大的Bug,或者说问题,是关于Spring的:
    在配置的时候使用模版方式定义,即:
    <bean id="basicActionWithAuthtication" abstract="true">
    此时该bean里面的所有注入属性都可以工作,也就是parent指向basicActionWithAuthtication的bean都会继承它的ref bean。
    但是在该bean里面声明的singleton="false"却不会被继承。
    这个需要参考以下参考书了,比较重要,不能误解!
    在Spring reference的第26-27页(1.2.6)第3.5节Abstract and child bean definitions:
    A child bean definition will inherit constructor argument values, property values and method overrides from the
    parent, with the option to add new values. If init method, destroy method and/or static factory method are
    specified, they will override the corresponding parent settings.
    The remaining settings will always be taken from the child definition: depends on, autowire mode, dependency
    check, singleton, lazy init.
    意思就是一般构造参数和参数值及方法都会从parent继承和覆盖,而如果指定了init方法destroy方法和static factory方法,也会覆盖parent的相应配置。
    但是depends on、autowire mode、dependency check、singleton、lazy这些属性则不会被继承,都直接从child中获取。
    这也就解释了我们使用的parent里面设置singleton="false"为什么不起作用(Spring默认true,其实就是我们的parent设置不会被继承)。
    里面还有个说明有意思:
    对于没有制定abstract="true"的action,如果它的class没有指定,则它默认情况下也是一个abstract。但是对于那些指定了class的bean,如果不指定abstract="false",则默认它会初始化。但是对于无abstract声明,但由没有class制定的bean,被引用或者初始化,则会报错!所以要注意,考虑好你的class是否是abstract,声明好。个人人为还是纯抽象并作为模版比较好,表示配置相同的那种方式(都指定class,且有parent关系)则不太合适。
    这个的严重性会造成Webwork的action变成singleton,如此的话,两台机器同时调用/administrator/load.action就会调出同一个admin,太可怕了!

     
  • tin 1:33 pm on January 11, 2006 Permalink | Log in to leave a Comment
    Tags:   

    java中的String的encoding和下载文件的jsp例子 

    晚上跟zh等同志一起看了下文件下载的中文问题,问题解决,并且收获不小:
    1、java的char类型是16bit,而不是c/c++中的8bit,所以char和byte之间的转换会造成严重的精度损失。而Java的char是Unicode的。
    2、java中String是基于char[]的,也就是说这个String天生就可以表示Unicode。所以如果从byte[]创建一个String就会涉及到一个严重的策略问题,是一个byte转一个String字还是两个byte转一个String字。
    3、所以我们常用的java转码中的语句somestr = new String(somestr.getBytes(),"ISO-8859-1")与somestr = new String(somestr.getBytes(),"GB2312")之间是有很大区别的,它们关系到从一个byte变两个byte或反过来。
    4、所以,对于单精度的"ISO-8859-1"与双精度的GB2312、GBK、utf-8处理的时候一定要分清,而且它也可以解决很多的问题。而如果你好好了解GB2312与GBK的效果其实很类似,他们只有部分的编码覆盖度上的区别,大部分字符是通用的,可是"ISO-8859-1"却与他们完全不同。
    5、还有一个有意思的地方:java.io.Writer与java.io.InputStream下面的东西有个明显的区别,前者接受char[],而后者接受byte[]。其实理解一下,他们之间的转换其实正好需要String的单字节编码与双字节编码的区别,我们可以用它们完成有意思的转换。在它们的沟通过程中我们如果使用buffer,则需要String作为中间者进行转换,算个小trick吧。
    6、从这里,我们引出今天解决的中文文件下载的问题中的有意思的地方:
    <%@ page language="java" import="java.io.PrintWriter"
    %><%
    String filename = (String)request.getAttribute("downloadFileName");
    String filepath = (String)request.getAttribute("downloadFileUrl");

    filename = new String(filename.getBytes(),"ISO-8859-1");
    if(filename != null && filepath != null) {
    response.setContentType("APPLICATION/OCTET-STREAM");
    response.setHeader("Content-Disposition",
    "attachment; filename=\"" + filename + "\"");
    java.io.FileInputStream fileInputStream =
    new java.io.FileInputStream(filepath);

    java.io.File file = new java.io.File(filepath);
    response.setContentLength((new Long(file.length()).intValue()));
    PrintWriter pw = response.getWriter();
    byte[] charArray = new byte[4096];
    int len;
    while ((len=fileInputStream.read(charArray)) != -1) {
     String s = new String(charArray,"ISO-8859-1");
     pw.write(s);
    }
    pw.flush();
    pw.close();
    fileInputStream.close();
    }
    %>

     
  • tin 3:12 pm on January 6, 2006 Permalink | Log in to leave a Comment
    Tags:   

    webork2与spring的autowire配合的trick 

    今天,又看了下上面这个例子里面的starter那个例子,发现:
    它使用了Spring的自动装配,以下两段代码效果相同:
    java代码: 

    <beans default-autowire="autodetect">
            <bean id="personManager" class="com.acme.PersonManager"/>
    </beans>

    java代码: 

    <beans>
            <bean id="personManager" class="com.acme.PersonManager"/>
            <bean id="listPeople" class="com.acme.ListPeople">
                    <property name="personManager" >
                            <ref local="personManager" />
                    </property>
            </bean>
            <bean id="createPserson" class="com.acme.CreatePerson">
                    <property name="personManager">
                            <ref local="personManager" />
                    </property>
            </bean>
    </beans>

    如果这样使用的话,如果在xwork里面配制好action的class,然后连这个class的bean都不用在spring里面声明了,其依赖也通过名字匹配自动装配了。
    真简单啊,想知道spring的autowire有没有性能损耗,如果每次装配都反射会不会性能很差?

     
  • tin 9:00 pm on January 5, 2006 Permalink | Log in to leave a Comment
    Tags:   

    webwork 2.2 中如何给Collection赋值 

    原本javaeye有这么一篇帖子“在WebWork2 Action中如何自动设置Array、List、Map”,是moxie大哥写的。
    http://forum.javaeye.com/viewtopic.php?t=8770

    但是已经是2004年11月的文章了,在webwork 2.2 b4中,XWorkList和XWorkMap已经是deprecated状态了,当时我就一头雾水,也没找到什么好的线索。
    去java.net下载了XWork的最新代码,看到了其中的注释,说这个工作已经可以自动完成了。
    又几经周折,才算搞明白先在如何让List、Map等工作起来:

    下面简单介绍一下:
    1、如果要将值映射到pojo的collection,则需要使用conversion功能。
    如我又一个Action,叫testAction:
    public class testAction extends ActionSupport {
     private Collection smoeAttrs = null;(使用webwork自动负值,应有对应getter和setter)
     private IDeptJgzTjkEcoAttDAO ecoAttDAO = null;(改DAO使用Spring注入,应有相应setter)

         public String execute() throws Exception {
             if (log.isDebugEnabled()) {
       log.debug("performing execute() method!");
             }

      //持久化collection里面的pojo
      for (Iterator iterator = smoeAttrs.iterator(); iterator.hasNext();) {
                  SomeAttr someAttr = (SomeAttr) iterator.next();
                  ecoAttDAO.saveOrUpdate(someAttr, someAttr.getId());
             }

             return Action.SUCCESS;
         }
    }

    对应一个pojo:
    package org.tin.test;

    public class SomeAttr implements Serializable {

     /** The composite primary key value. */
     private java.lang.Long id;

     private java.lang.Float fild1;
     private java.lang.String fild2;
     private java.util.Date fild3;

     /*
      ….
      对应的getter和setter
     */
    }

    可以看到,上面的Action声明的时候没有任何涉及到XWorkList的地方(moxie介绍的那种风格),也就是说现在webwork并不知道Collection里面放的pojo的类型。这就是Webwork目前的高明之处,这样的代码非常干净。但是如果要自动设定Collection的值,访问到这些Pojo,则一定要知道Pojo的类型,Webwork如何做呢?
    通过-conversion配置。
    需要在对应该才那个testAction.java的相同目录写一个testAction-conversion.properties文件(格式就是Action名字+“-conversion.properties”)。
    文件里面注明:
    Element_someAttrs = org.tin.test.SomeAttr (以前版本曾经用过Collection、Map分开,但是现在不管什么类型,都用Element)
    格式就是“Element_”+Action中Collection的名字+“=”+你的pojo的完整类名

    如此配置后,自动设置值的时候就可以知道你的pojo的类型了,很干净。

    下面一小段由于我接触Webwork不久,所以是个很初级的经验,如果需要则自取:
    回忆moxie帖子中的重要的部分,在post到相应action的页面的form中,input要遵循这样的命名:
    对应刚才所说的那个pojo:
    <form>
     <input  name="someAttrs[0].fild1" value="45555.6" id="xxx11" />
     <input  name="someAttrs[0].fild2" value="test" id="xxx12" />
     <input  name="someAttrs[0].fild3" value="2006-01-05" id="xxx13" />
     <input  name="someAttrs[1].fild1" value="45555.6" id="xxx21" />
     <input  name="someAttrs[1].fild2" value="test" id="xxx22" />
     <input  name="someAttrs[1].fild3" value="2006-01-05" id="xxx23" />
     <input  name="someAttrs[2].fild1" value="45555.6" id="xxx31" />
     <input  name="someAttrs[2].fild2" value="test" id="xxx32" />
     <input  name="someAttrs[2].fild3" value="2006-01-05" id="xxx33" />
    </form>

    如何输出?很简单,在列表页中:
    <ww:iterator value="someAttrs" status="someAttrsIter">
    <tr>
     <td>
      <ww:hidden name="someAttrs[%{#someAttrsIter.index}].id" value="%{id}"/>
      <ww:textfield name="someAttrs[%{#someAttrsIter.index}].fild1" value="%{fild1}"/></td>
     <td><ww:textfield name="someAttrs[%{#someAttrsIter.index}].fild2 value="%{fild2}"/></td>
     <td><ww:textfield name="someAttrs[%{#someAttrsIter.index}].fild3" value="%{fild3}"/></td>
    </tr>
    </ww:iterator>

    即可以,因为iteratror这个tag支持iteratroStatus这个东西,用它可以获取index、isOdd等信息,很方便。

    配合
    <action name="saveAction" class="testAction">
     <result name="success" type="redirect">/loadByInf.action?id=${someAttrOwner.id}</result>
    </action>

    则很容易的实现对Collection的CRUD。正好用到了ONGL的集中基本访问方式:#、%{}、${}

    以上内容,错漏难免。因为今天终于可以偷闲,赶紧结绳记之。欢迎大家讨论更简便的方法。

     
  • tin 8:06 pm on January 5, 2006 Permalink | Log in to leave a Comment
    Tags:   

    Webwork 2.2 b5中datapicker的本地化使用方法 

    仅作为记录,尽量简明:
    1、我使用Weblogic 8.1 SP5+Webwork 2.2 beta 5。2.2b5的Webwork已经完全转向使用jscalendar作为datapicker的js,而不是以前的tigracalendar,因为tigracalendar不支持国际化。Web项目使用FilterDispatcher,本应改可以将/webwork/*的请求拦截下来,但是它工做不正常。所以我把webwork.jar里面的\com\opensymphony\webwork\static目录拷贝到Web根目录,并将static目录重名名为webwork。
    此时,你的Web根目录下面应有一个名为webwork的目录,里面有jscalendar、dojo、niftycorners这几个文件加,如果不需要其它的,可以只保留jscalendar一个目录。
    2、在需要显示datapicker的地方使用如下标记<ww:datepicker name="ecoInf.turninDate" id="ecoInf.turninDate" template="datepicker.ftl" language="cn_utf8" format="%Y-%m-%d %H:%M:%S" showstime="true" />。
    其中template完全可以不写。而name标明你的数据的来源。id是方便javascript访问所保留的,可以和name相同(如果有重复name,如经过iterator,则需要区别其id,保持id在html dom中唯一)。
    showstime标明是否可以选择时间,可以是"true","false","24","12"。
    language决定jscalendar使用的语言,参照下面说明。
    3、language指定的语言其实就对应jscalendar/lang下面的语言文件,格式就是calendar-语言名.js,默认的中文使用的是zh。但是其实j2ee项目经常面对中文乱码问题,最佳解决方案就是统一使用UTF-8。但是calendar-zh.js正好不是UTF-8的,所以如果直接使用zh语言则datapicker没法正常工作。
    我的解决方法是将webwork附带的jscalendar 1.0的lang里面的cn_utf8.js改名为calendar-cn_utf8.js,然后将language="cn_utf8"就工作正常了。
    4、关于时间的显示格式。其实cn_utf8.js里面已经制定了时间的标准显示格式是%Y-%m-%d,符合我们的习惯。但是有时我们需要显示具体时间,参照他们网站的说明,使用format="%Y-%m-%d %H:%M:%S",这个也符合我们的习惯。
    发个牢骚:
    本来奇简单。但是很奇怪/webwork/*居然不能在Weblogic下自动映射,我一会而去试验下Tomcat,还有就是js解析utf-8出错造成整个js没法工作,浪费了半天时间,唉。
     
  • tin 8:06 pm on January 5, 2006 Permalink | Log in to leave a Comment
    Tags:   

    eXtremeComponent在中文环境下的使用 

    不知道大家是否使用过eXtremeComponent,我刚才在java eye没有搜索到。
    最早知道eXtremeComponent是从http://www.open-open.com,去年就在用了,感觉明显比display-tag要好用多了。
    它使用jstl,所以与webwork集成也很方便,不象display-tag那样需要把hibernate返回的collection复制一遍再访问。

    具体的使用方法参考官方网站好了:
    官方网站在这里:
    http://www.extremecomponents.org/extremesite/welcome.jsp
    最新的版本是1.0.1-M4-A14,可以到这里下载:
    http://www.extremecomponents.org/extremesite/public/download/
    或者直接下载:
    http://www.extremecomponents.org/extremesite/public/download/extremecomponents-1.0.1-M4-A14.zip
    但是这个snapshot版本没有依赖lib和资源文件等,推荐去这里下一个完整版本备用,目前最新的Production Release包是eXtremeComponents-1.0.1-M3-with-dependencies.zip:
    https://sourceforge.net/project/showfiles.php?group_id=108168
    最新版本的说明书在这里,说明书用的doc book格式,写的也很清楚:
    http://www.extremecomponents.org/extremesite/public/download/eXtremeComponents.pdf
    很多人都对他使用的doc book声称doc感兴趣,spring和hibernate都用doc book,可是一般看不到源文件。作者很慷慨将doc book的源文件也分享了,是学习是学习使用doc book的好东西:
    http://www.extremecomponents.org/extremesite/public/download/generate-docs.zip

    资源就贴到这里,这里要提及作者Jeff Johnston人非常热情,论坛上四处可见他的身影,给他发信他也是每信必会、有求必应,承蒙他多次帮助。而且论坛中大家多次提及中文问题,他也很重视。

    转入正题:
    我贴一下一个例子:
     <ec:table
     items="ecoAttrs"
     action="/jgz/tjk/eco/listTjkAttByInfId.action"
     imagePath="${pageContext.request.contextPath}/css/table/zh_CN/*.gif"
     cellpadding="1"
     title="农村经济运行情况列表"
     locale="zh_CN"
     rowsDisplayed="30">
      <ec:export view="xls" fileName="jgz_zyjjzbwcqk.xls" tooltip="输出Excel文件"/>
      <ec:exportPdf fileName="jgz_zyjjzbwcqk.pdf" tooltip="输出PDF文件" headerColor="blue" headerBackgroundColor="red" headerTitle="密云县农村经济月份经济主要指标完成情况表"/>
      <ec:exportCsv fileName="jgz_zyjjzbwcqk.txt" tooltip="输出CSV文件" delimiter="|"/>
      <ec:row>
       <ec:column property="ofTown.name" title="乡镇名称"/>
       <ec:column property="ncJihua" title="农村计划"/>
       <ec:column property="ncWancheng" title="农村完成"/>
       <ec:column property="ncQunian" title="农村去年"/>
       <ec:column property="zongShouRuWCJH" title="完成计划%"/>
       <ec:column property="zongShouRuTB" title="同比+/-%"/>
      </ec:row>
     </ec:table>

    其中ecoAttrs是一个collection,放入pojo。action里面写你这个页面的访问方法(如我的页面是一个action,其他的如.do或者.jsp什么的都可以)。rowsDisplayed是默认显示条数,它可以自动实现分页。
    下面的三个<ec:export>是导出三种格式用的,不用的话可以不写(写了需要在web.xml配置相应的filter)。
    <ec:column>里面放属性,property指向pojo的相应属性,而title是表头显示的信息,这个标签需要用<ec:row>包起来(1.0.1 m4以后)(抱歉pojo比较丑,出自同事之手)。

    这里放一套我做的中文图标:
    http://tiny.51.net/extremecomponent/zh_CN.rar
    还有我该写了一下css,更适合使用中文,将字体该为%大小,可以定义.eXtremeTable里面的font-size,即影响所有eXtremeTable里面的字体大小,也方便写js来动态修改大小:
    http://tiny.51.net/extremecomponent/extremecomponents.css

    贴一下我在web.xml里面的配置:
    <filter>
     <filter-name>eXtremeExport</filter-name>
     <filter-class>
      org.extremecomponents.table.filter.ExportFilter
     </filter-class>
    </filter>

    <filter-mapping>
     <filter-name>eXtremeExport</filter-name>
     <url-pattern>/*</url-pattern>
    </filter-mapping>

    <taglib>
     <taglib-uri>/extremecomponents</taglib-uri>
     <taglib-location>/WEB-INF/tld/extremecomponents.tld</taglib-location><!– 别忘了把那个tld拷贝到相应目录去 –>
    </taglib>

    其实,那个filter只是在使用<ec:export>的时候才需要,不过这个功能还是很有用的。

    export里面的excel和pdf默认不支持中文,需要手工修改源码,excel的比较简单:
    修改org.extremecomponents.table.view.XlsView.java(我指的是1.0.1-M4-A14的相应代码)
    102行:
    HSSFCell hssfCell = hssfRow.createCell(cellnum);
    hssfCell.setEncoding(HSSFCell.ENCODING_UTF_16);(就是添加这一行)
    122行:
    HSSFCell cell = row.createCell(cellnum);
    cell.setEncoding(HSSFCell.ENCODING_UTF_16);(就是添加这一行)
    这个在使用UTF-8时工作正常。如果其他Unicode环境可以尝试HSSFCell.ENCODING_COMPRESSED_UNICODE。

    编译后将对应.class放到WEB-INF/classes相应目录就可以了。

    pdf view的比较麻烦,还没尝试,解决方法参照这个帖子:
    http://extremecomponents.org/forum/viewtopic.php?t=139&highlight=chinese+filter
    http://www-128.ibm.com/developerworks/cn/xml/x-ospdf/index.html

    还有一小点:
    升级到1.0.1-M4-A14以后两个图片改名了,如果用1.0.1-M3的对应gif则需要该如下两个文件名(我修改的那个ZH-CN已经重命名过了):
    searchArrow.gif -> filterArrow.gif
    search.gif -> filter.gif

    说的比较罗嗦,主要是想让和我一样的非常初级水平的朋友能够比较容易上手。其实eXtremeComponent的文档很不错,用那个上手其实更好,我仅抛砖引玉,各位大虾多多包涵。

     
c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
esc
cancel