springboot使用flowable(1)

22 篇文章 3 订阅
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.dmg</groupId>
    <artifactId>flow02</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>flow02</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
        <flowable.version>6.7.2</flowable.version>
    </properties>

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


            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>2.0.7</version>
            </dependency>

            <!-- 添加MyBatisPlus的依赖 -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.5.1</version>
            </dependency>
            <!-- MySQL数据 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.16</version>
            </dependency>
            <!-- druid  连接池-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.14</version>
            </dependency>
            <!-- MyBatisPlus 代码生成器 -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-generator</artifactId>
                <version>3.5.2</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <optional>true</optional>
            </dependency>
            <!-- JSR 303 的依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-validation</artifactId>
            </dependency>
            <dependency>
                <groupId>org.flowable</groupId>
                <artifactId>flowable-spring-boot-starter</artifactId>
                <version>${flowable.version}</version>
            </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.7.RELEASE</version>
                <configuration>
                    <mainClass>com.dmg.Flow02Application</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

application.properties

# 应用名称
spring.application.name=flow02
# 应用服务 WEB 访问端口
server.port=8080


spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
#&nullCatalogMeansCurrent=true 一定要有 否则报错
spring.datasource.url=jdbc:mysql://localhost:3306/flowable?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource


mybatis-plus.mapper-locations=classpath:mapper/*.xml
# 控制台打印sql语句
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

# Flowable相关的日志打印
logging.level.org.flowable.engine.impl.persistence.entity.*=debug
logging.level.org.flowable.task.service.impl.persistence.entity.*=debug

# Flowable的配置
#关闭定时任务JOB 定时事件使用
flowable.async-executor-activate=true
#当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本
flowable.database-schema-update=true

创建工作流工厂类,管理所有工作流服务

package com.dmg.service;

import org.flowable.engine.*;
import org.flowable.task.service.HistoricTaskService;
import org.flowable.variable.service.HistoricVariableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 工作流服务的工厂类 被其他类 所继承
 * 这里使用受保护的 就是可以被所继承的类使用
 */
@Component
public class FlowServiceFactory {


    @Autowired
    protected IdentityService identityService;

    @Autowired
    protected ManagementService managementService;

    @Autowired
    protected TaskService taskService;

    @Autowired
    protected ProcessEngine processEngine;

    @Autowired
    protected RuntimeService runtimeService;

    @Autowired
    protected RepositoryService repositoryService;

    @Autowired
    protected HistoryService historyService;

}

创建返回全局json实体

package com.dmg.common;

/**
 * 返回全局json实体
 * @param <T>
 */
public class Result<T> {
    /**
     * 错误码,表示一种错误类型
     * 请求成功,状态码为200
     */
    private int code;

    /**
     * 对错误代码的详细解释
     */
    private String message;

    /**
     * 返回的结果包装在value中,value可以是单个对象
     */
    private T data;

    public Result() {
    }

    public Result(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }


    public static Result success(Object object) {
        Result apiResult = new Result();
        apiResult.setData(object);
        apiResult.setCode(200);
        apiResult.setMessage("请求成功");
        return apiResult;
    }

    public static Result success() {
        return success(null);
    }

    public static <T> Result buildResult(Integer code, String message, T data) {
        Result result = new Result();
        result.setCode(code);
        result.setMessage(message);
        result.setData(data);
        return result;
    }

}

创建FlowService

package com.dmg.service;


import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;


public interface FlowService {

    public void deploy(String name, MultipartFile file) throws IOException;

}
package com.dmg.config;

import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.context.annotation.Configuration;

/**
 * 防止流程图中文乱码
 */
@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
    @Override
    public void configure(SpringProcessEngineConfiguration conn) {
        //设置活动字体名称
        conn.setActivityFontName("宋体");
        //设置标签字体名称
        conn.setLabelFontName("宋体");
        //设置注释字体名称
        conn.setAnnotationFontName("宋体");
    }
}

创建FlowServiceImpl

package com.dmg.service.impl;


/**
 * 流程定义服务实现类
 */
@Service
public class FlowServiceImpl extends FlowServiceFactory implements FlowService {


