锁定老帖子 主题:jBPM工作流应用
精华帖 (0) :: 良好帖 (0) :: 新手帖 (3) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-03-15
基础环境是eclipse3+myeclipse6+mysql5+tomcat6 。 首先从网站上下载jBPM开发包(jbpm-jpdl-suite-3.2.3.zip),据说现在jBPM3已经升到3.2.6了,而且据说已经推出了jBPM4了。将jbpm-jpdl-suite-3.2.3.zip解压缩后,里面有个\designer文件夹,这个是eclipse IDE的jBPM插件,是可视化的那种。 安装这个插件: 1、 HelpSoftware Updates 2、 Find and Install Search for new features to install 3、 点击 New Local Site,选择jBPM开发包解压缩后的那个插件的地址,例如D:\jbpm-jpdl-3.2.3\designer 4、 一路点击Next就可以了,安装完成后,eclipse需要重启。重启后,可以在project中到到一个JBoss jBPM的项目。如图所示。 二、 设置一个User Library 很多人不习惯Process Project的那种代码结构,而我也不习惯。Process Project 的结构如图所示。 于是想给它设置一个自己的库,可以随时在各种WEB应用中调用。设置User Library的步骤如下: 1、 eclipse中,点击WindowPreferences 2、 JavaUser Library 3、 点击New,设置User Library name 为jBPM Library。点击OK。 4、 点击Add JARs,首先来到jBPM解压缩后的路径(例如:D:\jbpm-jpdl-3.2.3),有两个JAR,其中jbpm-jpdl.jar是一定要加的。 5、 还有其他的JARs要加,重复步骤4,进入lib包(例如:D:\jbpm-jpdl-3.2.3\lib),选中所有的JARs。 6、 这样,我们的jBPM Library就设置好了。如图所示: 三、 一个结合Struts 1.x的应用 首先,假定一个流程。这个流程是常用的报销流程,只考虑了最简单的流程。 角色有三种:普通员工(employee)、经理(manager)、BOSS(boss)。这里因为只是做个示例,没有考虑过多的权限方面的设置。这里设计了三个用户,分别对应了三种角色,并且员工有上级(经理)无下属、经理有上级(BOSS)有下属(员工)、BOSS无上级有下属(经理)。具体参看数据库设计。 好了,数据设计好了,开始搭建系统吧。步骤如下: 1、 FileNewWeb Project 2、 给新添加的web项目添加Struts 1.x类库。 3、 添加新的User Library,将刚才设置好的jBPM Library添加进来。 4、 在项目下新增一个Source Folder,命名为jbpm。 搭建好的结构如下图所示: 项目的流程定义文件和jBPM插件生成的图片在com.flowdemo.jbpm.expense包下。hibernate.cfg.xml配置文件需要做一些修改,原本配置的数据库连接是hsqldb。现在把它改成为连接MySQL。具体的配置信息查看代码清单。 Com.flowdemo.service包中包含有两个业务逻辑类,一个是关于对象持久化的:PersistenceService.java 一个是工作流的:FlowService.java 。 以下是PersistenceService.java源代码,主要是对持久化对象的一些操作。 package com.flowdemo.service; import java.util.ArrayList; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import com.flowdemo.po.Expenses; import com.flowdemo.po.Users; import com.flowdemo.util.HibernateSessionFactory; public class PersistenceService { /** * 保存一个报销单对象 * @param expense */ public static void save(Expenses expense){ Session hibernateSession = HibernateSessionFactory.getSession(); try{ //hibernateSession.getTransaction().begin(); hibernateSession.beginTransaction(); hibernateSession.saveOrUpdate(expense); hibernateSession.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); hibernateSession.getTransaction().rollback(); }finally{ HibernateSessionFactory.closeSession(); } } /** * 更新一个报销单对象 * @param expense */ public static void update(Expenses expense){ Session hibernateSession = HibernateSessionFactory.getSession(); try{ //hibernateSession.getTransaction().begin(); hibernateSession.beginTransaction(); //hibernateSession.saveOrUpdate(expense); hibernateSession.update(expense); hibernateSession.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); hibernateSession.getTransaction().rollback(); }finally{ HibernateSessionFactory.closeSession(); } } /** * 删除一个报销单对象 * @param expense */ public static void delete(Expenses expense){ Session hibernateSession = HibernateSessionFactory.getSession(); try{ //hibernateSession.getTransaction().begin(); hibernateSession.beginTransaction(); hibernateSession.delete(expense); hibernateSession.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); hibernateSession.getTransaction().rollback(); }finally{ HibernateSessionFactory.closeSession(); } } /** * 返回一个报销单列表 * @return */ public static List<Expenses> getExpenses(){ Session hibernateSession = HibernateSessionFactory.getSession(); List<Expenses> expenses = new ArrayList<Expenses>(); try{ //hibernateSession.getTransaction().begin(); hibernateSession.beginTransaction(); //hibernateSession.delete(expense); Query query = hibernateSession.createQuery("from Expenses"); expenses = query.list(); hibernateSession.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); hibernateSession.getTransaction().rollback(); }finally{ HibernateSessionFactory.closeSession(); } return expenses; } /** * 根据用户ID返回一个对象 * @param userId * @return */ public static Users getUserById(String userId){ Session hibernateSession = HibernateSessionFactory.getSession(); Users user = new Users(); try{ hibernateSession.beginTransaction(); user = (Users)hibernateSession.get(Users.class, userId); hibernateSession.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); hibernateSession.getTransaction().rollback(); }finally{ HibernateSessionFactory.closeSession(); } return user; } /** * 检查用户是否存在 * @param user * @return */ public static boolean checkUser(Users user){ Users user2 = null; try{ user2 = getUserById(user.getUserId()); System.out.println("用户的值==="+user2.getUserName()); }catch(Exception e){ e.printStackTrace(); }finally{ //HibernateSessionFactory.closeSession(); } if(user2.getUserPass() == user.getUserPass() || user2.getUserPass().equals(user.getUserPass())){ return true; }else{ return false; } } /** * 测试主方法 * @param args */ public static void main(String[]args){ Session hibernateSession = HibernateSessionFactory.getSession(); System.out.println("测试Session是否启动1"+hibernateSession.toString()); hibernateSession.close(); System.out.println("测试Session是否启动2"+hibernateSession.toString()); hibernateSession = HibernateSessionFactory.getSession(); System.out.println("测试Session是否启动1"+hibernateSession.toString()); HibernateSessionFactory.closeSession(); System.out.println("测试Session是否启动2"+hibernateSession.toString()); Users user = new Users(); user.setUserId("001"); user.setUserPass("employee"); boolean flag = checkUser(user); System.out.println("是否是正确的?"+flag); } } 以下是FlowService.java源代码: package com.flowdemo.service; import java.util.ArrayList; import java.util.List; import org.jbpm.JbpmConfiguration; import org.jbpm.JbpmContext; import org.jbpm.db.GraphSession; import org.jbpm.graph.def.ProcessDefinition; import org.jbpm.graph.exe.ProcessInstance; import org.jbpm.taskmgmt.exe.TaskInstance; import com.flowdemo.jbpm.util.PoTaskWrapper; import com.flowdemo.po.Expenses; import com.flowdemo.po.Users; import com.flowdemo.util.HibernateSessionFactory; public class FlowService { static JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance(); /** * 初始化流程 */ public static void initJbpm(){ JbpmContext jbpmContext = jbpmConfiguration.getCurrentJbpmContext(); if(jbpmContext == null || jbpmContext.equals("")){ jbpmContext = jbpmConfiguration.createJbpmContext(); } //如果流程定义没有,则重新部署 try{ ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("com/flowdemo/jbpm/expense/processdefinition.xml");; //测试是否存在 System.out.println("流程定义是否加载?==="+processDefinition.toString()); jbpmContext.deployProcessDefinition(processDefinition); GraphSession graphSession = jbpmContext.getGraphSession(); processDefinition = graphSession.findLatestProcessDefinition("expense"); }finally{ jbpmContext.close(); } } /** * 绑定报销单到流程中 */ public static void bindingExpenseToProcess(){ JbpmContext jbpmContext = jbpmConfiguration.getCurrentJbpmContext(); if(jbpmContext == null || jbpmContext.equals("")){ jbpmContext = jbpmConfiguration.createJbpmContext(); } try{ jbpmContext.setSessionFactory(HibernateSessionFactory.getSessionFactory()); ProcessDefinition processDefinition = jbpmContext.getGraphSession().findLatestProcessDefinition("expense"); ProcessInstance processInstance = new ProcessInstance(processDefinition); jbpmContext.save(processInstance); long processInstanceId = processInstance.getId(); //用什么来get or load这个Expenses对象呢? Expenses expense = (Expenses)jbpmContext.getSession().createQuery("from Expenses where processInstanceId = "+null).list().get(0); //Expenses expense = (Expenses)jbpmContext.getSession().get(Expenses.class, 3); expense.setProcessInstanceId(new Long(processInstanceId).toString()); jbpmContext.getSession().update(expense); processInstance.getContextInstance().setVariable("expense_id", expense.getExpenseId()); processInstance.signal(); }finally{ jbpmContext.close(); } } /** * 根据用户来返回自己需要处理的任务 * @param user * @return */ public static List getTasks(Users user){ JbpmContext jbpmContext = jbpmConfiguration.getCurrentJbpmContext(); if(jbpmContext == null || jbpmContext.equals("")){ jbpmContext = jbpmConfiguration.createJbpmContext(); } System.out.println("提供任务的人的名字"+user.getUserName()); List tasks = new ArrayList(); //List expenses = new ArrayList(); List poAndTasks = new ArrayList(); try{ tasks = jbpmContext.getTaskMgmtSession().findTaskInstances(user.getUserName()); System.out.println("需要处理的任务的多少"+tasks); TaskInstance taskInstance = null; Expenses expense = null; for(int i=0;i<tasks.size();i++){ taskInstance = (TaskInstance)tasks.get(i); Integer expenseId =(Integer)taskInstance.getProcessInstance().getContextInstance().getVariable("expense_id"); System.out.println("expenseId的值是多少呢?"+expenseId); PoTaskWrapper poTask = new PoTaskWrapper(); jbpmContext.setSessionFactory(HibernateSessionFactory.getSessionFactory()); expense = (Expenses)jbpmContext.getSession().load(Expenses.class, expenseId); System.out.println("对应的报销单的编号、金额和理由"+expense.getExpenseId()+" "+expense.getMoney()+" "+expense.getReason()); //expenses.add(expense); poTask.setExpense(expense); System.out.println("poTask获得的expense-->"+poTask.getExpense().getMoney()); poTask.setTaskInstanceId(taskInstance.getId()); poTask.setTokenId(taskInstance.getToken().getId()); poAndTasks.add(poTask); } }catch(Exception e){ e.printStackTrace(); }finally{ jbpmContext.close(); } //return expenses; System.out.println("队列的长度 -->"+poAndTasks.size()); return poAndTasks; } /** * @param processInstanceId * @return */ public static boolean managerApprove(String processInstanceId){ JbpmContext jbpmContext = jbpmConfiguration.getCurrentJbpmContext(); if(jbpmContext == null || jbpmContext.equals("")){ jbpmContext = jbpmConfiguration.createJbpmContext(); } try{ ProcessInstance processInstance = jbpmContext.getProcessInstance(new Long(processInstanceId).longValue()); //ProcessDefinition processDefinition = jbpmContext.getGraphSession().findLatestProcessDefinition("expense"); //ProcessInstance processInstance = new ProcessInstance(processDefinition); TaskInstance taskInstance = processInstance.getTaskMgmtInstance().createTaskInstance(); taskInstance.end(); processInstance.signal(); }catch(Exception e){ e.printStackTrace(); }finally{ jbpmContext.close(); } return false; } /** * 审核 * @param taskInstanceId */ public static void approve(long taskInstanceId){ JbpmContext jbpmContext = jbpmConfiguration.getCurrentJbpmContext(); if(jbpmContext == null || jbpmContext.equals("")){ jbpmContext = jbpmConfiguration.createJbpmContext(); } try{ TaskInstance taskInstance = jbpmContext.getTaskInstance(taskInstanceId); //taskInstance.end("manager_approve"); taskInstance.end(); //processInstance.signal(); }catch(Exception e){ e.printStackTrace(); }finally{ jbpmContext.close(); } } } 还有一点需要注意的是,在测试运行之前需要把jbpm的数据库表创建好,当然也可以通过JbpmContext jbpmContext = cfg.createJbpmContext();来创建,但是这是在每次运行时都会创建,所以还是直接通过导入jbpm的sql文件来创建的好。 好了,一个基于struts的jbpm应用差不多就完成了,我比较懒,所以也不太想在介绍代码上费功夫了,各位看官自己看咯,呵呵。 还想做一些集成spring的应用,但是由于公司也没用上这种技术,所以兴趣又降了一大半,⊙﹏⊙b汗。以后有机会再自己写写吧。以下附上源代码。有需要的请下载吧。按照习惯,我去掉了jar包,所有的需要的jar清单,请看图片: 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-03-16
为什么我部署好了 登陆的时候报空指针异常呢
|
|
返回顶楼 | |
发表时间:2009-03-16
%%%% Error Creating SessionFactory %%%%
org.hibernate.MappingNotFoundException: resource: org/jbpm/graph/action/MailAction.hbm.xml not found at org.hibernate.cfg.Configuration.addResource(Configuration.java:517) at org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:1511) at org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:1479) at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1458) at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:1432) at org.hibernate.cfg.Configuration.configure(Configuration.java:1352) at com.flowdemo.util.HibernateSessionFactory.<clinit>(HibernateSessionFactory.java:30) at com.flowdemo.service.PersistenceService.getUserById(PersistenceService.java:104) at com.flowdemo.service.PersistenceService.checkUser(PersistenceService.java:128) at com.flowdemo.struts.action.LoginAction.execute(LoginAction.java:35) at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431) at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236) at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196) at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414) at javax.servlet.http.HttpServlet.service(HttpServlet.java:690) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) at java.lang.Thread.run(Thread.java:619) 10:16:00,093 [http-8080-1] INFO Configuration : configuring from resource: /hibernate.cfg.xml 10:16:00,093 [http-8080-1] INFO Configuration : Configuration resource: /hibernate.cfg.xml 10:16:00,093 [http-8080-1] INFO Configuration : Reading mappings from resource: org/jbpm/db/hibernate.queries.hbm.xml |
|
返回顶楼 | |
发表时间:2009-03-16
jar包中没用的东西太多
对于这种内容的帖子 懂的人根本不会细看 不懂的人看了更是不懂 发出来基本没什么价值! |
|
返回顶楼 | |
发表时间:2009-03-16
hanshuixinhan 写道 为什么我部署好了 登陆的时候报空指针异常呢
请检查jbpm的数据库表和自定义的表是否建立,用户表是否初始化数据了 |
|
返回顶楼 | |
发表时间:2009-03-16
多谢楼主开启的话题。
在www.projectzero.org上看到这个审批差旅计划的例子,比较而言,jBPM花费的时间有些多了。 虽然说自卖自夸有些不妥,但能让程序员们的生活简单些也值得了。不妨一试 |
|
返回顶楼 | |
发表时间:2009-03-16
cocococoon 写道 多谢楼主开启的话题。 在www.projectzero.org上看到这个审批差旅计划的例子,比较而言,jBPM花费的时间有些多了。 虽然说自卖自夸有些不妥,但能让程序员们的生活简单些也值得了。不妨一试 呵呵,谢谢 我也是闲来无事,一怕自己荒废了java,二想锻炼下自己 我做的这个例子离真正的企业应用还差了十万八千里,这个我自己知道,感觉自己有标题党的嫌疑了 呵呵,谢谢捧场哈 |
|
返回顶楼 | |
发表时间:2009-04-20
关于ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("com/flowdemo/jbpm/expense/processdefinition.xml");这段代码有个问题。
我用junit进行测试时,执行到ProcessDefinition.parseXmlResource这个方法时,会抛出异常,找不到对应目录文件。 但是用如下方法就可以通过,先生成文件流,在读取就可以了,这是为什么。 FileInputStream f=new FileInputStream("hello/processdefinition.xml"); ProcessDefinition processDefinition = ProcessDefinition.parseXmlInputStream(f); |
|
返回顶楼 | |
发表时间:2009-04-20
Storm1988 写道 关于ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("com/flowdemo/jbpm/expense/processdefinition.xml");这段代码有个问题。
我用junit进行测试时,执行到ProcessDefinition.parseXmlResource这个方法时,会抛出异常,找不到对应目录文件。 但是用如下方法就可以通过,先生成文件流,在读取就可以了,这是为什么。 FileInputStream f=new FileInputStream("hello/processdefinition.xml"); ProcessDefinition processDefinition = ProcessDefinition.parseXmlInputStream(f); 首先,请确认下您是否是按照我的代码里的package那样设置的 其次,parseXmlInputStream是处理xml文件输入流的,当然可以读取输入流中的内容。parseXmlResource方法中包括了处理输入流的操作,所以直接将xml文件的路径传递给parseXmlResource是可以的。 对了,好像JUNIT好象不是运行时环境,所以又可能会出现异常!我猜是这个原因! 嗯,Storm1988同学的习惯非常好,下次做什么得先写测试用例。谢谢! |
|
返回顶楼 | |
发表时间:2009-04-22
我用你的代码运行后,出现如下错误,帮忙看看,谢谢!
16:32:40,234 [http-8080-Processor24] WARN RequestProcessor : Unhandled Exception thrown: class org.hibernate.exception.SQLGrammarException 16:32:40,250 [http-8080-Processor24] ERROR StandardWrapperValve : Servlet.service() for servlet action threw exception java.sql.SQLException: Unknown column 'node0_.PARENTLOCKMODE_' in 'field list' at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2926) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1571) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1666) at com.mysql.jdbc.Connection.execSQL(Connection.java:2978) at com.mysql.jdbc.Connection.execSQL(Connection.java:2902) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:933) at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1027) at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:186) at org.hibernate.loader.Loader.getResultSet(Loader.java:1787) at org.hibernate.loader.Loader.doQuery(Loader.java:674) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236) at org.hibernate.loader.Loader.loadEntity(Loader.java:1860) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3049) at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:399) at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:375) at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139) at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:98) at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878) at org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:836) at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:66) at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111) at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:150) at org.jbpm.graph.def.Node$$EnhancerByCGLIB$$f2f76a0e.execute(<generated>) at org.jbpm.graph.exe.ProcessInstance.fireStartEvent(ProcessInstance.java:189) at org.jbpm.graph.exe.ProcessInstance.<init>(ProcessInstance.java:147) at org.jbpm.graph.exe.ProcessInstance.<init>(ProcessInstance.java:96) at com.flowdemo.service.FlowService.bindingExpenseToProcess(FlowService.java:57) at com.flowdemo.struts.action.SubmitExpenseAction.execute(SubmitExpenseAction.java:48) at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:421) at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:226) at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1158) at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:397) at javax.servlet.http.HttpServlet.service(HttpServlet.java:627) at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875) at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665) at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528) at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689) at java.lang.Thread.run(Thread.java:595) |
|
返回顶楼 | |