activiti 动态表单+easyui 实现启动流程功能(二)

15 篇文章 0 订阅
13 篇文章 0 订阅

上一篇讲了动态表单实现的基本原理,这一篇主要写一下实现的关键源码。

首先是流程定义的controller,这个类接收用户启动流程的请求,有一个流程定义id的参数。

@Controller
@RequestMapping(value = "/backstage/workflow/hi/")
public class ProcDefController extends BaseController<Object>{
	
	@Autowired
	private ProcDefService procDefService;
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private FormService formService;
	@Autowired
	private IdentityService identityService;
	@Autowired
	private ProcInstService procInstService;
	/**
     * 发起流程页面
     */
    @RequestMapping(value = "index")
    public String index(Model model) {
    	List<ProcDef> procDefList = procDefService.getProcDefList();
    	model.addAttribute("procDefList", procDefList);
		return "/system/workflow/hi/procDefList";
    }
   
    /**
     * 发起指定流程表单页面
     */
    @RequestMapping(value = "getStartPage")
    public String getStartPage(Model model,String procDefId,RedirectAttributes attr)  {
    	ProcDef pd = procDefService.getProcDefById(procDefId);
    	String key = pd.getKey();
    	if(key.indexOf("c_") == 0){//普通表单
    		return getStartPageForCommon(model,pd,attr);
    	}else if(key.indexOf("ex_") == 0){//外置表单
    		return getStartPageForEX(model,pd,attr);
    	}else{//动态表单
    		return getStartPageForDynamics(model,pd,attr);
    	}
    }
    
    /**
     * 获取 动态表单 流程启动页面
     */
    public String getStartPageForDynamics(Model model,ProcDef pd,RedirectAttributes attr){
    	List<FormAttr> formAttrlist = procDefService.getFormAttrList(pd);
    	model.addAttribute("deploymentId", pd.getDeploymentId());
    	model.addAttribute("pd", pd);
		model.addAttribute("formAttrlist", formAttrlist);
		return "/system/workflow/hi/start";
    }
}

ProcDef pd = procDefService.getProcDefById(procDefId);
这个是根据流程定义id,获取对应的实体。我使用的mybatis,这里只写一下对应的xml定义:

ProcDefMapper.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pl.repository.workflow.hi.ProcDefDao">
	<resultMap id="procDef" type="ProcDef">
    	<id column="id" jdbcType="VARCHAR" property="id"/>
    	<result column= "name" property="name" />
    	<result column= "key" property="key" />
    	<result column= "version" property="version" />
    	<result column= "category" property="category" />
    	<result column= "deploymentId" property="deploymentId" />
    	<result column= "resourceName" property="resourceName" />
    	<result column= "dgrmResourceName" property="dgrmResourceName" />
    	<result column= "description" property="description" />
    	<association property="byteArray"  resultMap="com.pl.repository.workflow.hi.ByteArrayDao.byteArray" columnPrefix="ba_"/>
    </resultMap>
     <!-- 通过id获取对象 -->
    <select id="getEntityById" resultMap="procDef" parameterType="String">
    	select pd.id_ as id ,pd.name_  as name ,pd.key_ as key ,pd.version_ as version ,pd.category_ as category,pd.deployment_id_ as deploymentId,
    		pd.resource_name_ as resourceName ,pd.dgrm_resource_name_ as dgrmResourceName ,pd.description_ as description 
    		,ba.id_ as ba_id ,ba.rev_ as ba_rev ,ba.name_ as ba_name ,ba.deployment_id_ as ba_deploymentId ,ba.bytes_ as ba_bytes 
    	from ACT_RE_PROCDEF pd
		left join ACT_GE_BYTEARRAY ba on pd.deployment_id_=ba.deployment_id_ and pd.resource_name_=ba.name_
		where pd.id_ = #{id}
    </select> 
</mapper>


ByteArrayMapper.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pl.repository.workflow.hi.ByteArrayDao">
	<resultMap id="byteArray" type="ByteArray">
    	<id column="id" jdbcType="VARCHAR" property="id"/>
    	<result column= "rev" property="rev" />
    	<result column= "name" property="name" />
    	<result column= "deploymentId" property="deploymentId" />
    	<result column= "bytes" property="bytes" />
    </resultMap>
</mapper>

ACT_RE_PROCDEF表与 ACT_GE_BYTEARRAY表关联,流程定义id,可以获取流程定义对应的xml文件,即ACT_GE_BYTEARRAY的 bytes_字段。

