Fork me on GitHub
24 Apr 2014
分享到:
Comments

集成Diagram Viewer跟踪流程

首先这是一篇迟来的教程,因为从5.12版本(目前最新版本为5.15.1)开始就已经提供了Diagram Viewer这个流程图跟踪组件,不管如何总归有人需要用到,所以我觉得还是要和大家分享一下。

1. 前言

目前被大家所采用的流程图跟踪有两种方式:

  • 一种是由引擎后台提供图片,可以把当前节点标记用红色
  • 一种是比较灵活的方式,先用引擎接口获取流程图(原图),然后再通过解析引擎的Activity对象逐个解析(主要是判断哪个是当前节点),最后把这些对象组成一个集合转换成JSON格式的数据输出给前端,用Javascript和Css技术实现流程的跟踪

这两种方式在kft-activiti-demo中都有演示,这里就不介绍了,参考流程跟踪部门代码即可。

2. Diagram Viewer简介

Diagram Viewer是官方在5.12版本中添加的新组件,以Raphaël为基础库,用REST(参考:《如何使用Activiti Rest模块》)方式获取JSON数据生成流程图并把流程的处理过程用不同的颜色加以标注,最终的效果如下图所示。

在应用中使用时也很方便,把这个组件的源码复制到项目中再配置一个REST拦截器,最后拼接一个URL即可;举个例子:

http://demo.kafeitu.me/kft-activiti-demo/diagram-viewer/index.html?processDefinitionId=leave-jpa:1:22&processInstanceId=27

这个URL中有两个参数:

  • processDefinitionId: 流程定义ID
  • processInstanceId: 流程实例ID

3. 集成Diagram Viewer

3.1 创建REST路由类

REST路由类源码在官方的Activiti Explorer里面有提供,代码如下:

package org.activiti.explorer.rest;

import org.activiti.rest.common.api.DefaultResource;
import org.activiti.rest.common.application.ActivitiRestApplication;
import org.activiti.rest.common.filter.JsonpFilter;
import org.activiti.rest.diagram.application.DiagramServicesInit;
import org.activiti.rest.editor.application.ModelerServicesInit;
import org.restlet.Restlet;
import org.restlet.routing.Router;

public class ExplorerRestApplication extends ActivitiRestApplication {
  
  public ExplorerRestApplication() {
    super();
  }
  /**
   * Creates a root Restlet that will receive all incoming calls.
   */
  @Override
  public synchronized Restlet createInboundRoot() {
    Router router = new Router(getContext());
    router.attachDefault(DefaultResource.class);
    ModelerServicesInit.attachResources(router);
    DiagramServicesInit.attachResources(router);
    JsonpFilter jsonpFilter = new JsonpFilter(getContext());
    jsonpFilter.setNext(router);
    return jsonpFilter;
  }

}

