quartz整合spring boot,

  quartz整合spring boot,

  

目录

介绍基于跳羚创建的网项目整合石英框架依次实现手动音量调节三层

 

  

介绍

石英是开放式交响乐开源组织在作业调度领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用石英。可以用来创建简单或为运行十个,百个,甚至是好几万个乔布斯这样复杂的程序工作。可以做成标准的爪哇组件或EJB。石英的最新版本为石英.

 

  石英可以在某一个有规律的时间点干某件事,是一个任务调度框架,可以被集成到爪哇岛的各种应用中使用、石英框架可以支持分布式任务处理

  

基于springboot创建的web项目整合Quartz框架

整体代码结构

 

  导入依赖

  依赖groupIdorg.springframework.boot/groupId artifactId弹簧-启动-启动器-石英/artifactId/依赖创建石英_演示数据库,执行tables_mysql_innodb.sql文件创建对应表,下面是文件内容

  ##在石英属性文件中,您需要设置#组织。石英。工作商店。driverdelegateclass=org。石英。impl。jdbcjobstore。stdjdbcdelegate # # # by : Ron Cordell-Ron Cordell #我在任何地方都没有看到这个,所以我想我应该在这里发布它。这是来自石英的脚本,用于在关系型数据库数据库中创建表,修改后使用引擎而不是米沙姆.如果存在QRTZ_FIRED_TRIGGERS,则删除表;如果存在,则删除表QRTZ _暂停_触发_ GRPS;如果存在QRTZ _调度程序_状态,则删除表;如果存在QRTZ_LOCKS,则删除表;如果存在QRTZ _简单_触发器,则删除表;如果存在QRTZ_SIMPROP_TRIGGERS,则删除表;如果存在QRTZ_CRON_TRIGGERS则删除表;如果存在QRTZ _ BLOB _触发器,则删除表;如果存在QRTZ _触发器,则删除表;如果存在QRTZ_JOB_DETAILS则删除表;如果存在QRTZ _日历,则删除表;CREATE TABLE QRTZ _ JOB _ DETAILS(SCHED _ NAME VARCHAR(120)NOT NULL,JOB_NAME VARCHAR(190) NOT NULL,JOB_GROUP VARCHAR(190) NOT NULL,DESCRIPTION VARCHAR(250) NULL,JOB _ CLASS _ NAME VARCHAR(250)NOT NULL,IS_DURABLE VARCHAR(1) NOT NULL,IS _ non concurrent VARCHAR VARCHAR(1)NOT NULL,IS _ UPDATE _ DATA VARCHAR(1)NOT NULL,REQUESTS _ RECOVERY VARCHAR(1)NOT NULL,JOB _ DATA BLOB

  PREV_FIRE_TIME BIGINT(13) NULL,PRIORITY INTEGER NULL,TRIGGER_STATE VARCHAR(16) NOT NULL,TRIGGER_TYPE VARCHAR(8) NOT NULL,START_TIME BIGINT(13) NOT NULL,END_TIME BIGINT(13) NULL,CALENDAR_NAME VARCHAR(190) NULL,MISFIRE_INSTR SMALLINT(2) NULL,JOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))ENGINE=InnoDB;CREATE TABLE QRTZ_SIMPLE_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(190) NOT NULL,TRIGGER_GROUP VARCHAR(190) NOT NULL,REPEAT_COUNT BIGINT(7) NOT NULL,REPEAT_INTERVAL BIGINT(12) NOT NULL,TIMES_TRIGGERED BIGINT(10) NOT NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))ENGINE=InnoDB;CREATE TABLE QRTZ_CRON_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(190) NOT NULL,TRIGGER_GROUP VARCHAR(190) NOT NULL,CRON_EXPRESSION VARCHAR(120) NOT NULL,TIME_ZONE_ID VARCHAR(80),PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))ENGINE=InnoDB;CREATE TABLE QRTZ_SIMPROP_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(190) NOT NULL, TRIGGER_GROUP VARCHAR(190) NOT NULL, STR_PROP_1 VARCHAR(512) NULL, STR_PROP_2 VARCHAR(512) NULL, STR_PROP_3 VARCHAR(512) NULL, INT_PROP_1 INT NULL, INT_PROP_2 INT NULL, LONG_PROP_1 BIGINT NULL, LONG_PROP_2 BIGINT NULL, DEC_PROP_1 NUMERIC(13,4) NULL, DEC_PROP_2 NUMERIC(13,4) NULL, BOOL_PROP_1 VARCHAR(1) NULL, BOOL_PROP_2 VARCHAR(1) NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))ENGINE=InnoDB;CREATE TABLE QRTZ_BLOB_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(190) NOT NULL,TRIGGER_GROUP VARCHAR(190) NOT NULL,BLOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))ENGINE=InnoDB;CREATE TABLE QRTZ_CALENDARS (SCHED_NAME VARCHAR(120) NOT NULL,CALENDAR_NAME VARCHAR(190) NOT NULL,CALENDAR BLOB NOT NULL,PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))ENGINE=InnoDB;CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_GROUP VARCHAR(190) NOT NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))ENGINE=InnoDB;CREATE TABLE QRTZ_FIRED_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL,ENTRY_ID VARCHAR(95) NOT NULL,TRIGGER_NAME VARCHAR(190) NOT NULL,TRIGGER_GROUP VARCHAR(190) NOT NULL,INSTANCE_NAME VARCHAR(190) NOT NULL,FIRED_TIME BIGINT(13) NOT NULL,SCHED_TIME BIGINT(13) NOT NULL,PRIORITY INTEGER NOT NULL,STATE VARCHAR(16) NOT NULL,JOB_NAME VARCHAR(190) NULL,JOB_GROUP VARCHAR(190) NULL,IS_NONCONCURRENT VARCHAR(1) NULL,REQUESTS_RECOVERY VARCHAR(1) NULL,PRIMARY KEY (SCHED_NAME,ENTRY_ID))ENGINE=InnoDB;CREATE TABLE QRTZ_SCHEDULER_STATE (SCHED_NAME VARCHAR(120) NOT NULL,INSTANCE_NAME VARCHAR(190) NOT NULL,LAST_CHECKIN_TIME BIGINT(13) NOT NULL,CHECKIN_INTERVAL BIGINT(13) NOT NULL,PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))ENGINE=InnoDB;CREATE TABLE QRTZ_LOCKS (SCHED_NAME VARCHAR(120) NOT NULL,LOCK_NAME VARCHAR(40) NOT NULL,PRIMARY KEY (SCHED_NAME,LOCK_NAME))ENGINE=InnoDB;CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);commit;配置quartz

  

