1. 程式人生 > >springboot + activiti + modeler

springboot + activiti + modeler

 公司要使用activiti做流程管理中心,之前知道有這個框架,但是一直沒有機會去接觸學習,公司採用了springboot框架,(我就不介紹這個框架的使用了,簡單來說就是spring去掉配置檔案,就是springboot,哈哈,我是這樣認為的,比較容易上手)廢話不多說,下面開始框架的整合;
 **第一步:搭建springboot框架**
 無論是idea 還是eclipse,都有外掛生成springboot框架,但是個人認為,還是自己搭建比較好,可以瞭解框架由哪幾部分組成,我是用的idea,我就不適用idea一鍵生成springboot框架了,自己搭建比較好。
 (1)建立一個maven web專案

這裡寫圖片描述

 <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.3.RELEASE</version>
  </parent>

  <dependencies>

    <dependency>
      <groupId>org.springframework.boot</groupId
>
<artifactId>spring-boot-starter</artifactId> <version>1.5.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version
>
1.5.4.RELEASE</version> </dependency> </dependencies>

新增類 ServletInitializer.java,新增application.properties or application.ylm你喜歡哪一種配置方式都可以如圖所示檔案目錄:
這裡寫圖片描述
ServletInitializer.java

@ComponentScan
@ServletComponentScan
@EnableTransactionManagement
@MapperScan(basePackages = "com.river.dao") //整合mybatis 掃描路徑
@EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class})
//這玩意後面會解釋
public class ServletInitializer extends SpringBootServletInitializer{


    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(ServletInitializer.class);
    }


    public static void main(String[] args) {
        SpringApplication.run(ServletInitializer.class,args);
    }
}

到這裡springboot框架就搭建好了,需要依賴自己往pom.xml裡新增。我的pom.xml如下

<properties>
    <activiti.version>5.22.0</activiti.version>
  </properties>

  <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.3.RELEASE</version>
</parent>

  <dependencies>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>1.5.4.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>1.5.4.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
      <version>1.5.4.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>1.3.1</version>
    </dependency>

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.44</version>
    </dependency>

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.5</version>
    </dependency>


    <!--activiti-->
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring-boot-starter-basic</artifactId>
      <version>${activiti.version}</version>
    </dependency>
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring-boot-starter-actuator</artifactId>
      <version>${activiti.version}</version>
    </dependency>
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-rest</artifactId>
      <version>${activiti.version}</version>
    </dependency>

    <dependency>
      <groupId>org.apache.xmlgraphics</groupId>
      <artifactId>batik-codec</artifactId>
      <version>1.7</version>
    </dependency>
    <dependency>
      <groupId>org.apache.xmlgraphics</groupId>
      <artifactId>batik-css</artifactId>
      <version>1.7</version>
    </dependency>
    <dependency>
      <groupId>org.apache.xmlgraphics</groupId>
      <artifactId>batik-svg-dom</artifactId>
      <version>1.7</version>
    </dependency>
    <dependency>
      <groupId>org.apache.xmlgraphics</groupId>
      <artifactId>batik-svggen</artifactId>
      <version>1.7</version>
    </dependency>
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-explorer</artifactId>
      <version>${activiti.version}</version>
    </dependency>
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-diagram-rest</artifactId>
      <version>${activiti.version}</version>
    </dependency>
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-simple-workflow</artifactId>
      <version>${activiti.version}</version>
    </dependency>

    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring</artifactId>
      <version>${activiti.version}</version>
    </dependency>

    <!--<dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-modeler</artifactId>
      <version>${activiti.version}</version>
    </dependency>-->
  </dependencies>