    /**
     * 部署
     */
    @Override
    public void deploy(String name, MultipartFile file) throws IOException {
        DeploymentBuilder deploymentBuilder=repositoryService.createDeployment();
        deploymentBuilder.name(name);
        String fileName=file.getOriginalFilename();
        if(fileName.endsWith(".bpmn20.xml") || fileName.endsWith(".bpmn")){
            deploymentBuilder.addInputStream(file.getOriginalFilename(),file.getInputStream());
        }else if(fileName.endsWith(".bar") || fileName.endsWith(".zip")){
            deploymentBuilder.addZipInputStream(new ZipInputStream(file.getInputStream()));
        }else {
            throw new RuntimeException("文件类型不是 .bpmn20.xml 或者 .bpmn 或者 .bar 或者.zip");
        }
        //部署成功后 act_re_deployment,act_re_procdef,act_ge_bytearray 表就有数据了
        deploymentBuilder.deploy();
    }


  
}

创建ProcessDefinitionController

package com.dmg.controller;



import java.io.IOException;

/**
 * 流程定义控制层
 */
@RestController
public class ProcessDefinitionController {

    @Autowired
    private FlowService flowService;


    /**
     * 部署流程  文件类型 .bpmn20.xml 或者 .bpmn 或者 .bar 或者.zip
     */
    @PostMapping("deploy")
    public Result deploy(@RequestParam("name") String name,@RequestParam("file") MultipartFile file){
        try {
            flowService.deploy(name,file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Result.success();
    }




}
package com.dmg;

@MapperScan("com.dmg.mapper")
@SpringBootApplication
public class Flow02Application {

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


}

先在数据库创建好数据库,然后在启动项目

我们先在flowable-ui创建好流程图,不会flowable-ui的,看我这篇链接

springboot集成flowable-ui最新版本_我是一只代码狗的博客-CSDN博客

key要唯一

这个是开始事件

这个是用户任务

这个是结束事件 就是流程走完了

这里是网关

 点击箭头就可以指向其他地方,放入到对方里面,就自动联线了

 下面就是我们的完整流程图了

 

 

 字符串的表达式一定要加单引号,例如${flag=='true'}

注意在流条件,表达式里面不能写其他的字符例如  通过${flag=='true'},要把通过去掉,否则

UelExpressionCondition这个类会抛出异常

点击保存

 

选择流程图

 点击下载

然后把文件拿到,上传,进行部署 

访问http://localhost:8080/deploy

 可以看到部署成功了,我们在看下数据库

先创建请假单表

CREATE TABLE `tb_qj` (
  `id` varchar(50) NOT NULL COMMENT '主键',
  `name` varchar(50) DEFAULT NULL COMMENT '申请单名称',
  `day` double DEFAULT NULL COMMENT '请假天数',
  `create_by` varchar(50) DEFAULT NULL COMMENT '创建人账号',
  `create_by_name` varchar(50) DEFAULT NULL COMMENT '创建人名称',
  `instance_id` varchar(50) DEFAULT NULL COMMENT '流程实例id',
  `approval_status` varchar(10) DEFAULT NULL COMMENT '审批状态 1:未提交 2:审批中 3:审批通过  ',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='请假表';

创建实体类 

package com.dmg.entity;

import java.util.Date;
import lombok.Data;

/**
    * 请假表
    */
@Data
@TableName("tb_qj")
public class Qj {
    /**
    * 主键
    */
    private String id;

    /**
    * 申请单名称
    */
    private String name;

    /**
    * 请假天数
    */
    private Double day;

    /**
    * 创建人账号
    */
    private String createBy;

    /**
    * 创建人名称
    */
    private String createByName;

    /**
    * 流程实例id
    */
    private String instanceId;

    /**
    * 审批状态 1:未提交 2:审批中 3:审批通过  
    */
    private String approvalStatus;

    /**
    * 创建时间
    */
    private Date createTime;
}

创建mapper接口

public interface QjMapper extends BaseMapper<Qj> {
    
}

我们在看下流程定义和部署的信息

package com.dmg.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 配置这个插件 mybatis-plus分页才好使
 */
@Configuration
//指定扫描目录
@MapperScan("com.dmg.mapper")
public class MybatisPlusConfig{

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //注意使用哪种数据库
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

}
package com.dmg.vo;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.util.Date;

/**
 * 流程定义 部署 vo类
 */
@Data
public class ProcessDefinitionVo {

    // 流程定义ID
    private String  processDefinitionId;

    // 流程定义名称
    private String  processDefinitionName;

    // 流程定义key
    private String  processDefinitionKey;


    // 租户编号
    private String tenantId;

    // 部署编号
    private String deployId;

    // 部署的时间
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date deployTime;

    // 是否挂起 1正常 2挂起
    private Integer suspensionState;

    // 流程定义的版本
    private int version;

    // 资源名称
    private String resourceName;

    // dgrm资源名称
    private String dgrmResourceName;
}
<?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.dmg.mapper.QjMapper">



    <select id="getProcessDefinitionPage" resultType="com.dmg.vo.ProcessDefinitionVo">
        SELECT
            a.ID_ processDefinitionId,
            a.KEY_ processDefinitionKey,
            a.NAME_ processDefinitionName,
            a.DEPLOYMENT_ID_ deployId,
            a.VERSION_ version,
            a.RESOURCE_NAME_ resourceName,
            a.DGRM_RESOURCE_NAME_ dgrmResourceName,
            a.SUSPENSION_STATE_ suspensionState,
            a.TENANT_ID_ tenantId,
            b.DEPLOY_TIME_ deployTime

        FROM
            act_re_procdef as a

            LEFT JOIN act_re_deployment as b on a.DEPLOYMENT_ID_=b.ID_

            ORDER BY b.DEPLOY_TIME_ desc


    </select>

</mapper>
package com.dmg.mapper;


public interface QjMapper extends BaseMapper<Qj> {




    /**
     * 分页流程定义 部署信息
     * @param page
     * @return
     */
    IPage<ProcessDefinitionVo>getProcessDefinitionPage(Page<ProcessDefinitionVo>page);
}
package com.dmg.service;


public interface FlowService {


    public IPage<ProcessDefinitionVo> getProcessDefinitionPage(int current, int size);



}
package com.dmg.service.impl;


/**
 * 流程定义服务实现类
 */
@Service
public class FlowServiceImpl extends FlowServiceFactory implements FlowService {


    @Autowired
    private QjMapper qjMapper;



  
    /**
     * 分页查询流程定义信息
     * @param current 当前页
     * @param size 每页条数
     */
    @Override
    public IPage<ProcessDefinitionVo> getProcessDefinitionPage(int current,int size) {
        Page<ProcessDefinitionVo>page=new Page<>(current,size);
        IPage<ProcessDefinitionVo> processDefinitionVoIPage = qjMapper.getProcessDefinitionPage(page);
        return processDefinitionVoIPage;
    }




}
package com.dmg.controller;


import java.io.IOException;

/**
 * 流程定义控制层
 */
@RestController
public class ProcessDefinitionController {

    @Autowired
    private FlowService flowService;




    /**
     *  分页查询流程定义 部署信息
     */
    @PostMapping("getProcessDefinitionPage")
    public Result getProcessDefinitionPage(@RequestBody PageReq req){
        IPage<ProcessDefinitionVo> processDefinitionPage = flowService.getProcessDefinitionPage(req.getCurrent()
                , req.getSize());
        return Result.success(processDefinitionPage);
    }



}
package com.dmg.vo.req;

import lombok.Data;

@Data
public class PageReq {

    /**
     * 当前页
     */
    int current;

    /**
     * 每页条数
     */
    int size;
}

http://localhost:8080/getProcessDefinitionPage

{

    "current":"1",

    "size": 2

}

我们来看下效果

我们也可以对当前流程进行挂载和激活

挂载后,无法在启动流程实例

只有正常的情况下才能往下走

package com.dmg.vo.req;

import lombok.Data;

@Data
public class FlowReq extends PageReq{

    /**
     * 流程定义名称
     */
    private String processDefinitionName;


    /**
     * 流程定义key
     */
    private String processDefinitionKey;


    /**
     * 任务id
     */
    private String taskId;


    /**
     *  当前人账号
     */
    private String account;


    /**
     * 流程定义id
     */
    private String processDefinitionId;


}

package com.dmg.service.impl;



/**
 * 流程定义服务实现类
 */
@Service
public class FlowServiceImpl extends FlowServiceFactory implements FlowService {



    /**
     * 挂载/激活 流程定义
     * @param req
     */
    @Override
    public void mountActivation(FlowReq req) {
        ProcessDefinition processDefinition = repositoryService.
                createProcessDefinitionQuery().processDefinitionId(req.getProcessDefinitionId()).singleResult();
        if(processDefinition.isSuspended()){
            //如果是暂停 那么激活他
            repositoryService.activateProcessDefinitionById(req.getProcessDefinitionId());
        }else {
            //如果是正常的 那么挂起他
            repositoryService.suspendProcessDefinitionById(req.getProcessDefinitionId());
        }
    }

}
package com.dmg.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dmg.vo.ProcessDefinitionVo;
import com.dmg.vo.req.FlowReq;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Map;

public interface FlowService {




    public void mountActivation(FlowReq req);


}
package com.dmg.controller;



/**
 * 流程定义控制层
 */
@RestController
public class ProcessDefinitionController {

    @Autowired
    private FlowService flowService;



    /**
     *  挂载/激活 流程定义
     */
    @PostMapping("mountActivation")
    public Result mountActivation(@RequestBody FlowReq req){
        flowService.mountActivation(req);
        return Result.success();
    }



}

我们在来看下结果

http://localhost:8080/mountActivation

{

    "processDefinitionId":"qj:2:e60a4c1e-6cb8-11ed-b720-005056c00008"

}

 我们可以看到act_re_procdef表的SUSPENSION_STATE_字段已经变成了2,就是挂起状态了

 这时候 我们启动一个流程实例来看看 他是是报错

package com.dmg.service;



public interface FlowService {



    public String startProcessInstance(String processDefinitionKey);

   


}
package com.dmg.service.impl;



/**
 * 流程定义服务实现类
 */
@Service
public class FlowServiceImpl extends FlowServiceFactory implements FlowService {



    /**
     * 启动流程实例,返回流程实例id
     * @param processDefinitionKey 流程定义key
     */
    @Override
    public String startProcessInstance(String processDefinitionKey){
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
        if(processInstance==null){
            throw new RuntimeException("启动流程实例失败");
        }
        //返回流程实例id
        return processInstance.getId();
    }



 

}
package com.dmg.controller;



/**
 * 流程定义控制层
 */
@RestController
public class ProcessDefinitionController {

    @Autowired
    private FlowService flowService;




    /**
     *  启动流程实例
     */
    @PostMapping("startProcessInstance")
    public Result startProcessInstance(@RequestBody FlowReq req){
        String s = flowService.startProcessInstance(req.getProcessDefinitionKey());
        return Result.success(s);
    }





}

我们来看下效果

http://localhost:8080/startProcessInstance

{

    "processDefinitionKey":"qj"

}

我这里启动流程实例,每次都是最新的版本启动的,一定要注意

可以看到当前流程是挂起的,不能启动流程实例

 我们在吧流程定义激活,然后在启动下流程实例

可以看到 已经启动成功了

 act_ru_task 运行时任务表已经有了数据,就是这个 提交

我们也可以部署bpmn.js传过来的xml文件的数据

注意这里的name后面必须以.bpmn结尾,否则act_re_procdef(已部署的流程定义表)没有数据

   /**
     * 部署xml
     */
    @PostMapping(value = "deployXml")
    public String deployXml(@RequestParam("name")String name,@RequestParam("xml") String xml) throws IOException {
        Deployment deploy = repositoryService.createDeployment()
                //name必须以xxx.bpmn结尾
                .addInputStream(name+".bpmn",new ByteArrayInputStream(xml.getBytes()))
                .name(name)
                .deploy();
        return deploy.getId();
    }

结果如下

关于bpmn.js的可以可以看下这个链接

vue集成bpmn.js_我是一只代码狗的博客-CSDN博客

springboot使用flowable(2)_我是一只代码狗的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想在Spring Boot项目中使用Flowable,你可以通过引入相应的依赖来实现。根据引用的内容,你可以添加以下依赖到你的项目中: ```xml <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-spring-boot-starter</artifactId> <version>6.7.2</version> </dependency> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-spring-boot-starter-actuator</artifactId> <version>6.7.2</version> </dependency> ``` 你也可以从引用和引用中提供的链接中下载Flowable的zip文件。这些文件包含了Flowable引擎的各个组件和执行器。下载并解压缩zip文件后,你可以将Flowable引擎部署到Tomcat服务器上,从而在Spring Boot项目中使用Flowable。 希望以上信息能帮助到你。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Spring Boot + Flowable 工作流引擎](https://blog.csdn.net/qq_39035773/article/details/125414301)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [SpringBoot + Flowable使用](https://blog.csdn.net/fajing_feiyue/article/details/116209534)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [SpringBoot + Flowable的基础使用](https://blog.csdn.net/S0001100/article/details/120042604)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值