springBoot+quartz实现动态定时任务

第一步pom.xml,因为我配置了多数据源和webService所以有很多jar是定时任务不需要的,看情况删除




    4.0.0

    xm_demo
    xm_demo
    1.0-SNAPSHOT


    xm_demo Maven Webapp
    
    http://www.example.com
    
    
        org.springframework.boot
        spring-boot-starter-parent
        1.5.9.RELEASE
         
    
    
    
        UTF-8
        UTF-8
        1.8
        1.2.33
        1.0.14
        1.3.1
        3.0.8.RELEASE
        2.2.2
        3.0.2.RELEASE
    

    
        
        
            com.google.code.gson
            gson
            2.6.2
        
        
        
            org.apache.cxf
            cxf-spring-boot-starter-jaxws
            3.1.11
        

        
        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        
        
        
            net.sourceforge.nekohtml
            nekohtml
            1.9.22
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            com.alibaba
            druid
            1.1.6
        

        
        
            com.oracle
            ojdbc6
            11.2.0.3
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
        
       
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.0.1
        
       
        
            com.alibaba
            fastjson
            1.2.41
        

        
        
            org.apache.httpcomponents
            httpclient
            4.5
        
        
            org.apache.httpcomponents
            httpmime
            4.5
        
        
            org.apache.httpcomponents
            httpcore
            4.4.1
        

        
        
            net.sf.json-lib
            json-lib
            2.4
            jdk15
        
        
        
            commons-fileupload
            commons-fileupload
            1.3
        
        
        
            com.thoughtworks.xstream
            xstream
            1.4.3
        
        
        
            org.quartz-scheduler
            quartz
            2.2.3
        
        
            org.quartz-scheduler
            quartz-jobs
            2.2.3
        
        
            org.springframework
            spring-context-support
        
        
            org.apache.commons
            commons-lang3
            3.9
        
    


    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    true
                
            
        
        
        
            
                src/main/resources
                
                    *
                    **/*
                
                false
            
            
                src/main/java
                
                    **/*.properties
                    **/*.xml
                
                false
            
        
    

第二步,数据库表结构,根据自己需求更改(特别注意类名是包路径+类名,例如:com.xlt.jczb.controller.HelloWorldJob,方法名没用到)

springBoot+quartz实现动态定时任务_第1张图片

 第三步,实体类

package com.xlt.xfzb.entity;

import java.util.Date;

public class Dingshi {

	//任务值唯一ID
	private String job_id;
	//任务名称
	private String job_name;
	//类名
	private String bean_name;
	//方法名
	private String method_name;
	//地址
	private String url;
	//参数
	public  String params;
	//表达式
	private String cron;
	//状态
	private String status;
	//备注
	private String remark;
	//创建时间
	private Date create_time;
	//修改时间
	private String update_time;
	//整备场ID
	private String zbc_id;
	//整备场名称
	private String zbc_name;
	//机务段ID
	private String jwd_id;
	//机务段名称
	private String jwd_name;

	// 任务分组
	private String jobGroup;

	public String getJobGroup() {
		return jobGroup="xf";
	}

	public void setJobGroup(String jobGroup) {
		this.jobGroup = jobGroup;
	}

	public void setParams(String params) {
		this.params = params;
	}

	public String getJob_id() {
		return job_id;
	}

	public void setJob_id(String job_id) {
		this.job_id = job_id;
	}

	public String getJob_name() {
		return job_name;
	}

	public void setJob_name(String job_name) {
		this.job_name = job_name;
	}

	public String getBean_name() {
		return bean_name;
	}

	public void setBean_name(String bean_name) {
		this.bean_name = bean_name;
	}

	public String getMethod_name() {
		return method_name;
	}

	public void setMethod_name(String method_name) {
		this.method_name = method_name;
	}

	public String getUrl() {
		return url;
	}

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

	public String getParams() {
		return params;
	}


	public String getCron() {
		return cron;
	}

	public void setCron(String cron) {
		this.cron = cron;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public Date getCreate_time() {
		return create_time;
	}

	public void setCreate_time(Date create_time) {
		this.create_time = create_time;
	}

	public String getUpdate_time() {
		return update_time;
	}

	public void setUpdate_time(String update_time) {
		this.update_time = update_time;
	}

	public String getZbc_id() {
		return zbc_id;
	}

	public void setZbc_id(String zbc_id) {
		this.zbc_id = zbc_id;
	}

	public String getZbc_name() {
		return zbc_name;
	}

	public void setZbc_name(String zbc_name) {
		this.zbc_name = zbc_name;
	}

	public String getJwd_id() {
		return jwd_id;
	}

	public void setJwd_id(String jwd_id) {
		this.jwd_id = jwd_id;
	}

	public String getJwd_name() {
		return jwd_name;
	}

	public void setJwd_name(String jwd_name) {
		this.jwd_name = jwd_name;
	}
}

第四步,持久层

package com.xlt.xfzb.dao.test01;


import com.xlt.xfzb.entity.Dingshi;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public interface DingshiMapper {

	//获得任务列表
	List getDingshi(Dingshi bit);
	
	void updateDingshi(Dingshi bit);
	
	void addDingshi(Dingshi bit);
	
	void delDingshi(String bitIds);

	//根据任务ID获取任务
	Dingshi getByKey(String job_id);
}

 DingshiMapper.xml





	
	

	
	

	
	  	update SCHEDULE_JOB 
	  	
			
				job_name = #{job_name,jdbcType=VARCHAR},
			
	  		
				bean_name = #{bean_name,jdbcType=VARCHAR},
			
			
				method_name = #{method_name,jdbcType=VARCHAR},
			
			
				params = #{params,jdbcType=VARCHAR},
			
			
				cron = #{cron,jdbcType=VARCHAR},
			
			
				update_time = #{update_time,jdbcType=VARCHAR},
			
			
				remark = #{remark,jdbcType=VARCHAR},
			
			
				status = #{status,jdbcType=VARCHAR},
			
	  	
	  	where
	  		job_id = #{job_id,jdbcType=VARCHAR}
    
    
    	insert into SCHEDULE_JOB(job_name,bean_name,method_name,params,cron,status,remark,create_time,zbc_id,zbc_name,jwd_id,jwd_name,job_id,url)
    	values(#{job_name,jdbcType=VARCHAR},#{bean_name,jdbcType=VARCHAR},#{method_name,jdbcType=VARCHAR},#{params,jdbcType=VARCHAR},#{cron,jdbcType=VARCHAR},
		#{status,jdbcType=VARCHAR},#{remark,jdbcType=VARCHAR},#{create_time,jdbcType=DATE},#{zbc_id,jdbcType=VARCHAR}
		,#{zbc_name,jdbcType=VARCHAR},#{jwd_id,jdbcType=VARCHAR},#{jwd_name,jdbcType=VARCHAR},#{job_id},#{url,jdbcType=VARCHAR})
    
    
    	delete from SCHEDULE_JOB
    	where job_id in (${value})
    
  
  

第五步,quartz配置

package com.xlt.xfzb.config;

import org.quartz.Scheduler;
import org.quartz.spi.JobFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import java.io.IOException;
import java.util.Properties;


/**
 * quartz配置信息
 */

