Appfuse2.0.2(SSH)整合JBPM3.2.x事务处理

JBPM发展到现在,已经被越来越多的人应用,非常感谢Jboss的出色贡献。这篇文章主要讲Appfuse2.0.2(Spring2.5+Struts2.0+Hibernate3)如何与jbpm3.2.x共享事务。
1.下载jbpm3.2.6,新建一个干净的appfuse2.0.2(ssh)的工程,还有建表什么的这里就不多说了。
2.在工程中加入jbpm-identity.jar、jbpm-jpdl.jar和spring-modules-jbpm31.jar类包,也可以通过配置pox.xml的方式。
3.在数据库中新建一张表,例如news,使用appfuse的生成工具,生成dao\service\action等
4.在resources中增加jbpm.cfg.xml、jbpm.mail.templates.xml(不是必须)
5.增加jbpm的配置到hibernate文件中
<session-factory>
<!-- ############################################ -->
<!-- # mapping files with external dependencies # -->
<!-- ############################################ -->

<!-- Additional mappings defined per module go here -->
<mapping resource="hibernate.extra.hbm.xml" />
<mapping resource="hibernate.identity.hbm.xml" />
<!-- ###################### -->
<!-- # jbpm mapping files # -->
<!-- ###################### -->

<!-- hql queries -->
<mapping resource="org/jbpm/db/hibernate.queries.hbm.xml" />

<!-- hql queries used in simulation for querying historical data.
uncomment if you want to use the GetSimulationInputCommand
or you want to use the queries directly.
beware: the queries need the stddev function to be enabled in your dialect.
for more information, visit:
http://www.camunda.com/business_process_simulation_news/mysql_and_stddev.html -->
<!--
<mapping resource="org/jbpm/sim/bam/hibernate.queries.hbm.xml" />
-->

<!-- graph.action mapping files -->
<mapping resource="org/jbpm/graph/action/MailAction.hbm.xml"/>

<!-- graph.def mapping files -->
<mapping resource="org/jbpm/graph/def/ProcessDefinition.hbm.xml"/>
<mapping resource="org/jbpm/graph/def/Node.hbm.xml"/>
<mapping resource="org/jbpm/graph/def/Transition.hbm.xml"/>
<mapping resource="org/jbpm/graph/def/Event.hbm.xml"/>
<mapping resource="org/jbpm/graph/def/Action.hbm.xml"/>
<mapping resource="org/jbpm/graph/def/SuperState.hbm.xml"/>
<mapping resource="org/jbpm/graph/def/ExceptionHandler.hbm.xml"/>
<mapping resource="org/jbpm/instantiation/Delegation.hbm.xml"/>

<!-- ########################################### -->
<!-- # mapping file with external dependencies # -->
<!-- ########################################### -->
<!-- the following mapping file has a dependency on 'bsh-{version}.jar'.
uncomment this if bsh is not in your classpath.
the script element will not be available in process definition files.
note: this mapping must appear below org/jbpm/graph/def/Action.hbm.xml -->
<mapping resource="org/jbpm/graph/action/Script.hbm.xml"/>

<!-- graph.node mapping files -->
<mapping resource="org/jbpm/graph/node/StartState.hbm.xml"/>
<mapping resource="org/jbpm/graph/node/EndState.hbm.xml"/>
<mapping resource="org/jbpm/graph/node/ProcessState.hbm.xml"/>
<mapping resource="org/jbpm/graph/node/Decision.hbm.xml"/>
<mapping resource="org/jbpm/graph/node/Fork.hbm.xml"/>
<mapping resource="org/jbpm/graph/node/Join.hbm.xml"/>
<mapping resource="org/jbpm/graph/node/MailNode.hbm.xml"/>
<mapping resource="org/jbpm/graph/node/State.hbm.xml"/>
<mapping resource="org/jbpm/graph/node/TaskNode.hbm.xml"/>