把这个路由配置到web.xml中:


    ExplorerRestletServlet
    org.restlet.ext.servlet.ServerServlet
    
        
        org.restlet.application
        org.activiti.explorer.rest.ExplorerRestApplication
    



	ExplorerRestletServlet
	/service/*

3.2 复制Diagram Viewer组件

在官方提供的Zip文件(可以从www.activiti.org/download.html下载)中有一个wars目录,用压缩工具解压activiti-explorer.war文件,目录结构如下图:

diagram-viewer复制到项目的webapp目录(或者是WebRoot目录)下,在项目中需要跟踪的地方拼接访问diagram-viewer/index.html的URL即可,别忘记了刚刚介绍的两个重要参数。

http://demo.kafeitu.me/kft-activiti-demo/diagram-viewer/index.html?processDefinitionId=leave-jpa:1:22&processInstanceId=27

URL中有两个参数:

  • processDefinitionId: 流程定义ID
  • processInstanceId: 流程实例ID

这是一个独立的页面,你可以直接打开它或者把它嵌入在一个对话框里面(kft-activiti-demo就是用的嵌入方式)。

18 Apr 2014
分享到:
Comments

在Activiti中集成JPA(解决动态表单生成的大量数据)

1. 为何集成JPA

在《比较Activiti中三种不同的表单及其应用》一文中介绍了不同表单的特点以及表现形式,相信这是每个初学者都会面临表单类型的选择。

如果选择了使用动态表单那么将面临一个比较“严峻”的问题——大数据量,我们知道动态表单的内容都保存在一张表中(ACT_HI_DETAIL),我们也清楚动态表单中每一个Field都会在该表中插入一条记录,假如一个流程共有20个字段,这个数据量大家可以计算一下,每天多少个流程实例,每个月、每年多少?

日积月累的大数据会影响系统的性能,尤其涉及到关联查询时影响更深,除了性能之外动态表单还有一个弊端那就是数据是以的形式存储没有任何数据结构可言,流程运行中生成的数据很难被用于分析、查询,如何破解嘞?

2. 如何集成JPA

Activiti除了核心的Engine之外对企业现有的技术、平台、架构都有所支持,对于业务实体的持久化当然也会有所支持,那就是EJB的标准之一)——JPA,引擎把JPA的API引入到了内部,使用JPA功能的时候只需要把entityManagerFactory配置到引擎配置对象(参考:谈谈Activiti的引擎与引擎配置对象)即可。

参考用户手册的JPA章节,介绍了引擎配置对象中的几个jpa有关的属性,如下:

  • jpaPersistenceUnitName: 使用持久化单元的名称(要确保该持久化单元在类路径下是可用的)。根据该规范,默认的路径是/META-INF/persistence.xml)。要么使用 jpaEntityManagerFactory 或者jpaPersistenceUnitName。
  • jpaEntityManagerFactory: 一个实现了javax.persistence.EntityManagerFactory的bean的引用。它将被用来加载实体并且刷新更新。要么使用jpaEntityManagerFactory 或者jpaPersistenceUnitName。
  • jpaHandleTransaction: 在被使用的EntityManager 实例上,该标记表示流程引擎是否需要开始和提交/回滚事物。当使用Java事物API(JTA)时,设置为false。
  • jpaCloseEntityManager: 该标记表示流程引擎是否应该关闭从 EntityManagerFactory获取的 EntityManager的实例。当EntityManager 是由容器管理的时候需要设置为false(例如 当使用并不是单一事物作用域的扩展持久化上下文的时候)。

2.1 配置持久化单元或者EntityManagerFactory

要在引擎中使用JPA需要提供EntityManagerFactory或者提供持久化单元名称(引擎会自动查找最终获取到EntityManagerFactory对象),在使用的时候可以根据自己的实际情况进行选择,在kft-activiti-demo中使用了jpaEntityManagerFactory属性注入EntityManagerFactory对象的方式。

2.2 Standalone模式的JPA配置

	
	
    

2.3 Spring(托管)模式的JPA配置

	
	
    

3. 实例分析

在最新版本(1.10)的kft-activiti-demo中添加了JPA演示,大家可以从Github上下载源码查看源码。

请假流程-JPA版本

3.1 相关说明

  • 流程定义文件:leave-jpa.bpmn
  • 实体文件:me.kafeitu.demo.activiti.entity.oa.LeaveJpaEntity
  • 实体管理器:me.kafeitu.demo.activiti.service.oa.leave.LeaveEntityManager

3.2 创建实体

在流程定义文件中定义了一个流程的start类型监听器:


  

这个监听器的触发的时候会执行一个表达式,调用名称为leaveEntityManager的Spring Bean对象的newLeave方法,并且把引擎的Execution对象传递过去,得到一个LeaveJpaEntity对象后设置到引擎的变量中(名称为leave)。

下面是LeaveEntityManager.java的代码:

@Entity(name = "LEAVE_JPA")
public class LeaveJpaEntity implements Serializable {

    private Long id;
    private String processInstanceId;
    private String userId;
    private Date startTime;
    private Date endTime;
    private Date realityStartTime;
    private Date realityEndTime;
    private Date reportBackDate;
    private Date applyTime;
    private String leaveType;
    private String reason;

    /**
     * 部门领导是否同意
     */
    private String deptLeaderApproved;

    /**
     * HR是否同意
     */
    private String hrApproved;
    
    ...
}
@Service
public class LeaveEntityManager {