@Configuration
public class QuartzConfig {

    @Autowired
    private JobFactory jobFactory;

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        try {
            schedulerFactoryBean.setOverwriteExistingJobs(true);
            schedulerFactoryBean.setQuartzProperties(quartzProperties());
            schedulerFactoryBean.setJobFactory(jobFactory);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return schedulerFactoryBean;
    }

    // 指定quartz.properties,可在配置文件中配置相关属性
    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
       // propertiesFactoryBean.setLocation(new ClassPathResource("/config/quartz.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    // 创建schedule
    @Bean(name = "scheduler")
    public Scheduler scheduler() {
        return schedulerFactoryBean().getScheduler();
    }

}

第六步,核心控制器

package com.xlt.xfzb.util;


import com.xlt.xfzb.entity.Dingshi;
import org.apache.log4j.Logger;
import org.quartz.*;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
 * @Classname QuartzManager
 * @Description TODO
 * @Date 2019/12/2 11:04
 * @Created by xm
 */
@Service
public class QuartzManager {

    public final Logger log = Logger.getLogger(this.getClass());
    @Autowired
    private Scheduler scheduler;

    /**
     * 添加任务
     *
     * @param
     * @throws SchedulerException
     */
    @SuppressWarnings("unchecked")
    public void addJob(Dingshi task) {
        try {
            // 创建jobDetail实例,绑定Job实现类
            // 指明job的名称,所在组的名称,以及绑定job类

            Class jobClass = (Class) (Class.forName(task.getBean_name()).newInstance()
                    .getClass());
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(task.getJob_name(), task.getJobGroup())// 任务名称和组构成任务key
                    .build();
            // 定义调度触发规则
            // 使用cornTrigger规则
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity(task.getJob_name(), task.getJobGroup())// 触发器key
                    .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
                    .withSchedule(CronScheduleBuilder.cronSchedule(task.getCron())).startNow().build();
            // 把作业和触发器注册到任务调度中
            scheduler.scheduleJob(jobDetail, trigger);
            // 启动
            if (!scheduler.isShutdown()) {
                scheduler.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取所有计划中的任务列表
     *
     * @return
     * @throws SchedulerException
     */
    public List getAllJob() throws SchedulerException {
        GroupMatcher matcher = GroupMatcher.anyJobGroup();
        Set jobKeys = scheduler.getJobKeys(matcher);
        List jobList = new ArrayList();
        for (JobKey jobKey : jobKeys) {
            List triggers = scheduler.getTriggersOfJob(jobKey);
            for (Trigger trigger : triggers) {
                Dingshi job = new Dingshi();
                job.setJob_name(jobKey.getName());
                job.setJobGroup(jobKey.getGroup());
                job.setRemark("触发器:" + trigger.getKey());
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                job.setStatus(triggerState.name());
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    job.setCron(cronExpression);
                }
                jobList.add(job);
            }
        }
        return jobList;
    }

    /**
     * 所有正在运行的job
     *
     * @return
     * @throws SchedulerException
     */
    public List getRunningJob() throws SchedulerException {
        List executingJobs = scheduler.getCurrentlyExecutingJobs();
        List jobList = new ArrayList(executingJobs.size());
        for (JobExecutionContext executingJob : executingJobs) {
            Dingshi job = new Dingshi();
            JobDetail jobDetail = executingJob.getJobDetail();
            JobKey jobKey = jobDetail.getKey();
            Trigger trigger = executingJob.getTrigger();
            job.setJob_name(jobKey.getName());
            job.setJobGroup(jobKey.getGroup());
            job.setRemark("触发器:" + trigger.getKey());
            Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
            job.setStatus(triggerState.name());
            if (trigger instanceof CronTrigger) {
                CronTrigger cronTrigger = (CronTrigger) trigger;
                String cronExpression = cronTrigger.getCronExpression();
                job.setCron(cronExpression);
            }
            jobList.add(job);
        }
        return jobList;
    }

    /**
     * 暂停一个job
     *
     * @param dingshi
     * @throws SchedulerException
     */
    public void pauseJob(Dingshi dingshi) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(dingshi.getJob_name(), dingshi.getJobGroup());
        scheduler.pauseJob(jobKey);
    }

    /**
     * 恢复一个job
     *
     * @param task
     * @throws SchedulerException
     */
    public void resumeJob(Dingshi task) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(task.getJob_name(), task.getJobGroup());
        scheduler.resumeJob(jobKey);
    }