<!-- context.def mapping files -->
<mapping resource="org/jbpm/context/def/ContextDefinition.hbm.xml"/>
<mapping resource="org/jbpm/context/def/VariableAccess.hbm.xml"/>

<!-- bytes mapping files -->
<mapping resource="org/jbpm/bytes/ByteArray.hbm.xml"/>

<!-- module.def mapping files -->
<mapping resource="org/jbpm/module/def/ModuleDefinition.hbm.xml"/>

<!-- file.def mapping files -->
<mapping resource="org/jbpm/file/def/FileDefinition.hbm.xml"/>

<!-- taskmgmt.def mapping files -->
<mapping resource="org/jbpm/taskmgmt/def/TaskMgmtDefinition.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/def/Swimlane.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/def/Task.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/def/TaskController.hbm.xml"/>

<!-- scheduler.def mapping files -->
<mapping resource="org/jbpm/scheduler/def/CreateTimerAction.hbm.xml"/>
<mapping resource="org/jbpm/scheduler/def/CancelTimerAction.hbm.xml"/>

<!-- graph.exe mapping files -->
<mapping resource="org/jbpm/graph/exe/Comment.hbm.xml"/>
<mapping resource="org/jbpm/graph/exe/ProcessInstance.hbm.xml"/>
<mapping resource="org/jbpm/graph/exe/Token.hbm.xml"/>
<mapping resource="org/jbpm/graph/exe/RuntimeAction.hbm.xml"/>

<!-- module.exe mapping files -->
<mapping resource="org/jbpm/module/exe/ModuleInstance.hbm.xml"/>

<!-- context.exe mapping files -->
<mapping resource="org/jbpm/context/exe/ContextInstance.hbm.xml"/>
<mapping resource="org/jbpm/context/exe/TokenVariableMap.hbm.xml"/>
<mapping resource="org/jbpm/context/exe/VariableInstance.hbm.xml"/>
<mapping resource="org/jbpm/context/exe/variableinstance/ByteArrayInstance.hbm.xml"/>
<mapping resource="org/jbpm/context/exe/variableinstance/DateInstance.hbm.xml"/>
<mapping resource="org/jbpm/context/exe/variableinstance/DoubleInstance.hbm.xml"/>
<mapping resource="org/jbpm/context/exe/variableinstance/HibernateLongInstance.hbm.xml"/>
<mapping resource="org/jbpm/context/exe/variableinstance/HibernateStringInstance.hbm.xml"/>
<mapping resource="org/jbpm/context/exe/variableinstance/LongInstance.hbm.xml"/>
<mapping resource="org/jbpm/context/exe/variableinstance/NullInstance.hbm.xml"/>
<mapping resource="org/jbpm/context/exe/variableinstance/StringInstance.hbm.xml"/>

<!-- job mapping files -->
<mapping resource="org/jbpm/job/Job.hbm.xml"/>
<mapping resource="org/jbpm/job/Timer.hbm.xml"/>
<mapping resource="org/jbpm/job/ExecuteNodeJob.hbm.xml"/>
<mapping resource="org/jbpm/job/ExecuteActionJob.hbm.xml"/>
<mapping resource="org/jbpm/job/CleanUpProcessJob.hbm.xml"/>

<!-- taskmgmt.exe mapping files -->
<mapping resource="org/jbpm/taskmgmt/exe/TaskMgmtInstance.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/exe/TaskInstance.hbm.xml" />
<mapping resource="org/jbpm/taskmgmt/exe/PooledActor.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/exe/SwimlaneInstance.hbm.xml"/>