我这里用key的命名规则区分了下表单类型,c_前缀开始表示普通表单,ex_开始表示外置表单,其他的都是动态表单。

List<FormAttr> formAttrlist = procDefService.getFormAttrList(pd);
这个方法对应 前一篇文章中原理所讲的4.1和4.2步骤。即或者xml并解析。

ProcDefService.java

@Service("procDefService")
public class ProcDefService extends BaseServiceImp<ProcDef> {

	@Autowired
	private ProcDefDao procDefDao;
		
	public List<FormAttr> getFormAttrList(ProcDef pd) {
		ByteArray ba = pd.getByteArray();
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();  
		outStream.write(ba.getBytes(), 0, ba.getBytes().length);  
		String xml = null;
		try {
			xml = new String(ba.getBytes(), "utf-8");//读取数据库中xml文件,二进制格式转换为字符串格式
		} catch (UnsupportedEncodingException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		}
		Node root = XMLTools.Dom2Map(xml);//使用dom4j解析xml文件
		List<FormAttr> formMap = new ArrayList<FormAttr>();
		Node processNode = root.getSubNodeByName("process");
		Node startEventNode = processNode.getSubNodeByName("startEvent");
		Node extensionElements = startEventNode.getSubNodeByName("extensionElements");
		if(extensionElements == null){
			return formMap;
		}
		List<Node> formPropertyList = extensionElements.getChildrenList();
		for (Node formProperty : formPropertyList) {
			FormAttr fa = new FormAttr(formProperty);
			formMap.add(fa);
		}
		return formMap;
	}
}


XMLTools.java
/***
 * JSON、XML、MAP的互转
 * @author pelin
 */
public class XMLTools {
     
	/***
	 * 将dom4j的Element格式化为自己定义的结点Node格式
	 * @param Node
	 * @return
	 */
	public static Node getNodes(Element ele){  
		Node node = new Node();
		Map<String, String> attrMap = new HashMap<String, String>();
		List<Node> childrenList = new ArrayList<Node>();
		node.setName(ele.getName());//当前节点名称  
		node.setText(ele.getTextTrim());//当前节点文本内容
		node.setAttrMap(attrMap);//当前节点所有属性的list  
		node.setChildrenList(childrenList);//当前节点所有子节点  
		
		List<Attribute> listAttr = ele.attributes();//当前节点的所有属性的list  
	    for(Attribute attr:listAttr){//遍历当前节点的所有属性  
	    	attrMap.put(attr.getName(), attr.getValue());
	    }  
	    //递归遍历当前节点所有的子节点  
	    List<Element> listElement = ele.elements();//所有一级子节点的list  
	    for(Element e:listElement){//遍历所有一级子节点  
	    	Node mapChildren = getNodes(e);//递归  
	    	childrenList.add(mapChildren);
	    }  
	    return node;
	}  
	public static Node Dom2Map(String xml){  
		Document doc = null;
		Element root= null;
		try {
			doc = DocumentHelper.parseText(xml);
			root = doc.getRootElement();//获取根节点  
		} catch (DocumentException e) {
			e.printStackTrace();
		}
        return getNodes(root);  
    }  
}


Node.java
public class Node {
	String name;
	String text;
	Map<String, String> attrMap;
	List<Node> childrenList;
}

/***
 * 表单属性
 * @author Administrator
 */
public class FormAttr {
	String id;
	String name;
	String type;
	boolean required;//默认是fasle
	boolean readable;//默认是true
	boolean writable;//默认是true
	List<Node> selects;
	public FormAttr(){}
	public FormAttr(Node formProperty){
		Map<String,String> attrMap = formProperty.getAttrMap();
		id = attrMap.get("id");
		name = attrMap.get("name");
		type = attrMap.get("type");
		//attrMap没找到,即结果为null说明是默认值
		required = "true".equals(attrMap.get("required")) ? true : false;
		readable = "false".equals(attrMap.get("readable")) ? false : true;
		writable = "false".equals(attrMap.get("writable")) ? false : true;
		if("enum".equals(type)){
			selects = formProperty.getChildrenList();
		}
	}
	public String toRequiredStr(){
		return required ? " required='true' " : "";
	}
	public String toReadableStr(){
		return readable ? "" : " display:none; ";
	}
	public String toWritableStr(){
		return writable ? " name='"+id+"' " : " readonly='readonly' ";
	}
}

通过上面的处理,可以获取到流程定义时开始结点的表单属性列表了。接下来只剩下最后一步4.3.  即  根据表单属性列表生成相应的html代码。

具体实现源码,见下一篇。





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值