    /**
     * 删除一个job
     *
     * @param task
     * @throws SchedulerException
     */
    public void deleteJob(Dingshi task) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(task.getJob_name(), task.getJobGroup());
        scheduler.deleteJob(jobKey);

    }

    /**
     * 立即执行job
     *
     * @param task
     * @throws SchedulerException
     */
    public void runJobNow(Dingshi task) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(task.getJob_name(), task.getJobGroup());
        scheduler.triggerJob(jobKey);
    }

    /**
     * 更新job时间表达式
     *
     * @param task
     * @throws SchedulerException
     */
    public void updateJobCron(Dingshi task) throws SchedulerException {

        TriggerKey triggerKey = TriggerKey.triggerKey(task.getJob_name(), task.getJobGroup());

        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCron());

        trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

        scheduler.rescheduleJob(triggerKey, trigger);
    }
}

第七步,服务层

package com.xlt.jczb.service;


import com.xlt.jczb.entity.Dingshi;
import org.quartz.SchedulerException;

import java.util.List;

public interface DingshiService {

	//任务列表
	List getDingshi(Dingshi bit);

	//更新定时任务库表数据
	boolean updateDingshi(Dingshi bit);

	//增加库表数据
	String addDingshi(Dingshi bit);

	//根据ID删除库表信息
	void delDingshi(String bitIds);