<!-- logging mapping files -->
<mapping resource="org/jbpm/logging/log/ProcessLog.hbm.xml"/>
<mapping resource="org/jbpm/logging/log/MessageLog.hbm.xml"/>
<mapping resource="org/jbpm/logging/log/CompositeLog.hbm.xml"/>
<mapping resource="org/jbpm/graph/log/ActionLog.hbm.xml"/>
<mapping resource="org/jbpm/graph/log/NodeLog.hbm.xml"/>
<mapping resource="org/jbpm/graph/log/ProcessInstanceCreateLog.hbm.xml"/>
<mapping resource="org/jbpm/graph/log/ProcessInstanceEndLog.hbm.xml"/>
<mapping resource="org/jbpm/graph/log/ProcessStateLog.hbm.xml"/>
<mapping resource="org/jbpm/graph/log/SignalLog.hbm.xml"/>
<mapping resource="org/jbpm/graph/log/TokenCreateLog.hbm.xml"/>
<mapping resource="org/jbpm/graph/log/TokenEndLog.hbm.xml"/>
<mapping resource="org/jbpm/graph/log/TransitionLog.hbm.xml"/>
<mapping resource="org/jbpm/context/log/VariableLog.hbm.xml"/>
<mapping resource="org/jbpm/context/log/VariableCreateLog.hbm.xml"/>
<mapping resource="org/jbpm/context/log/VariableDeleteLog.hbm.xml"/>
<mapping resource="org/jbpm/context/log/VariableUpdateLog.hbm.xml"/>
<mapping resource="org/jbpm/context/log/variableinstance/ByteArrayUpdateLog.hbm.xml"/>
<mapping resource="org/jbpm/context/log/variableinstance/DateUpdateLog.hbm.xml"/>
<mapping resource="org/jbpm/context/log/variableinstance/DoubleUpdateLog.hbm.xml"/>
<mapping resource="org/jbpm/context/log/variableinstance/HibernateLongUpdateLog.hbm.xml"/>
<mapping resource="org/jbpm/context/log/variableinstance/HibernateStringUpdateLog.hbm.xml"/>
<mapping resource="org/jbpm/context/log/variableinstance/LongUpdateLog.hbm.xml"/>
<mapping resource="org/jbpm/context/log/variableinstance/StringUpdateLog.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/log/TaskLog.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/log/TaskCreateLog.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/log/TaskAssignLog.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/log/TaskEndLog.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/log/SwimlaneLog.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/log/SwimlaneCreateLog.hbm.xml"/>
<mapping resource="org/jbpm/taskmgmt/log/SwimlaneAssignLog.hbm.xml"/>

<!-- ################## -->
<!-- # cache settings # -->
<!-- ##################-->

<!-- strategy="nonstrict-read-write" can be used with HashtableCacheProvider -->

<class-cache class="org.jbpm.context.def.VariableAccess" usage="nonstrict-read-write" />

<collection-cache collection="org.jbpm.file.def.FileDefinition.processFiles" usage="nonstrict-read-write" />

<collection-cache collection="org.jbpm.graph.action.Script.variableAccesses" usage="nonstrict-read-write" />

<class-cache class="org.jbpm.graph.def.Action" usage="nonstrict-read-write" />

<class-cache class="org.jbpm.graph.def.Event" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.Event.actions" usage="nonstrict-read-write" />

<class-cache class="org.jbpm.graph.def.ExceptionHandler" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.ExceptionHandler.actions" usage="nonstrict-read-write" />

<class-cache class="org.jbpm.graph.def.Node" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.Node.events" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.Node.exceptionHandlers" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.Node.leavingTransitions" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.Node.arrivingTransitions" usage="nonstrict-read-write" />

<class-cache class="org.jbpm.graph.def.ProcessDefinition" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.ProcessDefinition.events" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.ProcessDefinition.exceptionHandlers" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.ProcessDefinition.nodes" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.ProcessDefinition.actions" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.ProcessDefinition.definitions" usage="nonstrict-read-write" />

<collection-cache collection="org.jbpm.graph.def.SuperState.nodes" usage="nonstrict-read-write" />

<class-cache class="org.jbpm.graph.def.Transition" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.Transition.events" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.graph.def.Transition.exceptionHandlers" usage="nonstrict-read-write" />