server: port: ${PORT:12011} servlet: session: timeout: 86400s # session有效期(xxx秒) cookie: http-only: false # 如果为true, 浏览器脚本将无法访问cookie secure: false # 如果为true, 则仅通过https连接发送cookie, http无法携带cookie context-path: # 程序上下文路径配置spring: application: name: quartz-demo aop: proxy-target-class: true auto: true datasource: url: jdbc:mysql://localhost:3306/quartz_demo username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver # 配置日期格式化 jackson: date-format: yyyy-MM-dd HH:mm:ss #时间戳统一转换为指定格式 time-zone: GMT+8 # 时区修改为东8区 quartz: # 将任务等保存化到数据库 job-store-type: jdbc # 程序结束时会等待quartz相关的内容结束 wait-for-jobs-to-complete-on-shutdown: true # QuartzScheduler启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录 overwrite-existing-jobs: true properties: org: quartz: # scheduler相关 scheduler: # scheduler的实例名 instanceName: scheduler instanceId: AUTO # 持久化相关 jobStore: class: org.quartz.impl.jdbcjobstore.JobStoreTX driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate # 表示数据库中相关表是QRTZ_开头的 tablePrefix: QRTZ_ useProperties: false # 配置集群 # 是否加入集群 isClustered: true # 容许的最大作业延长时间 clusterCheckinInterval: 20000 # 线程池相关 threadPool: class: org.quartz.simpl.SimpleThreadPool # 线程数 threadCount: 10 # 线程优先级 threadPriority: 5 threadsInheritContextClassLoaderOfInitializingThread: truemybatis-plus: global-config: db-config: logic-delete-field: is_deleted logic-delete-value: 1 logic-not-delete-value: 0 configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpllogging: level: com.my.quartz: debug

添加sys_job表

 

  

CREATE TABLE `sys_job` ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `job_id` varchar(100) DEFAULT NULL, `job_name` varchar(255) DEFAULT NULL, `job_group_name` varchar(255) DEFAULT NULL, `invoke_target` varchar(255) NOT NULL, `cron_expression` varchar(50) DEFAULT NULL, `misfire_policy` varchar(255) DEFAULT NULL COMMENT cron计划策略0=默认,1=立即触发执行,2=触发一次执行,3=不触发立即执行, `status` varchar(10) DEFAULT NULL COMMENT 任务状态(0正常 1暂停), `concurrent` varchar(10) DEFAULT NULL COMMENT 是否并发执行(0允许 1禁止), PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