	//根据ID查询任务详情
	Dingshi getByKey(String id);

	//启动任务
	void run(Dingshi dingshi) throws SchedulerException;

	//初始化任务
	void initSchedule() throws SchedulerException;

	//新增服务
	void addJob(String id);

	//暂停服务
	void pauseJob(String id);

	//恢复服务
	void resumeJob(String id);

	//删除服务
	void  deleteJob(String id);

	//立即执行服务
	void runJobNow(String id);

	//更新表达式
	void updateJobCron(Dingshi dingshi);

	//所有计划中任务列表
	List getAllJob();

	//正在运行任务列表
	List getRunningJob();
}
package com.xlt.jczb.service.impl;

import com.xlt.jczb.entity.Dingshi;
import com.xlt.jczb.mapper.DingshiMapper;
import com.xlt.jczb.service.DingshiService;
import com.xlt.jczb.util.QuartzManager;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 定时任务调度业务对象
 *
 * @author xm
 * @date	2019-12-2 14:50:59
 */
@Service
public class DingshiServiceImp implements DingshiService {

	@Autowired
	private DingshiMapper dingshiMapper;

	@Autowired
	QuartzManager quartzManager;

	@Override
	public List getDingshi(Dingshi bit) {
		return dingshiMapper.getDingshi(bit);
	}