<collection-cache collection="org.jbpm.graph.node.Decision.decisionConditions" usage="nonstrict-read-write" />

<collection-cache collection="org.jbpm.graph.node.ProcessState.variableAccesses" usage="nonstrict-read-write" />

<collection-cache collection="org.jbpm.graph.node.TaskNode.tasks" usage="nonstrict-read-write" />

<class-cache class="org.jbpm.instantiation.Delegation" usage="nonstrict-read-write" />

<class-cache class="org.jbpm.module.def.ModuleDefinition" usage="nonstrict-read-write" />

<collection-cache collection="org.jbpm.taskmgmt.def.Swimlane.tasks" usage="nonstrict-read-write" />

<class-cache class="org.jbpm.taskmgmt.def.TaskController" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.taskmgmt.def.TaskController.variableAccesses" usage="nonstrict-read-write" />

<class-cache class="org.jbpm.taskmgmt.def.Task" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.taskmgmt.def.Task.events" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.taskmgmt.def.Task.exceptionHandlers" usage="nonstrict-read-write" />

<collection-cache collection="org.jbpm.taskmgmt.def.TaskMgmtDefinition.swimlanes" usage="nonstrict-read-write" />
<collection-cache collection="org.jbpm.taskmgmt.def.TaskMgmtDefinition.tasks" usage="nonstrict-read-write" /></session-factory>

6.配置applicationContext-dao.xml,增加jbpm与Spring的配置文件
<bean id="jbpmConfiguration" class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="configuration" value="classpath:jbpm.cfg.xml"/>
</bean>

<bean id="jbpmTemplate" class="org.springmodules.workflow.jbpm31.JbpmTemplate">
<constructor-arg index="0" ref="jbpmConfiguration"/>
</bean>

7.打开applicationContext-service.xml,更改news的Spring配置,改为
<bean id="newsManager" class="com.infohold.app.service.impl.NewsManagerImpl">
<constructor-arg ref="newsDao"/>
<!--增加spring与jbpm的衔接Configuration-->
<property name="config" ref="jbpmConfiguration"/>
</bean>


8.我的NewsAction.java内容
package com.infohold.app.webapp.action;

import com.opensymphony.xwork2.Preparable;
import com.infohold.app.service.NewsManager;
import com.infohold.app.model.AppUser;
import com.infohold.app.model.News;
import com.infohold.app.webapp.action.BaseAction;

import java.util.List;
import java.util.Map;

import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContext;

public class NewsAction extends BaseAction implements Preparable {
private NewsManager newsManager;
private List newss;
private List tasks;
private List hisTasks;
private News news;
private Long id;

public void setNewsManager(NewsManager newsManager) {
this.newsManager = newsManager;
}

public List getNewss() {
return newss;
}

public List getTasks() {
return tasks;
}

public void setTasks(List tasks) {
this.tasks = tasks;
}

public List getHisTasks() {
return hisTasks;
}

public void setHisTasks(List hisTasks) {
this.hisTasks = hisTasks;
}

public void setId(Long id) {
this. id = id;
}

public News getNews() {
return news;
}

public void setNews(News news) {
this.news = news;
}
/**
* Grab the entity from the database before populating with request parameters
*/
public void prepare() {
if (getRequest().getMethod().equalsIgnoreCase("post")) {
// prevent failures on new
String newsId = getRequest().getParameter("news.id");
if (newsId != null && !newsId.equals("")) {
news = newsManager.get(new Long(newsId));
}
}
}

public String list() {
newss = newsManager.getAll();
return SUCCESS;
}

public String flowTaskList(){
AppUser u=userManager.getUserByUsername(this.getRequest().getRemoteUser());
hisTasks = newsManager.hisTaskList(u.getId().toString());
tasks = newsManager.taskList(u.getId().toString());
// newss = newsManager.taskList(u.getId().toString());
return SUCCESS;
}



public String delete() {
newsManager.remove(news.getId());
saveMessage(getText("news.deleted"));

return SUCCESS;
}

public String edit() {
if (id != null) {
news = newsManager.get(id);
} else {
news = new News();
}

return SUCCESS;
}

public String editAndFlow() {
if (id != null) {
news = newsManager.getNews(id);
} else {
news = new News();
}
return SUCCESS;
}

public String save() throws Exception {
if (cancel != null) {
return "cancel";
}
if (delete != null) {
return delete();
}
boolean isNew = (news.getId() == null);
newsManager.saveFlow(news);
String key = (isNew) ? "news.added" : "news.updated";
saveMessage(getText(key));
if (!isNew) {
return INPUT;
} else {
return SUCCESS;
}
}

}