    @PersistenceContext
    private EntityManager entityManager;
    
    /* 把流程变量的值赋值给JPA实体对象并保存到数据库 */
    @Transactional
    public LeaveJpaEntity newLeave(DelegateExecution execution) {
        LeaveJpaEntity leave = new LeaveJpaEntity();
        leave.setProcessInstanceId(execution.getProcessInstanceId());
        leave.setUserId(execution.getVariable("applyUserId").toString());
        leave.setStartTime((Date) execution.getVariable("startTime"));
        leave.setEndTime((Date) execution.getVariable("endTime"));
        leave.setLeaveType(execution.getVariable("leaveType").toString());
        leave.setReason(execution.getVariable("reason").toString());
        leave.setApplyTime(new Date());
        entityManager.persist(leave);
        return leave;
    }

    public LeaveJpaEntity getLeave(Long id) {
        return entityManager.find(LeaveJpaEntity.class, id);
    }

}

当启动流程后查看表LEAVE_JPA中的数据与表单填写的一致。

3.3 在流程中更改实体的值

部门领导或者人事审批节点完成时需要把审批结果更新到LeaveJpaEntity属性中(即更新表LEAVE_JPA),所以在这两个任务上添加一个complete类型的监听器,如下所示:


	
		
	



	
		
	

3.4 流程结束后删除表单数据

熟悉Activiti表的应该知道表单数据会保存在表ACT_HI_DETAIL中,特性是字段TYPE_字段的值为FormProperty,我们只要根据流程实例ID过滤删除记录就可以清理掉已经结束流程的表单数据。

在最新版本的Demo中(1.10版本)添加了一个类用来执行SQL:

@Component
public class ActivitiDao {

    @PersistenceContext
    private EntityManager entityManager;

    /**
     * 流程完成后清理detail表中的表单类型数据
     * @param processInstanceId
     * @return
     */
    public int deleteFormPropertyByProcessInstanceId(String processInstanceId) {
        int i = entityManager.createNativeQuery("delete from act_hi_detail where proc_inst_id_ = ? and type_ = 'FormProperty' ")
                .setParameter(1, processInstanceId).executeUpdate();
        return i;
    }

}

流程中定义了一个流程级别的结束监听器me.kafeitu.demo.activiti.service.oa.leave.LeaveProcessEndListener

@Service
@Transactional
public class LeaveProcessEndListener implements ExecutionListener {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    ActivitiDao activitiDao;

    @Override
    public void notify(DelegateExecution execution) throws Exception {
        String processInstanceId = execution.getProcessInstanceId();

        int i = activitiDao.deleteFormPropertyByProcessInstanceId(processInstanceId);
        logger.debug("清理了 {} 条历史表单数据", i);
    }
}

3.5 已知问题(未解决)

由于引擎的Bug导致数据不能完整删除

图中的三条数据因为是在销假任务完成后设置的,不知道是不是引擎的Bug导致插入这三个表单属性比调用流程结束监听器还晚(从引擎的日志中可以分析出来)导致这三条记录不能被删除,因为在删除的时候这三条数据还没有插入到数据库。

这个问题后面会继续跟踪,解决了会在这里更新!!!

23 Jan 2014
分享到:
Comments

剖析Activiti的Activity

1. 窥视Activity内部

在设计流程时每一个组件在Activiti中都可以称之为——Activity,部署流程时引擎把XML文件保存到数据库,当启动流程、完成任务时会从数据库读取XML并转换为Java对象,很多人想在处理任务时获取任务的一些配置,例如某个任务配置了哪些监听器或者条件Flow配置了什么条件表达式。

2. 代码

下面的代码做了简单的演示,根据不同的Activity类型输出属性,读者可以继续探索其他不同类型Activity的属性,最终可以获取到所有Activity的属性。

3. 输出结果示例

{taskDefinition=org.activiti.engine.impl.task.TaskDefinition@19c6e4d1, default=null, name=部门领导审批, documentation=null, type=userTask}
{conditionText=${!deptLeaderPass}, condition=org.activiti.engine.impl.el.UelExpressionCondition@50d8628f, name=不同意, documentation=null}
{conditionText=${deptLeaderPass}, condition=org.activiti.engine.impl.el.UelExpressionCondition@2e2ec3c0, name=同意, documentation=null}
{taskDefinition=org.activiti.engine.impl.task.TaskDefinition@3589f0, default=null, name=调整申请, documentation=null, type=userTask}
{taskDefinition=org.activiti.engine.impl.task.TaskDefinition@3af2ebab, default=null, name=人事审批, documentation=null, type=userTask}
{conditionText=${hrPass}, condition=org.activiti.engine.impl.el.UelExpressionCondition@224e45c9, name=同意, documentation=null}
{conditionText=${!hrPass}, condition=org.activiti.engine.impl.el.UelExpressionCondition@40c7a0b7, name=不同意, documentation=null}
{taskDefinition=org.activiti.engine.impl.task.TaskDefinition@72086f9a, default=null, name=销假, documentation=null, type=userTask}
{conditionText=${reApply}, condition=org.activiti.engine.impl.el.UelExpressionCondition@7d721f3, name=重新申请, documentation=null}
{conditionText=${!reApply}, condition=org.activiti.engine.impl.el.UelExpressionCondition@3cf5dc8a, name=结束流程, documentation=null}
{name=Start, documentation=null, type=startEvent}
{name=End, documentation=null, type=endEvent}
30 Aug 2013
分享到:
Comments

在Activiti中使用UUID作为主键生成策略

1. 默认的主键生成策略

了解过Activiit表中数据的同学可能知道记录的主键ID是用自增的生成策略,这样的生成策略有两个优点:

  • 有顺序:所有引擎的表在插入新记录时全部使用同一个ID生成器
  • 便于记忆:因为是自增的所以有一定的顺序,便于记忆;例如业务人员让管理员删除一条数据(ID为5位左右的长度),管理员只要看一眼就可以记住

当然也有缺点

  • 随着时间的推移或者数据量非常大自增的ID生成策略的“便于记忆”优势也就不存在了,因为ID的位数会逐步增加(举个例子,我们公司做的一个小系统,用户量在30人左右,ID的长度已经到了7位数)
  • 并发量高时会可能导致主键冲突

在引擎初始化的时候会注册ID生成器,看过源码的同学还可能知道有一个类:org.activiti.engine.impl.db.DbIdGenerator,这个类实现了一个接口:org.activiti.engine.impl.cfg.IdGenerator

public interface IdGenerator {
  String getNextId();
}

该接口仅有一个方法,返回一个String类型的字符串,有兴趣的同学可以去看看引擎默认的生成器源码,接下来介绍如何更改引擎的主键生成器。

2. 更改默认的主键生成器

UUID是全球唯一的主键生成器,也是除自增策略之外最常用的一种,很幸运:引擎内置了UUID生成器实现。

要更改引擎默认的主键生成器很简单,只需要在配置引擎时覆盖一个属性即可,代码如下:



	

ID为“uuidGenerator”的bean对象就是引擎内部提供的UUID生成器,把Bean对象注册好以后覆盖引擎的“idGenerator”属性即可;再次启动系统后创建的新数据都会用UUID生成策略。

2.1 添加依赖

引擎提供的UUID生成器依赖fastxml的一个模块,需要在pom.xml(Maven工程)中添加如下依赖:


    com.fasterxml.uuid
    java-uuid-generator
    3.1.3

用UUID生成策略产生的ID

3. 自定义ID生成器

  • Step 1:创建一个类实现接口org.activiti.engine.impl.cfg.IdGenerator
  • Step 2:参考本文第2部分 ^_^

更多博客

Activiti 5.13修复版本5.13.1-kft发布 17 Jul 2013 Comments
一个基于Maven的配置文件管理成功案例 29 Jun 2013 Comments
利用100行代码动态创建并部署流程 27 May 2013 Comments
谈谈Activiti的引擎与引擎配置对象 19 Apr 2013 Comments
博客论坛正式上线 13 Apr 2013 Comments
Activiti 5.12.X 衍生版本发布 05 Apr 2013 Comments
IntelliJ IDEA中文乱码解决办法 26 Mar 2013 Comments
Activiti Designer 5.12.0 发布 23 Mar 2013 Comments
Activiti快速入门项目kft-activiti-demo 1.7.0版本发布 10 Mar 2013 Comments
整合Activiti Modeler到业务系统(或BPM平台) 10 Mar 2013 Comments
Activiti 5.12发布 06 Mar 2013 Comments
利用静态服务提升读取Activiti流程图的性能 14 Feb 2013 Comments
如何使用Activiti Rest模块 12 Jan 2013 Comments
kft-activiti-demo 1.5.0 发布 15 Dec 2012 Comments
Activiti Explorer 5.11登录页面乱码解决办法 15 Dec 2012 Comments
jQuery UI Portlet V1.1.0 发布 08 Dec 2012 Comments
Activiti 5.11发布 05 Dec 2012 Comments
基于jQuery UI的Portlet插件—jQuery UI Portlet 22 Nov 2012 Comments
Activiti 5.10支持直接部署扩展名为bpmn的流程文件 22 Oct 2012 Comments
新版Activiti Modeler发布以及教程 30 Sep 2012 Comments
Activiti Explorer中文汉化 30 Sep 2012 Comments
activiti:initiator的作用及其使用 14 Sep 2012 Comments
jqGrid启用列冻结之后列高度不一致问题解决办法 25 Aug 2012 Comments
谈谈Activiti中流程对象之间的关系 09 Aug 2012 Comments
比较Activiti中三种不同的表单及其应用 05 Aug 2012 Comments
Activiti入门,学习资源索引 04 Aug 2012 Comments
Zsh(oh-my-zsh)的Maven自动提示插件(zsh-maven-complection) 18 Jul 2012 Comments
如何打包Activiti的流程资源文件(bpmn20.xml、form、png) 18 Jul 2012 Comments
如何使用Signavio打包Activiti Modeler 07 Jun 2012 Comments
Activiti快速入门项目-kft-activiti-demo 26 May 2012 Comments
Activiti设置流程发起用户信息 20 May 2012 Comments
我是如何在Linux(Ubuntu)上工作的? 19 May 2012 Comments
让Activiti记录变量历史信息 18 May 2012 Comments
从Activiti Designer5.8升级到5.9遇到的问题 01 May 2012 Comments
同步或者重构Activiti Identify用户数据的多种方案比较 23 Apr 2012 Comments
在Linux(Ubuntu)+Nginx安装配置AjaXplorer 14 Apr 2012 Comments
在Ubuntu(Debian)上安装最新版Git 10 Apr 2012 Comments
在Ubuntu上安装Git1.7.10-rc4(中文化) 05 Apr 2012 Comments
推荐:jQuery提示插件qTip2 03 Apr 2012 Comments
Git Submodule使用完整教程 27 Mar 2012 Comments
我最喜爱的工具-oh-my-zsh 25 Mar 2012 Comments
工作流引擎Activiti使用总结 22 Mar 2012 Comments
从Wordpress迁移到Github 21 Mar 2012 Comments
Linux(Ubuntu)环境安装配置Nginx+Dokuwiki 03 Feb 2012 Comments
Linux下springside4快捷脚本(quick-start、generate-project) 09 Dec 2011 Comments
Linux下springside3快捷脚本(quick-start、generate-project) 13 Aug 2011 Comments
jQuery UI及其插件在企业环境的应用总结 24 Jul 2011 Comments
Ubuntu配置ngnix+phpmyadmin 16 Jul 2011 Comments
Ubuntu安装ORACLE-XE 15 Jul 2011 Comments
Windows Server 2008 R2 X64安装Oracle 10g R2后不能创建数据库问题解决办法 26 Jun 2011 Comments
推荐:国内第一本Maven书籍——《Maven实战》 19 Nov 2010 Comments
Maven多模块布局实例详解 11 Nov 2010 Comments
CAS单点登录(SSO)完整教程(2012-02-01更新) 05 Nov 2010 Comments
maven-war-plugin插件的warSourceExcludes和packagingExcludes参数的区别 03 Nov 2010 Comments
公布一下我的Evernote分享地址 03 Nov 2010 Comments
Maven常见问题收集(持续更新-2010-12-15) 01 Nov 2010 Comments
《Maven实战》最新消息,11月初出版 27 Oct 2010 Comments
jquery.validate插件remote规则相同值不验证的问题解决办法 25 Oct 2010 Comments
城市级联选择插件jquery.area2select闪亮登场(前后台设计) 18 Oct 2010 Comments
工欲善其事必先利其器--Java Web快速开发框架--Springside 11 Oct 2010 Comments
Struts2 Annotation实现文件下载功能 03 Oct 2010 Comments
利用Windows的计划任务自动更新最新的Chromium 01 Oct 2010 Comments
利用JavaScript获取窗口/Body的宽度和高度(让jqGrid自适应窗口大小) 20 Aug 2010 Comments
Apache Asia Roadshow 2010 Juven Maven PPT和视频下载 16 Aug 2010 Comments
Hudson系列教程 15 Aug 2010 Comments
Apache Asia Roadshow 2010归来 14 Aug 2010 Comments
推荐精选3枚jQuery遮罩插件 12 Aug 2010 Comments
Eclipse+Maven+WTP+Tomcat不能Run On Server其中一个原因 10 Aug 2010 Comments
Springside3.3.3报错:java.lang.NoClassDefFoundError: org/codehaus/classworlds/Launcher解决办法 09 Aug 2010 Comments
Maven学习引导 07 Aug 2010 Comments
工欲善其事,必先利其器 30 Jul 2010 Comments
为jstree添加双击事件切换[展开/收缩]功能 19 Jun 2010 Comments
JasperReports iReport导出PDF中文解决办法 30 May 2010 Comments
[转][推荐]15 个 JavaScript Web UI 库 20 May 2010 Comments
解决a different object with the same identifier value was already associated with the session错误 18 May 2010 Comments
jqGrid查询中文乱码问题解决办法(2011-11-11) 23 Apr 2010 Comments
Maven下用mvn assembly:assembly打包class文件重复 22 Apr 2010 Comments
[转][评论]谷歌重申不过滤搜索结果 做好停止中国业务准备 12 Mar 2010 Comments
Win7下不能安装Oracle11g解决办法 03 Mar 2010 Comments
直逼 Flash 的流畅感:jQuery 运动特效展示 02 Mar 2010 Comments
IE6浏览器葬礼的背后 02 Mar 2010 Comments
[转][推荐]程序员们,请珍爱自己的身体 25 Feb 2010 Comments
Sexy Buttons(Web 按钮[图标]素材) 10 Feb 2010 Comments
jQuery 1.4.1 中文文档 CHM 版发布 02 Feb 2010 Comments
转:关于web2.0网站易用性设计的一些原则 27 Jan 2010 Comments
jQuery1.4 API 区别与更新中文版 19 Jan 2010 Comments
分享:Java日期工具类 15 Jan 2010 Comments
jQuery 1.4 正式版发布啦(14 Days of jQuery) 15 Jan 2010 Comments
推荐:基于jQuery开发仿Google Calendar(jQuery Week Calendar) 12 Jan 2010 Comments
推荐:2009 年度最佳 jQuery 插件 12 Dec 2009 Comments
程序员的学历有多重要 18 Nov 2009 Comments
推荐:正则表达式口诀及教程 03 Nov 2009 Comments
Json-lib 与 hibernate 共同使用的问题 24 Oct 2009 Comments
备忘:金格、用友CELL不能在IE8下使用的解决办法 14 Oct 2009 Comments
22岁生日 22 Aug 2009 Comments
使用hibernate和json-lib时忽略属性和集合 04 Aug 2009 Comments
Hibernate的映射类型 hibernate mysql映射类型 30 Jul 2009 Comments
叽歪怎么了? 29 Jul 2009 Comments
[推荐]改进的提示插件-jQuery.hiAlerts.1.0 27 Jul 2009 Comments
《疯狂程序员》一书中的奥秘 23 Jul 2009 Comments
Twitter用户发起“拒绝IE6”请愿活动 18 Jul 2009 Comments
推荐一个ajax资源站点 16 Jul 2009 Comments
做了一次集成服务:基于weebox和simpletree的dialogtree诞生了 16 Jul 2009 Comments
站点GBK编码下jQuery Ajax中文乱码解决方案 01 Jul 2009 Comments
简单实现在基于Java的AJAX环境下未登录自动跳转流程详解(spring代理struts的action) 22 Jun 2009 Comments
如何判断一个请求是否为AJAX请求 22 Jun 2009 Comments
夏天到了,终于收到迟来的WordPress T恤了 08 Jun 2009 Comments
jQuery性能优化指南 23 May 2009 Comments
心系5.12(2009年5.12日 2:28分我们集体默哀3分钟) 11 May 2009 Comments
2009.5.1~5.3杭州之旅(露营、雨中游西湖) 05 May 2009 Comments
IE中丢失session问题解决办法 21 Apr 2009 Comments
6个你必须用到AJAX的地方与6个不必用到的地方 04 Apr 2009 Comments
庆祝博客PageRank提升到了3/10 04 Apr 2009 Comments
wordcamp 2009 in ShangHai归来 04 Apr 2009 Comments
推荐国外著名的xhtml+css模板 28 Mar 2009 Comments
一行jQuery代码打印九九乘法表 25 Mar 2009 Comments
IE浏览器下的JS实用调试小工具——fullsource(2K) 11 Mar 2009 Comments
jQuery.plugin——强大的遮罩层(nyroModal) 02 Mar 2009 Comments
HR教你怎么投简历 01 Mar 2009 Comments
实例解析java + jQuery + json工作过程(获取JSON数据) 28 Feb 2009 Comments
自己动手定制ajax loading图片 26 Feb 2009 Comments
实例解析java + jQuery + json工作过程(登录) 24 Feb 2009 Comments
推荐一个不错的js编辑工具Spket IDE for eclipse 22 Feb 2009 Comments
模拟google相册鼠标移动提示信息 22 Feb 2009 Comments
推荐日期选择组件My97 DatePicker 21 Feb 2009 Comments
既爱又恨Firefox 21 Feb 2009 Comments
转:Javascript 脚本的调试经验 21 Feb 2009 Comments
分享:JavaScript在线压缩工具 21 Feb 2009 Comments
从Google搜索联想到了jQuery 20 Feb 2009 Comments
单表查询树形结构的SQL语句 20 Feb 2009 Comments
申请友链及说明 20 Feb 2009 Comments
我暴露了程序员的习惯 19 Feb 2009 Comments
推荐jQuery插件系列——表单验证formValidator 18 Feb 2009 Comments
jQuery1.3中文API下载(HTML、chm版) 14 Feb 2009 Comments
基于Java、jQuery应用的账务管理系统开源了(09.3.19更新) 14 Feb 2009 Comments
程序员的十种级别,看看你属于哪个级别的程序员 13 Feb 2009 Comments
基于Java、jQuery开发的账务管理系统(个人版)即将开源 13 Feb 2009 Comments
推荐使用轻量级ajax框架-jQuery 10 Feb 2009 Comments
基于jQuery开发的账务管理系统(个人版)演示 08 Feb 2009 Comments
优秀程序员的两大要素:懒+笨 08 Feb 2009 Comments
《jQuery in Action》中文版即将上市 07 Feb 2009 Comments
经典:从追MM谈Java的23种设计模式 07 Feb 2009 Comments
javascript中字符串累加的性能优化(String和StringBuffer) 07 Feb 2009 Comments
出现net.sf.json.JSONException: There is a cycle in the hierarchy异常的解决办法 07 Feb 2009 Comments
关于WEB开发中引入javascript文件方式的一点建议 07 Feb 2009 Comments