	@Override
	public boolean updateDingshi(Dingshi bit) {
		try {
			dingshiMapper.updateDingshi(bit);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	@Override
	public String addDingshi(Dingshi bit) {
		String id = UUID.randomUUID().toString();
		try {
			bit.setCreate_time(new Date());
			bit.setJob_id(id);
			bit.setStatus("0");
			dingshiMapper.addDingshi(bit);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return id;
	}

	@Override
	public void delDingshi(String bitIds) {
		try {
			dingshiMapper.delDingshi(bitIds);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public Dingshi getByKey(String id) {
		return dingshiMapper.getByKey(id);
	}

	@Override
	public void run(Dingshi dingshi) throws SchedulerException {
		quartzManager.runJobNow(dingshi);
	}

	@Override
	public void initSchedule() throws SchedulerException {
		// 这里获取任务信息数据
		List dingshi = this.getDingshi(new Dingshi());
		for (Dingshi dingshi1 : dingshi) {
			if("1".equals(dingshi1.getStatus())){
				quartzManager.addJob(dingshi1);
			}

		}

	}

	@Override
	public void addJob(String id) {
		Dingshi byKey = this.getByKey(id);
		quartzManager.addJob(byKey);
	}

	@Override
	public void pauseJob(String id) {
		Dingshi byKey = this.getByKey(id);
		try {
			quartzManager.pauseJob(byKey);
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void resumeJob(String id) {
		Dingshi byKey = this.getByKey(id);
		try {
			quartzManager.resumeJob(byKey);
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void deleteJob(String id) {
		Dingshi byKey = this.getByKey(id);
		try {
			quartzManager.deleteJob(byKey);
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void runJobNow(String id) {
		Dingshi byKey = this.getByKey(id);
		try {
			quartzManager.runJobNow(byKey);
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void updateJobCron(Dingshi dingshi) {
		try {
			quartzManager.updateJobCron(dingshi);
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}

	@Override
	public List getAllJob() {
		try {
			return quartzManager.getAllJob();
		} catch (SchedulerException e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public List getRunningJob() {
		try {
			return quartzManager.getRunningJob();
		} catch (SchedulerException e) {
			e.printStackTrace();
			return null;
		}
	}

}

 第八步,前端控制器

package com.xlt.jczb.controller;

import com.xlt.jczb.entity.Dingshi;
import com.xlt.jczb.service.DingshiService;
import com.xlt.jczb.util.SupConstant;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 定时任务前端控制器
 *
 * @author xm
 * @date    2019-12-2 14:59:29
 */
@Controller
@RequestMapping("task")
public class TaskController {

    //定时任务实现业务
    @Autowired
   private DingshiService dingshiService;


    /**
     * 查询任务列表,可以根据整备场,机务段,类名,任务ID查询
     * @param
     * @return
     */
    @GetMapping("/list")
    public ResponseEntity list(Dingshi dingshi) {
        List dingshiList = dingshiService.getDingshi(dingshi);
        return new ResponseEntity(dingshiList,HttpStatus.OK);
    }

    /**
     * 查询所有运行中任务列表
     * @param dingshi
     * @return
     */
    /*@GetMapping("/getRunningJob")
    public ResponseEntity getRunningJob(Dingshi dingshi) {
        List dingshiList = dingshiService.getRunningJob();
        return new ResponseEntity(dingshiList,HttpStatus.OK);
    }*/

    /**
     * 新增任务 (特别注意类名称是类的包路径+类名)
     * @param
     * @return
     */
    @PostMapping("/addJob")
    public ResponseEntity addJob(Dingshi dingshi) {
        if (StringUtils.isEmpty(dingshi)) {
            return new ResponseEntity(SupConstant.BAD_PARAMETER,HttpStatus.OK);
        }
        dingshi.setCreate_time(new Date());
        //数据库保存定时任务
        dingshiService.addDingshi(dingshi);
        //若保存的任务是开启状态
        if ("1".equals(dingshi.getStatus())) {
            dingshiService.addJob(dingshi.getJob_id());
        }

        return new ResponseEntity(SupConstant.SUCCESS_OPERATION,HttpStatus.OK);
    }

    /**
     * 暂停服务
     * @param id
     * @return
     */
    @GetMapping("/pauseJob")
    public ResponseEntity pauseJob(String id) {
        dingshiService.pauseJob(id);
        return new ResponseEntity(SupConstant.SUCCESS_OPERATION,HttpStatus.OK);
    }

    /**
     * 恢复服务
     * @param id
     * @return
     */
    @GetMapping("/resumeJob")
    public ResponseEntity resumeJob(String id) {
        dingshiService.resumeJob(id);
        return new ResponseEntity(SupConstant.SUCCESS_OPERATION,HttpStatus.OK);
    }


    /**
     * 更新定时任务信息
     * @param dingshi
     * @return
     */
    @PutMapping("update")
    public ResponseEntity update(Dingshi dingshi){
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dingshi.setUpdate_time(format.format(new Date()));
        //更新数据库信息
        dingshiService.updateDingshi(dingshi);
        Dingshi byKey = dingshiService.getByKey(dingshi.getJob_id());
        //若开启任务
        if ("1".equals(byKey.getStatus())) {
            dingshiService.updateJobCron(byKey);
        }
        return new ResponseEntity(SupConstant.SUCCESS_OPERATION,HttpStatus.OK);
    }

    /**
     * 删除定时任务
     * @param id
     * @return
     */
    @DeleteMapping("del")
    public ResponseEntity del(String id){
        //删除任务
        dingshiService.deleteJob(id);
        //删除数据库
        dingshiService.delDingshi(id);
        return new ResponseEntity(SupConstant.SUCCESS_OPERATION,HttpStatus.OK);
    }

    /**
     * 修改任务状态0关闭,1启用
     * @param dingshi
     * @return
     */
    @PutMapping("updateState")
    public ResponseEntity updateState(Dingshi dingshi){
        if (StringUtils.isEmpty(dingshi)) {
            return new ResponseEntity(SupConstant.BAD_PARAMETER,HttpStatus.OK);
        }
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dingshi.setUpdate_time(format.format(new Date()));
        dingshiService.updateDingshi(dingshi);
        //改为启用
        if ("1".equals(dingshi.getStatus())) {
            dingshiService.addJob(dingshi.getJob_id());
            //改为关闭
        }else if("0".equals(dingshi.getStatus())){
            //删除任务
            dingshiService.deleteJob(dingshi.getJob_id());
        }
        return new ResponseEntity(SupConstant.SUCCESS_OPERATION,HttpStatus.OK);
    }

}

好了,搞定了,去测试一下呗!!

你可能感兴趣的:(后端)