写两条数据

 

  

 

  

 

  

依次实现mvc三层

mapper层的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.my.quartz.boot.mapper.SysJobMapper"> <resultMap id="BaseResultMap" type="com.my.quartz.boot.SysJob"> <id column="id" jdbcType="BIGINT" property="id" /> <result column="job_id" jdbcType="VARCHAR" property="jobId" /> <result column="job_name" jdbcType="VARCHAR" property="jobName" /> <result column="job_group_name" jdbcType="VARCHAR" property="jobGroupName" /> <result column="invoke_target" jdbcType="VARCHAR" property="invokeTarget" /> <result column="cron_expression" jdbcType="VARCHAR" property="cronExpression" /> <result column="misfire_policy" jdbcType="VARCHAR" property="misfirePolicy" /> <result column="status" jdbcType="VARCHAR" property="status" /> <result column="concurrent" jdbcType="VARCHAR" property="concurrent" /> </resultMap> <sql id="Base_Column_List"> t.id, t.job_id jobId, t.job_name jobName, t.job_group_name jobGroupName, t.invoke_target invokeTarget, t.cron_expression cronExpression, t.misfire_policy misfirePolicy, t.status, t.concurrent </sql></mapper>

mapper接口

 

  

/** * Auto Generated * * @author :Boy * @date :Created in 2022-06-18 * @description: * @modified By: */public interface SysJobMapper extends BaseMapper<SysJob> {}

service接口

 

  

public interface SysJobService extends IService<SysJob> {}

service接口实现

 

  

@Servicepublic class SysJobServiceImpl extends ServiceImpl<SysJobMapper, SysJob> implements SysJobService { @Autowired private Scheduler scheduler; @Autowired private ScheduleUtils scheduleUtils; /** * 项目启动时,初始化定时器 * 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据) */ @PostConstruct public void init() throws SchedulerException, TaskException { scheduler.clear(); List<SysJob> jobList = baseMapper.selectList(null); for (SysJob job : jobList) { scheduleUtils.createScheduleJob(scheduler, job); } }}

controller代码

 

  

@RestController@RequestMapping("/job")public class SysJobController { @Resource private SysJobService sysJobService; @Resource private ScheduleUtils scheduleUtils; @Resource private Scheduler scheduler; @PostMapping("/add") public Object add(@RequestBody SysJob entity) throws SchedulerException, TaskException { sysJobService.save(entity); scheduleUtils.createScheduleJob(scheduler, entity); return "ok"; }}

ScheduleUtils 定时任务工具类

 

  