NewsManagerImpl.java
package com.infohold.app.service.impl;

import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import com.infohold.app.dao.NewsDao;
import com.infohold.app.model.FlowTask;
import com.infohold.app.model.News;
import com.infohold.app.service.NewsManager;
import com.infohold.app.service.impl.GenericManagerImpl;

import javax.jws.WebService;

import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
import org.jbpm.taskmgmt.exe.TaskInstance;

//不知如何实现,待研究 @WebService(serviceName = "NewsService", endpointInterface = "com.infohold.app.service.NewsManager")
public class NewsManagerImpl extends GenericManagerImpl<News, Long> implements NewsManager {
NewsDao newsDao;
private JbpmConfiguration config;
private JbpmContext ctx;

public NewsManagerImpl(NewsDao newsDao) {
super(newsDao);
this.newsDao = newsDao;
}
public JbpmConfiguration getConfig() {
return config;
}
public void setConfig(JbpmConfiguration config) {
this.config = config;
}
public News getNews(Long taskId) {
ctx = config.createJbpmContext();
TaskInstance ti=ctx.getTaskInstance(taskId);
String newsId = (String) ti.getVariable("firstId");
News news = newsDao.get(Long.parseLong(newsId));
return news; //To change body of implemented methods use File | Settings | File Templates.
}
public News saveFlow(News object) {
ctx = config.createJbpmContext();
News news = newsDao.save(object);
ProcessDefinition pd=ctx.getGraphSession().findLatestProcessDefinition("first");
ProcessInstance pi=pd.createProcessInstance();
TaskInstance ti=pi.getTaskMgmtInstance().createStartTaskInstance();
//tzh:创建任务实例后会马上执行流程中的<tast>中的代码.如<task>中的<assignment>.
//也就是说创建任务实例后会把<start-state name="start">中的<task name="填写报销单">任务给执行了.
ti.setActorId("-2");
ti.setDescription(news.getFileName());
ti.setVariable("firstId", news.getId().toString());
ti.end();
//Token token = pi.getRootToken();
//ctx.close();

return news;
}

@SuppressWarnings("unchecked")
public List<FlowTask> taskList(String userId) {
ctx = config.createJbpmContext();
List temp=ctx.getTaskList(userId);
//tzh:本方法只从JBPM_TASKINSTANCE表中查找"actorid_"为"userid"的任务实例.
List gxlist=ctx.getTaskMgmtSession().findPooledTaskInstances(userId);
//tzh:本方法只从JBPM_TASKINSTANCE表中查找"isopen_"等于用户类型的值,且"actorid_"为"null"的任务实例.

temp.addAll(gxlist);
Vector userlist=new Vector();
for (Iterator iter = temp.iterator(); iter.hasNext();) {
TaskInstance el = (TaskInstance) iter.next();
FlowTask form=new FlowTask();
form.setActorId(el.getActorId());
form.setDescription(el.getDescription());
form.setTaskid(String.valueOf(el.getId()));
form.setTaskname(el.getName());
form.setDate(el.getCreate().toString());
form.setTokenid(String.valueOf(el.getToken().getId()));
userlist.add(form);
}
return userlist;
}

@SuppressWarnings("unchecked")
public List<FlowTask> hisTaskList(String userId) {
ctx = config.createJbpmContext();
List temp=newsDao.findAllHisTaskInstanceByUserId(userId);

Vector userlist=new Vector();
for (Iterator iter = temp.iterator(); iter.hasNext();) {
TaskInstance el = (TaskInstance) iter.next();
FlowTask form=new FlowTask();
form.setActorId(el.getActorId());
form.setDescription(el.getDescription());
form.setTaskid(String.valueOf(el.getId()));
form.setTaskname(el.getName());
form.setDate(el.getCreate().toString());
form.setTokenid(String.valueOf(el.getToken().getId()));
userlist.add(form);
}
return userlist;
}
}

NewsDaoHibernate.java
package com.infohold.app.dao.hibernate;

import java.util.List;

import org.jbpm.taskmgmt.exe.TaskInstance;

import com.infohold.app.model.FlowTask;
import com.infohold.app.model.News;
import com.infohold.app.dao.NewsDao;
import com.infohold.app.dao.hibernate.GenericDaoHibernate;

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

import org.hibernate.Query;

public class NewsDaoHibernate extends GenericDaoHibernate<News, Long> implements NewsDao {

public NewsDaoHibernate() {
super(News.class);
}

//un FlowTask
@SuppressWarnings("unchecked")
public List findAllHisTaskInstanceByUserId(String userid) {
//TaskInstance必须用全路径才能找到类
String hql="from org.jbpm.taskmgmt.exe.TaskInstance ti where ti.isOpen=false and ti.actorId ="+userid;
List<TaskInstance> list=this.getHibernateTemplate().find(hql);
return list;
}
}

taskList.jsp
<%@ include file="/common/taglibs.jsp"%>

<head>
<title><fmt:message key="newsList.title"/></title>
<meta name="heading" content="<fmt:message key='newsList.heading'/>"/>
<meta name="menu" content="NewsMenu"/>
</head>

<c:set var="buttons">
<input type="button" style="margin-right: 5px" class="button"
onclick="location.href='<c:url value="/editNews.html"/>'"
value="<fmt:message key="button.add"/>"/>

<input type="button" class="button" onclick="location.href='<c:url value="/mainMenu.html"/>'"
value="<fmt:message key="button.done"/>"/>
</c:set>

<c:out value="${buttons}" escapeXml="false" />

<display:table name="tasks" class="table" requestURI="" id="taskList" export="true" pagesize="25">
<display:column property="taskid" sortable="true" href="editNewsAndFlow.html" media="html"
paramId="id" paramProperty="taskid" titleKey="task.taskid"/>
<display:column property="taskid" media="csv excel xml pdf" titleKey="task.taskid"/>
<display:column property="taskname" sortable="true" titleKey="task.taskname"/>
<display:column property="description" sortable="true" titleKey="task.description"/>
<display:column property="actorId" sortable="true" titleKey="task.actorId"/>
<display:column property="date" sortable="true" titleKey="task.date"/>
<display:column property="tokenid" sortable="true" titleKey="task.tokenid"/>
</display:table>

<display:table name="hisTasks" class="table" requestURI="" id="hisTaskList" export="true" pagesize="25">
<display:column property="taskid" sortable="true" href="editNews.html" media="html"
paramId="taskid" paramProperty="taskid" titleKey="task.taskid"/>
<display:column property="taskid" media="csv excel xml pdf" titleKey="task.taskid"/>
<display:column property="taskname" sortable="true" titleKey="task.taskname"/>
<display:column property="description" sortable="true" titleKey="task.description"/>
<display:column property="actorId" sortable="true" titleKey="task.actorId"/>
<display:column property="date" sortable="true" titleKey="task.date"/>
<display:column property="tokenid" sortable="true" titleKey="task.tokenid"/>
</display:table>

<c:out value="${buttons}" escapeXml="false" />

<script type="text/javascript">
highlightTableRows("taskList");
</script>

至此,实现简单集成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值