application.properties

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot_activiti_service
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
mybatis.mapper-locations=classpath:com/river/dao/*.xml  #mybatis使用


logging.file=log.log
logging.pattern.level=debug

security.basic.enabled=false

(2)開始整合activiti+modeler
在網上有一些介紹,直接在pom.xml中直接新增

<dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring-boot-starter-basic</artifactId>
      <version>${activiti.version}</version>
    </dependency>
    <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring-boot-starter-actuator</artifactId>
      <version>${activiti.version}</version>
    </dependency>

這兩個依賴就可以,但事實是不可以的,我也不知道為啥,在springboot中,資料來源無法自動配置到ProcessEngineConfigurationConfigurer中,導致專案啟動時processEngine為null,搞了我大半天,然後自己寫配置自己掌控processEngine的DataSource
1、新增配置類ActivitiDataSourceProperties.java

@Component
public class ActivitiDataSourceProperties {

    @Value("${spring.datasource.url}")
    private String url;

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }
}

2、ActivitiDatadourceConfig.java

@Configuration
public class ActivitiDatadourceConfig extends AbstractProcessEngineAutoConfiguration {

    @Resource
    private ActivitiDataSourceProperties activitiDataSourceProperties;

    @Bean
    @Primary
    public DataSource activitiDataSource() {
        DruidDataSource DruiddataSource = new DruidDataSource();
        DruiddataSource.setUrl(activitiDataSourceProperties.getUrl());
        DruiddataSource.setDriverClassName(activitiDataSourceProperties.getDriverClassName());
        DruiddataSource.setPassword(activitiDataSourceProperties.getPassword());
        DruiddataSource.setUsername(activitiDataSourceProperties.getUsername());
        return DruiddataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(activitiDataSource());
    }

    @Bean
    public SpringProcessEngineConfiguration springProcessEngineConfiguration() {
        SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration();
        configuration.setDataSource(activitiDataSource());
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        configuration.setJobExecutorActivate(true);
        configuration.setTransactionManager(transactionManager());
        return configuration;
    }
}

(2)新增modeler相關檔案
這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

分配在這些資料夾中找到上面的modeler的檔案,放到相應的位置中
這裡寫圖片描述
修改一下這個檔案
雖然在pom.xml中有activiti-modeler這個依賴,但是集合springboot的時候不能使用,以為在傳引數的時候,@RequestBody @RequestBody MultiValueMap

@RestController
public class ModelSaveRestResource implements ModelDataJsonConstants {

    protected static final Logger LOGGER = LoggerFactory.getLogger(ModelSaveRestResource.class);

    @Autowired
    private RepositoryService repositoryService;


    @RequestMapping(value = "/model/{modelId}/save", method = RequestMethod.PUT)
    public void saveModel(@PathVariable String modelId, @RequestParam String json_xml,
                          @RequestParam  String svg_xml,@RequestParam String name, @RequestParam String description) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            Model model = repositoryService.getModel(modelId);

            ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());

            modelJson.put(MODEL_NAME, name);
            modelJson.put(MODEL_DESCRIPTION, description);
            model.setMetaInfo(modelJson.toString());
            model.setName(name);

            repositoryService.saveModel(model);

            repositoryService.addModelEditorSource(model.getId(), json_xml.getBytes("utf-8"));

            InputStream svgStream = new ByteArrayInputStream(svg_xml.getBytes("utf-8"));
            TranscoderInput input = new TranscoderInput(svgStream);

            PNGTranscoder transcoder = new PNGTranscoder();
            // Setup output
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            TranscoderOutput output = new TranscoderOutput(outStream);

            // Do the transformation
            transcoder.transcode(input, output);
            final byte[] result = outStream.toByteArray();
            repositoryService.addModelEditorSourceExtra(model.getId(), result);
            outStream.close();

            //部署流程
            Model modelData = repositoryService.getModel(modelId);
            ObjectNode modelNode = (ObjectNode) objectMapper.readTree(repositoryService.getModelEditorSource(modelData.getId()));
            byte[] bpmnBytes = null;
            BpmnModel model2 = new BpmnJsonConverter().convertToBpmnModel(modelNode);
            bpmnBytes = new BpmnXMLConverter().convertToXML(model2);

            String processName = modelData.getName() + ".bpmn";

            //部署流程
            Deployment deployment = repositoryService.createDeployment()
                    .name(modelData.getName())
                    .addString(processName, StringUtils.toEncodedString(bpmnBytes, Charset.forName("UTF-8")))
                    .deploy();


        } catch (Exception e) {
            LOGGER.error("Error saving model", e);
            throw new ActivitiException("Error saving model", e);
        }

    }
}

建立空mode即跳轉到modeler編輯頁面的程式碼如下

@Controller
@RequestMapping("/modeler")
public class ModelerController {

    private static final Logger logger = LoggerFactory.getLogger(ModelerController.class);

    @Resource
    private ModelerService modelerService;

    /**
     * 建立流程模型
     * @param name
     * @param key
     * @param description
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public String createModel(@RequestParam("name") String name, @RequestParam("key") String key,
                            @RequestParam("description") String description,
                            HttpServletRequest request, HttpServletResponse response) {
        logger.info("建立空modeler:name:{},key:{},description:{}", name, key, description);
        try {
            //建立空模型
            String modelId = modelerService.crateModel(name, key, description);
            if(StringUtils.isBlank(modelId)) {
                throw new RuntimeException("建立modeler失敗modelId:" + modelId);
            }

            return "redirect:../modeler.html?modelId=" + modelId;
        }catch (Exception e) {
            logger.error("建立模型失敗",e );
            throw new RuntimeException(e);
        }
    }

    /**
     * 模型列表
     * @param modelAndView
     * @return
     */
    @RequestMapping("/model/list")
    public ModelAndView modelList(ModelAndView modelAndView) {
        List<Model> list = modelerService.queryModelList();
        return modelAndView;
    }