/** * @Author ScholarTang * @Date 2021/7/15 下午3:50 * @Desc 定时任务工具类 */@Componentpublic class ScheduleUtils { @Autowired private Scheduler scheduler; /** * 构建任务触发对象 * * @param jobName * @param jobGroup * @return */ public TriggerKey getTriggerKey(String jobName, String jobGroup) { return TriggerKey.triggerKey(jobName, jobGroup); } /** * 构建任务键对象 * * @param jobName * @param jobGroup * @return */ public JobKey getJobKey(String jobName, String jobGroup) { return JobKey.jobKey(jobName, jobGroup); } /** * 创建定时调度任务 * * * @param scheduler * @param job * @throws SchedulerException * @throws TaskException */ public void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException { // 构建job信息 String jobName = job.getJobId() + "_" + job.getJobName(); String jobGroupName = job.getJobGroupName(); //TODO 反射动态获取Job实现类 //构建job实例 JobDetail jobDetail = JobBuilder.newJob(QuartzJobImpl.class) .withIdentity(getJobKey(jobName, jobGroupName)) .build(); jobDetail.getJobDataMap().put("QuartzJobExecutionData", job); // 表达式调度构建器 CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()); cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder); // 按新的cronExpression表达式构建一个新的trigger CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobName, jobGroupName)) .withSchedule(cronScheduleBuilder).build(); // 放入参数,运行时的方法可以获取 jobDetail.getJobDataMap().put("QuartzJobExecutionData", job); // 判断是否存在 if (scheduler.checkExists(getJobKey(jobName, jobGroupName))) { // 防止创建时存在数据问题 先移除,然后在执行创建操作 scheduler.deleteJob(getJobKey(jobName, jobGroupName)); } //创建定时任务调度 scheduler.scheduleJob(jobDetail, trigger); // 暂停任务 规定 0启动 1暂停 if (job.getStatus().equals("1")) { scheduler.pauseJob(getJobKey(jobName, jobGroupName)); } } /** * 删除定时调度任务 * * @param sysJob * @throws SchedulerException */ public void deleteScheduleJob(SysJob sysJob) throws SchedulerException { scheduler.deleteJob(getJobKey(sysJob.getJobId() + "_" + sysJob.getJobName(), sysJob.getJobGroupName())); } /** * 设置定时任务策略 * * @param sysJob * @param cronScheduleBuilder * @return */ public CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob sysJob, CronScheduleBuilder cronScheduleBuilder) throws TaskException { switch (sysJob.getMisfirePolicy()) { case "0": return cronScheduleBuilder; case "1": return cronScheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires(); case "2": return cronScheduleBuilder.withMisfireHandlingInstructionFireAndProceed(); case "3": return cronScheduleBuilder.withMisfireHandlingInstructionDoNothing(); default: throw new TaskException("任务失败策略 " + sysJob.getMisfirePolicy() + " 不能在cron计划任务中使用", TaskException.Code.CONFIG_ERROR); } }}

创建一个Job实现类,只是一个简单实现类,没有对方法添加参数

 

  

@Slf4j@Componentpublic class QuartzJobImpl implements Job { @Autowired private ApplicationContext context; @SneakyThrows @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { SysJob sysJob = new SysJob(); BeanUtils.copyProperties(jobExecutionContext.getMergedJobDataMap().get("QuartzJobExecutionData"), sysJob); log.info("正在执行任务"); String invokeTarget = sysJob.getInvokeTarget(); String beanName = invokeTarget.split("\.")[0]; String methodName = invokeTarget.split("\.")[1]; Object bean = context.getBean(beanName); Class<?> clazz = bean.getClass(); Method method = clazz.getMethod(methodName); method.invoke(bean); log.info("已结束任务"); System.out.println(); }}

创建最终任务执行类,执行函数级别的定时任务,数据库中的invoke_target是和这里放入spring中的名称相同的,quartz_target.hello最终执行的函数就是hello函数

 

  

@Slf4j@Component("quartz_target")public class QuartzJobExe { @Resource private Scheduler scheduler; public void hello() throws Exception { System.out.println("[job]实例执行...hello..." + System.currentTimeMillis()); } public void action() throws Exception { System.out.println("[job]实例执行...action..." + System.currentTimeMillis()); }}

最终代码结构

 

  

 

  启动spring boot之后的任务状态

  

 

  使用postman工具类添加一个任务

  

 

  然后在代码中添加一个对应的方法

  

 

  重新启动springboot的运行结果

  

 

  

理论上使用这样的反射方式可以运行任何代码的

 

  

到此这篇关于springboot创建的web项目整合Quartz框架的项目实践的文章就介绍到这了,更多相关springboot整合Quartz框架内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • spring编程式事务处理,spring编程事务
  • spring编程式事务处理,spring编程事务,详解Spring学习之编程式事务管理
  • spring的核心功能模块有几个,列举一些重要的spring模块
  • spring的核心功能模块有几个,列举一些重要的spring模块,七个Spring核心模块详解
  • spring注解和springmvc的注解,SpringMVC常用注解
  • spring注解和springmvc的注解,SpringMVC常用注解,详解springmvc常用5种注解
  • spring实现ioc的四种方法,spring的ioc的三种实现方式
  • spring实现ioc的四种方法,spring的ioc的三种实现方式,简单实现Spring的IOC原理详解
  • spring事务失效问题分析及解决方案怎么做,spring 事务失效情况
  • spring事务失效问题分析及解决方案怎么做,spring 事务失效情况,Spring事务失效问题分析及解决方案
  • spring5.0新特性,spring4新特性
  • spring5.0新特性,spring4新特性,spring5新特性全面介绍
  • spring ioc以及aop原理,springmvc aop原理
  • spring ioc以及aop原理,springmvc aop原理,深入浅析Spring 的aop实现原理
  • Spring cloud网关,spring cloud zuul作用
  • 留言与评论(共有 条评论)
       
    验证码: