调度中心API

This commit is contained in:
XinWei 2024-07-10 15:17:48 +08:00
parent e309502115
commit f6e2f92352
27 changed files with 988 additions and 318 deletions

View File

@ -43,6 +43,10 @@
<artifactId>spring-cloud-starter-openfeign</artifactId> <artifactId>spring-cloud-starter-openfeign</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -2,25 +2,24 @@ package com.xxl.job.admin.api.info;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.xxl.job.admin.api.info.dto.JobInfoDetailRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO; import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoSaveReqDTO;
import com.xxl.job.admin.enums.ApiConstants; import com.xxl.job.admin.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* @Description TODO * @Description 调度任务信息Api接口
*/ */
@FeignClient(name = ApiConstants.NAME) @FeignClient(name = ApiConstants.NAME, path = "/xxl-job-admin")
@Tag(name = "RPC 服务 - 任务信息管理") @Tag(name = "RPC 服务 - 任务信息管理")
@RequestMapping("")
public interface JobInfoApi { public interface JobInfoApi {
String PREFIX = ApiConstants.PREFIX + "/info"; String PREFIX = ApiConstants.PREFIX + "/info";
@GetMapping(PREFIX + "/page") @GetMapping(PREFIX + "/page")
@ -32,4 +31,31 @@ public interface JobInfoApi {
@Parameter(name = "handlerName", description = "处理器名字", required = false) @Parameter(name = "handlerName", description = "处理器名字", required = false)
public CommonResult<PageResult<JobInfoRespDTO>> getPage(@RequestParam(value = "pageNo") Integer pageNo, @RequestParam(value = "pageSize") Integer pageSize, @RequestParam(required = false, value = "name") String name, @RequestParam(required = false, value = "status") Integer status, @RequestParam(required = false, value = "handlerName") String handlerName); public CommonResult<PageResult<JobInfoRespDTO>> getPage(@RequestParam(value = "pageNo") Integer pageNo, @RequestParam(value = "pageSize") Integer pageSize, @RequestParam(required = false, value = "name") String name, @RequestParam(required = false, value = "status") Integer status, @RequestParam(required = false, value = "handlerName") String handlerName);
@GetMapping(PREFIX + "/get")
@Operation(summary = "获得任务详情")
@Parameter(name = "id", description = "任务主键", required = true)
CommonResult<JobInfoDetailRespDTO> get(@RequestParam("id") Integer id);
@PostMapping(PREFIX + "/create")
@Operation(summary = "创建任务")
CommonResult<Boolean> create(@RequestBody JobInfoSaveReqDTO jobInfoSaveReqDTO);
@PutMapping(PREFIX + "/update")
@Operation(summary = "修改任务")
CommonResult<Boolean> update(@RequestBody JobInfoSaveReqDTO jobInfoSaveReqDTO);
@DeleteMapping(PREFIX + "/delete")
@Operation(summary = "删除任务")
CommonResult<Boolean> delete(@RequestParam("id") Integer id);
@PutMapping(PREFIX + "/update-status")
@Operation(summary = "任务状态修改")
CommonResult<Boolean> updateStatus(@RequestParam("id") Integer id, @RequestParam("status") Integer status);
@PutMapping(PREFIX + "/trigger")
@Operation(summary = "任务立即执行一次")
CommonResult<Object> trigger(@RequestParam("id") Integer id);
@GetMapping(PREFIX + "/get_next_times")
@Operation(summary = "下n次执行时间")
CommonResult<List<String>> getNextTimes(@RequestParam("id") Integer id);
} }

View File

@ -0,0 +1,26 @@
package com.xxl.job.admin.api.info.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @Description 任务详情
*/
@Schema(description = "RPC 服务 - 任务信息 Response DTO")
@Data
public class JobInfoDetailRespDTO {
@Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer id;
@Schema(description = "任务名称")
private String name;
@Schema(description = "处理器的名字")
private String handlerName;
@Schema(description = "处理器的参数")
private String handlerParam;
@Schema(description = "CRON 表达式")
private String cronExpression;
@Schema(description = "重试次数")
private Integer retryCount;
@Schema(description = "监控超时时间")
private Integer monitorTimeout;
}

View File

@ -0,0 +1,24 @@
package com.xxl.job.admin.api.info.dto;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "RPC 服务 - 任务列表 Request DTO")
@Data
public class JobInfoPageReqDTO extends PageParam {
@Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer id;
@Schema(description = "任务名称")
private String name;
@Schema(description = "任务状态")
private Integer status;
@Schema(description = "处理器的名字")
private String handlerName;
@Schema(description = "处理器的参数")
private String handlerParam;
@Schema(description = "CRON 表达式")
private String cronExpression;
}

View File

@ -1,25 +1,34 @@
package com.xxl.job.admin.api.info.dto; package com.xxl.job.admin.api.info.dto;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
/** /**
* @Description 任务信息 * @Description 任务列表单个信息
*/ */
@Schema(description = "RPC 服务 - 任务信息 Response DTO") @Schema(description = "RPC 服务 - 任务信息 Response DTO")
@Data @Data
@ExcelIgnoreUnannotated
public class JobInfoRespDTO { public class JobInfoRespDTO {
@Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("任务编号")
private Integer id; private Integer id;
@Schema(description = "任务名称") @Schema(description = "任务名称")
@ExcelProperty("任务名称")
private String name; private String name;
@Schema(description = "任务状态") @Schema(description = "任务状态")
@ExcelProperty("任务状态")
private Integer status; private Integer status;
@Schema(description = "处理器的名字") @Schema(description = "处理器的名字")
@ExcelProperty("处理器的名字")
private String handlerName; private String handlerName;
@Schema(description = "处理器的参数") @Schema(description = "处理器的参数")
@ExcelProperty("处理器的参数")
private String handlerParam; private String handlerParam;
@Schema(description = "CRON 表达式") @Schema(description = "CRON 表达式")
@ExcelProperty("CRON 表达式")
private String cronExpression; private String cronExpression;
} }

View File

@ -0,0 +1,26 @@
package com.xxl.job.admin.api.info.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @Description TODO
*/
@Schema(description = "RPC 服务 - 新增任务 Request DTO")
@Data
public class JobInfoSaveReqDTO {
@Schema(description = "任务编号")
private Integer id;
@Schema(description = "任务名称")
private String name;
@Schema(description = "处理器的名字")
private String handlerName;
@Schema(description = "处理器的参数")
private String handlerParam;
@Schema(description = "CRON 表达式")
private String cronExpression;
@Schema(description = "重试次数")
private Integer retryCount;
@Schema(description = "监控超时时间")
private Integer monitorTimeout;
}

View File

@ -0,0 +1,28 @@
package com.xxl.job.admin.api.log;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
import com.xxl.job.admin.api.log.dto.JobLogPageReqDTO;
import com.xxl.job.admin.api.log.dto.JobLogRespDTO;
import com.xxl.job.admin.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.validation.Valid;
/**
* @Description 调度任务日志Api接口
*/
@FeignClient(name = ApiConstants.NAME, path = "/xxl-job-admin")
@Tag(name = "RPC 服务 - 任务日志管理")
public interface JobLogApi {
String PREFIX = ApiConstants.PREFIX + "/log";
@GetMapping(PREFIX + "/page")
@Operation(summary = "获得所有任务列表")
public CommonResult<PageResult<JobLogRespDTO>> getPage(@Valid JobLogPageReqDTO jobLogPageReqDTO);
}

View File

@ -0,0 +1,29 @@
package com.xxl.job.admin.api.log.dto;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.Date;
@Schema(description = "RPC 服务 - 任务日志 Request DTO")
@Data
public class JobLogPageReqDTO extends PageParam {
@NotNull(message = "任务编号不能为空")
@Schema(description = "任务编号")
private Integer jobId;
@Schema(description = "处理器的名字")
private String handlerName;
@Schema(description = "开始执行时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date beginTime;
@Schema(description = "结束执行时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
@Schema(description = "任务状态")
private Integer status;
}

View File

@ -0,0 +1,42 @@
package com.xxl.job.admin.api.log.dto;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
@Schema(description = "RPC 服务 - 任务日志 Response DTO")
@Data
@ExcelIgnoreUnannotated
public class JobLogRespDTO {
@Schema(description = "日志编号")
@ExcelProperty("日志编号")
private Integer id;
@Schema(description = "任务编号")
@ExcelProperty("任务编号")
private Integer jobId;
@Schema(description = "处理器的名字")
@ExcelProperty("处理器的名字")
private String handlerName;
@Schema(description = "处理器的参数")
@ExcelProperty("处理器的参数")
private String handlerParam;
@Schema(description = "第几次执行")
@ExcelProperty("第几次执行")
private Integer executeIndex;
@Schema(description = "开始执行时间")
@ExcelProperty("开始执行时间")
private Date beginTime;
@Schema(description = "结束执行时间")
@ExcelProperty("结束执行时间")
private Date endTime;
@Schema(description = "执行时长")
@ExcelProperty("执行时长")
private Integer duration;
@Schema(description = "任务状态")
@ExcelProperty("任务状态")
private Integer status;
}

View File

@ -2,7 +2,9 @@ package com.xxl.job.admin.api.info;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.xxl.job.admin.api.info.dto.JobInfoDetailRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO; import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoSaveReqDTO;
import com.xxl.job.admin.service.XxlJobService; import com.xxl.job.admin.service.XxlJobService;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -14,7 +16,7 @@ import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
/** /**
* @Description TODO * @Description 调度任务信息Api实现类
*/ */
@RestController // 提供 RESTful API 接口 Feign 调用 @RestController // 提供 RESTful API 接口 Feign 调用
@Validated @Validated
@ -26,4 +28,40 @@ public class JobInfoApiImpl implements JobInfoApi{
public CommonResult<PageResult<JobInfoRespDTO>> getPage(Integer pageNo, Integer pageSize, String name, Integer status, String handlerName) { public CommonResult<PageResult<JobInfoRespDTO>> getPage(Integer pageNo, Integer pageSize, String name, Integer status, String handlerName) {
return success(xxlJobService.apiPage(pageNo, pageSize, name, status, handlerName)); return success(xxlJobService.apiPage(pageNo, pageSize, name, status, handlerName));
} }
@Override
public CommonResult<JobInfoDetailRespDTO> get(Integer id) {
return success(xxlJobService.apiGet(id));
}
@Override
public CommonResult<Boolean> create(JobInfoSaveReqDTO jobInfoSaveReqDTO) {
return xxlJobService.apiCreate(jobInfoSaveReqDTO);
}
@Override
public CommonResult<Boolean> update(JobInfoSaveReqDTO jobInfoSaveReqDTO) {
return xxlJobService.apiUpdate(jobInfoSaveReqDTO);
}
@Override
public CommonResult<Boolean> delete(Integer id) {
return success(xxlJobService.apiDelete(id));
}
@Override
public CommonResult<Boolean> updateStatus(Integer id, Integer status) {
return success(xxlJobService.apiUpdateStatus(id, status));
}
@Override
public CommonResult<Object> trigger(Integer id) {
return xxlJobService.apiTrigger(id);
}
@Override
public CommonResult<List<String>> getNextTimes(Integer id) {
return xxlJobService.apiGetNextTimes(id);
}
} }

View File

@ -0,0 +1,56 @@
package com.xxl.job.admin.api.log;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
import com.xxl.job.admin.api.log.dto.JobLogPageReqDTO;
import com.xxl.job.admin.api.log.dto.JobLogRespDTO;
import com.xxl.job.admin.controller.JobInfoController;
import com.xxl.job.admin.controller.JobLogController;
import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.admin.dao.XxlJobGroupDao;
import com.xxl.job.admin.dao.XxlJobInfoDao;
import com.xxl.job.admin.dao.XxlJobLogDao;
import com.xxl.job.core.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description 调度任务日志Api实现类
*/
@RestController // 提供 RESTful API 接口 Feign 调用
@Validated
public class JobLogApiImpl implements JobLogApi {
private static Logger logger = LoggerFactory.getLogger(JobLogController.class);
@Resource
private XxlJobGroupDao xxlJobGroupDao;
@Resource
public XxlJobInfoDao xxlJobInfoDao;
@Resource
public XxlJobLogDao xxlJobLogDao;
@Override
public CommonResult<PageResult<JobLogRespDTO>> getPage(JobLogPageReqDTO jobLogPageReqDTO) {
// 设置默认组为3
int jobGroup = 3;
int status = jobLogPageReqDTO.getStatus() == null ? -1 : jobLogPageReqDTO.getStatus();
// page query
List<JobLogRespDTO> list = xxlJobLogDao.apiPageList(jobLogPageReqDTO.getPageNo(), jobLogPageReqDTO.getPageSize(), jobGroup, jobLogPageReqDTO.getJobId(), jobLogPageReqDTO.getBeginTime(), jobLogPageReqDTO.getEndTime(), status);
int list_count = xxlJobLogDao.pageListCount(jobLogPageReqDTO.getPageNo(), jobLogPageReqDTO.getPageSize(), jobGroup, jobLogPageReqDTO.getJobId(), jobLogPageReqDTO.getBeginTime(), jobLogPageReqDTO.getEndTime(), status);
// package result
PageResult<JobLogRespDTO> pageResult = new PageResult<>();
pageResult.setTotal((long) list_count);
pageResult.setList(list);
return CommonResult.success(pageResult);
}
}

View File

@ -1,7 +1,9 @@
package com.xxl.job.admin.dao; package com.xxl.job.admin.dao;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import com.xxl.job.admin.api.info.dto.JobInfoDetailRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO; import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoSaveReqDTO;
import com.xxl.job.admin.core.model.XxlJobInfo; import com.xxl.job.admin.core.model.XxlJobInfo;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -51,4 +53,7 @@ public interface XxlJobInfoDao extends BaseMapperX<XxlJobInfo> {
List<JobInfoRespDTO> apiPage(@Param("pageNo") Integer pageNo, @Param("pageSize") Integer pageSize, @Param("name") String name, @Param("status") Integer status, @Param("handlerName") String handlerName); List<JobInfoRespDTO> apiPage(@Param("pageNo") Integer pageNo, @Param("pageSize") Integer pageSize, @Param("name") String name, @Param("status") Integer status, @Param("handlerName") String handlerName);
Long apiPageCount(@Param("name") String name, @Param("status") Integer status, @Param("handlerName") String handlerName); Long apiPageCount(@Param("name") String name, @Param("status") Integer status, @Param("handlerName") String handlerName);
JobInfoDetailRespDTO apiGet(@Param("id") Integer id);
} }

View File

@ -1,5 +1,6 @@
package com.xxl.job.admin.dao; package com.xxl.job.admin.dao;
import com.xxl.job.admin.api.log.dto.JobLogRespDTO;
import com.xxl.job.admin.core.model.XxlJobLog; import com.xxl.job.admin.core.model.XxlJobLog;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -23,6 +24,13 @@ public interface XxlJobLogDao {
@Param("triggerTimeStart") Date triggerTimeStart, @Param("triggerTimeStart") Date triggerTimeStart,
@Param("triggerTimeEnd") Date triggerTimeEnd, @Param("triggerTimeEnd") Date triggerTimeEnd,
@Param("logStatus") int logStatus); @Param("logStatus") int logStatus);
public List<JobLogRespDTO> apiPageList(@Param("offset") int offset,
@Param("pagesize") int pagesize,
@Param("jobGroup") int jobGroup,
@Param("jobId") int jobId,
@Param("triggerTimeStart") Date triggerTimeStart,
@Param("triggerTimeEnd") Date triggerTimeEnd,
@Param("logStatus") Integer logStatus);
public int pageListCount(@Param("offset") int offset, public int pageListCount(@Param("offset") int offset,
@Param("pagesize") int pagesize, @Param("pagesize") int pagesize,
@Param("jobGroup") int jobGroup, @Param("jobGroup") int jobGroup,

View File

@ -1,7 +1,7 @@
package com.xxl.job.admin.framework.security.config; package com.xxl.job.admin.framework.security.config;
import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
import cn.iocoder.yudao.module.system.enums.ApiConstants; import com.xxl.job.admin.enums.ApiConstants;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@ -29,6 +29,8 @@ public class SecurityConfiguration {
.antMatchers("/actuator/**").anonymous(); .antMatchers("/actuator/**").anonymous();
// RPC 服务的安全配置 // RPC 服务的安全配置
registry.antMatchers(ApiConstants.PREFIX + "/**").permitAll(); registry.antMatchers(ApiConstants.PREFIX + "/**").permitAll();
// 放行所有后台原本请求和rpc接口
registry.antMatchers("/**").permitAll();
} }
}; };

View File

@ -83,24 +83,33 @@ public class LoginService {
* @return * @return
*/ */
public XxlJobUser ifLogin(HttpServletRequest request, HttpServletResponse response){ public XxlJobUser ifLogin(HttpServletRequest request, HttpServletResponse response){
String cookieToken = CookieUtil.getValue(request, LOGIN_IDENTITY_KEY);
if (cookieToken != null) { // String cookieToken = CookieUtil.getValue(request, LOGIN_IDENTITY_KEY);
XxlJobUser cookieUser = null; // if (cookieToken != null) {
try { // XxlJobUser cookieUser = null;
cookieUser = parseToken(cookieToken); // try {
} catch (Exception e) { // cookieUser = parseToken(cookieToken);
logout(request, response); // } catch (Exception e) {
} // logout(request, response);
if (cookieUser != null) { // }
XxlJobUser dbUser = xxlJobUserDao.loadByUserName(cookieUser.getUsername()); // if (cookieUser != null) {
if (dbUser != null) { // XxlJobUser dbUser = xxlJobUserDao.loadByUserName(cookieUser.getUsername());
if (cookieUser.getPassword().equals(dbUser.getPassword())) { // if (dbUser != null) {
return dbUser; // if (cookieUser.getPassword().equals(dbUser.getPassword())) {
} // return dbUser;
} // }
} // }
} // }
return null; // }
// return null;
// TODO 暂时放行cookie
XxlJobUser test = new XxlJobUser();
test.setId(1);
test.setUsername("admin");
test.setPassword("e10adc3949ba59abbe56e057f20f883e");
test.setRole(1);
test.setPermission(null);
return test;
} }
} }

View File

@ -3,7 +3,9 @@ package com.xxl.job.admin.service;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.xxl.job.admin.api.info.dto.JobInfoDetailRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO; import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoSaveReqDTO;
import com.xxl.job.admin.core.model.XxlJobInfo; import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobUser; import com.xxl.job.admin.core.model.XxlJobUser;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
@ -109,4 +111,54 @@ public interface XxlJobService {
* @return * @return
*/ */
PageResult<JobInfoRespDTO> apiPage(Integer pageNo, Integer pageSize, String name, Integer status, String handlerName); PageResult<JobInfoRespDTO> apiPage(Integer pageNo, Integer pageSize, String name, Integer status, String handlerName);
/**
* api接口用于查看任务详情
* @param id
* @return com.xxl.job.admin.api.info.dto.JobInfoDetailRespDTO
*/
JobInfoDetailRespDTO apiGet(Integer id);
/**
* api接口用于创建任务
* @param jobInfoSaveReqDTO
* @return
*/
CommonResult<Boolean> apiCreate(JobInfoSaveReqDTO jobInfoSaveReqDTO);
/**
* api接口用于修改任务
* @param jobInfoSaveReqDTO
* @return
*/
CommonResult<Boolean> apiUpdate(JobInfoSaveReqDTO jobInfoSaveReqDTO);
/**
* api接口用于删除任务
* @param id
* @return
*/
Boolean apiDelete(Integer id);
/**
* api接口用于任务状态修改
* @param id
* @param status
* @return
*/
Boolean apiUpdateStatus(Integer id, Integer status);
/**
* api接口用于任务立即执行一次
* @param id
* @return
*/
CommonResult<Object> apiTrigger(Integer id);
/**
* api接口用于获取下N次执行时间
* @param id
* @return cn.iocoder.yudao.framework.common.pojo.CommonResult<java.util.List<java.lang.String>>
*/
CommonResult<List<String>> apiGetNextTimes(Integer id);
} }

View File

@ -1,7 +1,10 @@
package com.xxl.job.admin.service.impl; package com.xxl.job.admin.service.impl;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.xxl.job.admin.api.info.dto.JobInfoDetailRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO; import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoSaveReqDTO;
import com.xxl.job.admin.core.cron.CronExpression; import com.xxl.job.admin.core.cron.CronExpression;
import com.xxl.job.admin.core.model.XxlJobGroup; import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo; import com.xxl.job.admin.core.model.XxlJobInfo;
@ -28,6 +31,9 @@ import javax.annotation.Resource;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.*; import java.util.*;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
/** /**
* core job action for xxl-job * core job action for xxl-job
* @author xuxueli 2016-5-28 15:30:33 * @author xuxueli 2016-5-28 15:30:33
@ -481,4 +487,126 @@ public class XxlJobServiceImpl implements XxlJobService {
return pageResult; return pageResult;
} }
@Override
public JobInfoDetailRespDTO apiGet(Integer id) {
return xxlJobInfoDao.apiGet(id);
}
@Override
public CommonResult<Boolean> apiCreate(JobInfoSaveReqDTO jobInfoSaveReqDTO) {
XxlJobInfo xxlJobInfo = new XxlJobInfo();
xxlJobInfo.setJobDesc(jobInfoSaveReqDTO.getName());
xxlJobInfo.setExecutorHandler(jobInfoSaveReqDTO.getHandlerName());
xxlJobInfo.setExecutorParam(jobInfoSaveReqDTO.getHandlerParam());
xxlJobInfo.setScheduleConf(jobInfoSaveReqDTO.getCronExpression());
if (jobInfoSaveReqDTO.getRetryCount() != null){
xxlJobInfo.setExecutorFailRetryCount(jobInfoSaveReqDTO.getRetryCount());
}
if (jobInfoSaveReqDTO.getMonitorTimeout() != null){
xxlJobInfo.setExecutorTimeout(jobInfoSaveReqDTO.getMonitorTimeout());
}
// 设置默认参数 默认为第3组
xxlJobInfo.setJobGroup(3);
xxlJobInfo.setAuthor("ludu");
xxlJobInfo.setScheduleType("CRON");
xxlJobInfo.setGlueType("BEAN");
xxlJobInfo.setExecutorRouteStrategy("FIRST");
xxlJobInfo.setMisfireStrategy("DO_NOTHING");
xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");
xxlJobInfo.setGlueRemark("GLUE代码初始化");
ReturnT<String> add = add(xxlJobInfo);
if (add.getCode() == ReturnT.FAIL_CODE){
return error(add.getCode(), add.getMsg());
}
return success(true);
}
@Override
public CommonResult<Boolean> apiUpdate(JobInfoSaveReqDTO jobInfoSaveReqDTO) {
XxlJobInfo xxlJobInfo = new XxlJobInfo();
xxlJobInfo.setId(jobInfoSaveReqDTO.getId());
xxlJobInfo.setJobDesc(jobInfoSaveReqDTO.getName());
xxlJobInfo.setExecutorHandler(jobInfoSaveReqDTO.getHandlerName());
xxlJobInfo.setExecutorParam(jobInfoSaveReqDTO.getHandlerParam());
xxlJobInfo.setScheduleConf(jobInfoSaveReqDTO.getCronExpression());
if (jobInfoSaveReqDTO.getRetryCount() != null){
xxlJobInfo.setExecutorFailRetryCount(jobInfoSaveReqDTO.getRetryCount());
}
if (jobInfoSaveReqDTO.getMonitorTimeout() != null){
xxlJobInfo.setExecutorTimeout(jobInfoSaveReqDTO.getMonitorTimeout());
}
// 设置默认参数 默认为第3组
xxlJobInfo.setJobGroup(3);
xxlJobInfo.setAuthor("ludu");
xxlJobInfo.setScheduleType("CRON");
xxlJobInfo.setGlueType("BEAN");
xxlJobInfo.setExecutorRouteStrategy("FIRST");
xxlJobInfo.setMisfireStrategy("DO_NOTHING");
xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");
xxlJobInfo.setGlueRemark("GLUE代码初始化");
ReturnT<String> update = update(xxlJobInfo);
if (update.getCode() == ReturnT.FAIL_CODE){
return error(update.getCode(), update.getMsg());
}
return success(true);
}
@Override
public Boolean apiDelete(Integer id) {
remove(id);
return true;
}
@Override
public Boolean apiUpdateStatus(Integer id, Integer status) {
if (status == null || id == null){
return false;
}
if (status == 1){
start(id);
}else if (status == 2){
stop(id);
}else{
return false;
}
return true;
}
@Override
public CommonResult<Object> apiTrigger(Integer id) {
XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
if (xxlJobInfo == null) {
return error(ReturnT.FAIL.getCode(), I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
}
JobTriggerPoolHelper.trigger(id, TriggerTypeEnum.MANUAL, -1, null, "", "");
return success(true);
}
@Override
public CommonResult<List<String>> apiGetNextTimes(Integer id) {
XxlJobInfo paramXxlJobInfo = new XxlJobInfo();
paramXxlJobInfo.setScheduleType("CRON");
paramXxlJobInfo.setScheduleConf(apiGet(id).getCronExpression());
List<String> result = new ArrayList<>();
try {
Date lastTime = new Date();
for (int i = 0; i < 5; i++) {
lastTime = JobScheduleHelper.generateNextValidTime(paramXxlJobInfo, lastTime);
if (lastTime != null) {
result.add(DateUtil.formatDateTime(lastTime));
} else {
break;
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
return error(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) + e.getMessage());
}
return success(result);
}
} }

View File

@ -31,12 +31,11 @@ spring:
### actuator ### actuator
management: management:
server:
servlet:
context-path: /actuator
health: health:
mail: mail:
enabled: false enabled: false
server:
base-path: /actuator

View File

@ -3,43 +3,46 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxl.job.admin.dao.XxlJobInfoDao"> <mapper namespace="com.xxl.job.admin.dao.XxlJobInfoDao">
<resultMap id="XxlJobInfo" type="com.xxl.job.admin.core.model.XxlJobInfo" > <resultMap id="XxlJobInfo" type="com.xxl.job.admin.core.model.XxlJobInfo">
<result column="id" property="id" /> <result column="id" property="id"/>
<result column="job_group" property="jobGroup" /> <result column="job_group" property="jobGroup"/>
<result column="job_desc" property="jobDesc" /> <result column="job_desc" property="jobDesc"/>
<result column="add_time" property="addTime" /> <result column="add_time" property="addTime"/>
<result column="update_time" property="updateTime" /> <result column="update_time" property="updateTime"/>
<result column="author" property="author" /> <result column="author" property="author"/>
<result column="alarm_email" property="alarmEmail" /> <result column="alarm_email" property="alarmEmail"/>
<result column="schedule_type" property="scheduleType" /> <result column="schedule_type" property="scheduleType"/>
<result column="schedule_conf" property="scheduleConf" /> <result column="schedule_conf" property="scheduleConf"/>
<result column="misfire_strategy" property="misfireStrategy" /> <result column="misfire_strategy" property="misfireStrategy"/>
<result column="executor_route_strategy" property="executorRouteStrategy" /> <result column="executor_route_strategy" property="executorRouteStrategy"/>
<result column="executor_handler" property="executorHandler" /> <result column="executor_handler" property="executorHandler"/>
<result column="executor_param" property="executorParam" /> <result column="executor_param" property="executorParam"/>
<result column="executor_block_strategy" property="executorBlockStrategy" /> <result column="executor_block_strategy" property="executorBlockStrategy"/>
<result column="executor_timeout" property="executorTimeout" /> <result column="executor_timeout" property="executorTimeout"/>
<result column="executor_fail_retry_count" property="executorFailRetryCount" /> <result column="executor_fail_retry_count" property="executorFailRetryCount"/>
<result column="glue_type" property="glueType" /> <result column="glue_type" property="glueType"/>
<result column="glue_source" property="glueSource" /> <result column="glue_source" property="glueSource"/>
<result column="glue_remark" property="glueRemark" /> <result column="glue_remark" property="glueRemark"/>
<result column="glue_updatetime" property="glueUpdatetime" /> <result column="glue_updatetime" property="glueUpdatetime"/>
<result column="child_jobid" property="childJobId" /> <result column="child_jobid" property="childJobId"/>
<result column="trigger_status" property="triggerStatus" /> <result column="trigger_status" property="triggerStatus"/>
<result column="trigger_last_time" property="triggerLastTime" /> <result column="trigger_last_time" property="triggerLastTime"/>
<result column="trigger_next_time" property="triggerNextTime" /> <result column="trigger_next_time" property="triggerNextTime"/>
</resultMap> </resultMap>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
t.id, t
.
id
,
t.job_group, t.job_group,
t.job_desc, t.job_desc,
t.add_time, t.add_time,
@ -66,9 +69,10 @@
</sql> </sql>
<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo"> <select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
SELECT <include refid="Base_Column_List" /> SELECT
<include refid="Base_Column_List"/>
FROM xxl_job_info AS t FROM xxl_job_info AS t
<trim prefix="WHERE" prefixOverrides="AND | OR" > <trim prefix="WHERE" prefixOverrides="AND | OR">
<if test="jobGroup gt 0"> <if test="jobGroup gt 0">
AND t.job_group = #{jobGroup} AND t.job_group = #{jobGroup}
</if> </if>
@ -92,7 +96,7 @@
<select id="pageListCount" parameterType="java.util.HashMap" resultType="int"> <select id="pageListCount" parameterType="java.util.HashMap" resultType="int">
SELECT count(1) SELECT count(1)
FROM xxl_job_info AS t FROM xxl_job_info AS t
<trim prefix="WHERE" prefixOverrides="AND | OR" > <trim prefix="WHERE" prefixOverrides="AND | OR">
<if test="jobGroup gt 0"> <if test="jobGroup gt 0">
AND t.job_group = #{jobGroup} AND t.job_group = #{jobGroup}
</if> </if>
@ -111,7 +115,7 @@
</trim> </trim>
</select> </select>
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" useGeneratedKeys="true" keyProperty="id" > <insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" useGeneratedKeys="true" keyProperty="id">
INSERT INTO xxl_job_info ( INSERT INTO xxl_job_info (
job_group, job_group,
job_desc, job_desc,
@ -168,15 +172,15 @@
</insert> </insert>
<select id="loadById" parameterType="java.util.HashMap" resultMap="XxlJobInfo"> <select id="loadById" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
SELECT <include refid="Base_Column_List" /> SELECT
<include refid="Base_Column_List"/>
FROM xxl_job_info AS t FROM xxl_job_info AS t
WHERE t.id = #{id} WHERE t.id = #{id}
</select> </select>
<update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" > <update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobInfo">
UPDATE xxl_job_info UPDATE xxl_job_info
SET SET job_group = #{jobGroup},
job_group = #{jobGroup},
job_desc = #{jobDesc}, job_desc = #{jobDesc},
update_time = #{updateTime}, update_time = #{updateTime},
author = #{author}, author = #{author},
@ -208,7 +212,8 @@
</delete> </delete>
<select id="getJobsByGroup" parameterType="java.util.HashMap" resultMap="XxlJobInfo"> <select id="getJobsByGroup" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
SELECT <include refid="Base_Column_List" /> SELECT
<include refid="Base_Column_List"/>
FROM xxl_job_info AS t FROM xxl_job_info AS t
WHERE t.job_group = #{jobGroup} WHERE t.job_group = #{jobGroup}
</select> </select>
@ -220,7 +225,8 @@
<select id="scheduleJobQuery" parameterType="java.util.HashMap" resultMap="XxlJobInfo"> <select id="scheduleJobQuery" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
SELECT <include refid="Base_Column_List" /> SELECT
<include refid="Base_Column_List"/>
FROM xxl_job_info AS t FROM xxl_job_info AS t
WHERE t.trigger_status = 1 WHERE t.trigger_status = 1
and t.trigger_next_time <![CDATA[ <= ]]> #{maxNextTime} and t.trigger_next_time <![CDATA[ <= ]]> #{maxNextTime}
@ -229,27 +235,36 @@
</select> </select>
<update id="scheduleUpdate" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" > <update id="scheduleUpdate" parameterType="com.xxl.job.admin.core.model.XxlJobInfo">
UPDATE xxl_job_info UPDATE xxl_job_info
SET SET trigger_last_time = #{triggerLastTime},
trigger_last_time = #{triggerLastTime},
trigger_next_time = #{triggerNextTime}, trigger_next_time = #{triggerNextTime},
trigger_status = #{triggerStatus} trigger_status = #{triggerStatus}
WHERE id = #{id} WHERE id = #{id}
</update> </update>
<!-- 以下是自定义语句 -->
<sql id="job_group_default">
3
</sql>
<resultMap id="JobInfoRespDTOResultMap" type="com.xxl.job.admin.api.info.dto.JobInfoRespDTO"> <resultMap id="JobInfoRespDTOResultMap" type="com.xxl.job.admin.api.info.dto.JobInfoRespDTO">
<id property="id" column="id" /> <id property="id" column="id"/>
<result property="name" column="job_desc" /> <result property="name" column="job_desc"/>
<result property="status" column="trigger_status" /> <result property="status" column="trigger_status"/>
<result property="handlerName" column="executor_handler" /> <result property="handlerName" column="executor_handler"/>
<result property="handlerParam" column="executor_param" /> <result property="handlerParam" column="executor_param"/>
<result property="cronExpression" column="schedule_conf" /> <result property="cronExpression" column="schedule_conf"/>
</resultMap> </resultMap>
<select id="apiPage" resultMap="JobInfoRespDTOResultMap"> <select id="apiPage" resultMap="JobInfoRespDTOResultMap">
SELECT id, job_desc, CASE WHEN trigger_status = 0 THEN 2 ELSE trigger_status END AS trigger_status, executor_handler, executor_param, schedule_conf SELECT id, job_desc, CASE WHEN trigger_status = 0 THEN 2 ELSE trigger_status END AS trigger_status,
executor_handler, executor_param, schedule_conf
FROM xxl_job_info FROM xxl_job_info
<where> <where>
AND job_group =
<include refid="job_group_default"/>
<if test="name != null and name != ''"> <if test="name != null and name != ''">
AND job_desc LIKE concat('%', #{name}, '%') AND job_desc LIKE concat('%', #{name}, '%')
</if> </if>
@ -260,13 +275,17 @@
AND executor_handler LIKE concat('%', #{handlerName}, '%') AND executor_handler LIKE concat('%', #{handlerName}, '%')
</if> </if>
</where> </where>
<if test="pageSize > 0">
LIMIT #{pageSize} OFFSET ${(pageNo - 1) * pageSize} LIMIT #{pageSize} OFFSET ${(pageNo - 1) * pageSize}
</if>
</select> </select>
<select id="apiPageCount" resultType="java.lang.Long"> <select id="apiPageCount" resultType="java.lang.Long">
SELECT count(*) SELECT count(*)
FROM xxl_job_info FROM xxl_job_info
<where> <where>
AND job_group =
<include refid="job_group_default"/>
<if test="name != null and name != ''"> <if test="name != null and name != ''">
AND job_desc LIKE concat('%', #{name}, '%') AND job_desc LIKE concat('%', #{name}, '%')
</if> </if>
@ -278,5 +297,23 @@
</if> </if>
</where> </where>
</select> </select>
<resultMap id="JobInfoDetailRespDTOResultMap" type="com.xxl.job.admin.api.info.dto.JobInfoDetailRespDTO">
<id property="id" column="id"/>
<result property="name" column="job_desc"/>
<result property="handlerName" column="executor_handler"/>
<result property="handlerParam" column="executor_param"/>
<result property="cronExpression" column="schedule_conf"/>
<result property="retryCount" column="executor_fail_retry_count"/>
<result property="monitorTimeout" column="executor_timeout"/>
</resultMap>
<select id="apiGet" resultMap="JobInfoDetailRespDTOResultMap">
SELECT id, job_desc, executor_handler, executor_param, schedule_conf, executor_fail_retry_count,
executor_timeout
FROM xxl_job_info
WHERE id = #{id}
AND job_group =
<include refid="job_group_default"/>
</select>
</mapper> </mapper>

View File

@ -78,6 +78,51 @@
LIMIT #{offset}, #{pagesize} LIMIT #{offset}, #{pagesize}
</select> </select>
<resultMap id="ApiXxlJobLog" type="com.xxl.job.admin.api.log.dto.JobLogRespDTO">
<id column="id" property="id"/>
<result column="job_id" property="jobId"/>
<result column="executor_handler" property="handlerName"/>
<result column="executor_param" property="handlerParam"/>
<result column="index" property="executeIndex"/>
<result column="trigger_time" property="beginTime"/>
<result column="handle_time" property="endTime"/>
<result column="duration" property="duration"/>
<result column="alarm_status" property="status"/>
</resultMap>
<select id="apiPageList" resultMap="ApiXxlJobLog">
SELECT <include refid="Base_Column_List" />, ROW_NUMBER() OVER (ORDER BY t.trigger_time) AS 'index', (t.handle_time -t.trigger_time) AS 'duration'
FROM xxl_job_log AS t
<trim prefix="WHERE" prefixOverrides="AND | OR" >
<if test="jobId==0 and jobGroup gt 0">
AND t.job_group = #{jobGroup}
</if>
<if test="jobId gt 0">
AND t.job_id = #{jobId}
</if>
<if test="triggerTimeStart != null">
AND t.trigger_time <![CDATA[ >= ]]> #{triggerTimeStart}
</if>
<if test="triggerTimeEnd != null">
AND t.trigger_time <![CDATA[ <= ]]> #{triggerTimeEnd}
</if>
<if test="logStatus == 1" >
AND t.handle_code = 200
</if>
<if test="logStatus == 2" >
AND (
t.trigger_code NOT IN (0, 200) OR
t.handle_code NOT IN (0, 200)
)
</if>
<if test="logStatus == 3" >
AND t.trigger_code = 200
AND t.handle_code = 0
</if>
</trim>
ORDER BY t.trigger_time DESC
LIMIT #{offset}, #{pagesize}
</select>
<select id="pageListCount" resultType="int"> <select id="pageListCount" resultType="int">
SELECT count(1) SELECT count(1)
FROM xxl_job_log AS t FROM xxl_job_log AS t

View File

@ -108,7 +108,7 @@ yudao:
captcha: captcha:
enable: true # 验证码的开关,默认为 true enable: true # 验证码的开关,默认为 true
tenant: # 多租户相关配置项 tenant: # 多租户相关配置项
enable: true enable: false
ignore-urls: ignore-urls:
ignore-tables: ignore-tables:

View File

@ -1,7 +1,8 @@
package cn.iocoder.yudao.module.ticket.framework.security.config; package cn.iocoder.yudao.module.ticket.framework.security.config;
import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
import cn.iocoder.yudao.module.system.enums.ApiConstants;
import cn.iocoder.yudao.module.ticket.enums.ApiConstants;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;

View File

@ -124,33 +124,28 @@ public class YudaoWebSecurityConfigurerAdapter {
// 获得 @PermitAll 带来的 URL 列表免登录 // 获得 @PermitAll 带来的 URL 列表免登录
Multimap<HttpMethod, String> permitAllUrls = getPermitAllUrlsFromAnnotations(); Multimap<HttpMethod, String> permitAllUrls = getPermitAllUrlsFromAnnotations();
// 设置每个请求的权限 // 设置每个请求的权限
// httpSecurity httpSecurity
// // 全局共享规则 // 全局共享规则
// .authorizeRequests() .authorizeRequests()
// // 1.1 静态资源可匿名访问 // 1.1 静态资源可匿名访问
// .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
// // 1.2 设置 @PermitAll 无需认证 // 1.2 设置 @PermitAll 无需认证
// .antMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll() .antMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll()
// .antMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll() .antMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll()
// .antMatchers(HttpMethod.PUT, permitAllUrls.get(HttpMethod.PUT).toArray(new String[0])).permitAll() .antMatchers(HttpMethod.PUT, permitAllUrls.get(HttpMethod.PUT).toArray(new String[0])).permitAll()
// .antMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll() .antMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll()
// // 1.3 基于 yudao.security.permit-all-urls 无需认证 // 1.3 基于 yudao.security.permit-all-urls 无需认证
// .antMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll() .antMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll()
// // 1.4 设置 App API 无需认证 // 1.4 设置 App API 无需认证
// .antMatchers(buildAppApi("/**")).permitAll() .antMatchers(buildAppApi("/**")).permitAll()
// // 1.5 验证码captcha 允许匿名访问 // 1.5 验证码captcha 允许匿名访问
// .antMatchers("/captcha/get", "/captcha/check").permitAll() .antMatchers("/captcha/get", "/captcha/check").permitAll()
// // TODO 未解决对xxl-job的默认管理端放行 // 每个项目的自定义规则
// .antMatchers("/**/xxl-job-admin/**").permitAll() .and().authorizeRequests(registry -> // 下面循环设置自定义规则
// // 每个项目的自定义规则 authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(registry)))
// .and().authorizeRequests(registry -> // 下面循环设置自定义规则 // 兜底规则必须认证
// authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(registry))) .authorizeRequests()
// // 兜底规则必须认证 .anyRequest().authenticated();
// .authorizeRequests()
// .anyRequest().authenticated();
// TODO 暂时先放行用于调度中心后台查看
httpSecurity.authorizeRequests().anyRequest().permitAll();
// 添加 Token Filter // 添加 Token Filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build(); return httpSecurity.build();

View File

@ -21,12 +21,12 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>cn.iocoder.cloud</groupId> <groupId>cn.iocoder.cloud</groupId>
<artifactId>ludu-job-admin-api</artifactId> <artifactId>ludu-job-core</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cn.iocoder.cloud</groupId> <groupId>cn.iocoder.cloud</groupId>
<artifactId>ludu-job-core</artifactId> <artifactId>ludu-job-admin-api</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<!-- Spring Cloud 基础 --> <!-- Spring Cloud 基础 -->

View File

@ -1,28 +1,35 @@
package cn.iocoder.yudao.module.infra.controller.admin.job; package cn.iocoder.yudao.module.infra.controller.admin.job;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.http.HttpRequestUtil; import cn.iocoder.yudao.framework.common.util.http.HttpRequestUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import com.xxl.job.admin.api.info.JobInfoApi; import com.xxl.job.admin.api.info.JobInfoApi;
import com.xxl.job.admin.api.info.dto.JobInfoDetailRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoPageReqDTO;
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO; import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
import com.xxl.job.admin.api.info.dto.JobInfoSaveReqDTO;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.HttpHeaders; import org.apache.poi.ss.formula.functions.T;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
@Tag(name = "管理后台 - 定时任务") @Tag(name = "管理后台 - 定时任务")
@ -30,36 +37,76 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
@RequestMapping("/infra/job") @RequestMapping("/infra/job")
@Validated @Validated
public class JobController { public class JobController {
/*@Resource @Resource
private JobInfoApi jobInfoApi;*/ private JobInfoApi jobInfoApi;
// private static final String XXL_JOB_URL = "http://127.0.0.1:9090/xxl-job-admin"; @GetMapping("/page")
// private static final String USERNAME = "admin"; // TODO 可以直接读取配置中的账号和密码 @Operation(summary = "获得任务列表")
// private static final String PASSWORD = "123456";
// TODO 整体思路也可以使用网关拦截器
// 用于获取登录成功后返回的Cookie值
/*static{
Map<String, Object> params = new HashMap<>();
params.put("userName", USERNAME);
params.put("password", PASSWORD);
HttpHeaders headers = HttpRequestUtil.post(XXL_JOB_URL + "/login", params).getHeaders();
// 获取 Set-Cookie
List<String> setCookies = headers.get("Set-Cookie");
if (setCookies != null && !setCookies.isEmpty()) {
String cookie = setCookies.get(0);
// TODO 存入到一个常量中
System.out.println("this is cookie" + cookie);
}else{
// TODO 如果登录失败则不会有Set-Cookie的值抛出异常使用全局异常处理类
}
}*/
// TODO 出现未知错误 JobInfoApi 无法创建 bean
/*@GetMapping("/page")
@Operation(summary = "获得定时任务分页")
@PreAuthorize("@ss.hasPermission('infra:job:query')") @PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<PageResult<JobInfoRespDTO>> getJobPage(@RequestParam(value = "pageNo") Integer pageNo, @RequestParam(value = "pageSize") Integer pageSize, @RequestParam(required = false, value = "name") String name, @RequestParam(required = false, value = "status") Integer status, @RequestParam(required = false, value = "handlerName") String handlerName) { public CommonResult<PageResult<JobInfoRespDTO>> getJobPage(@RequestParam(value = "pageNo") Integer pageNo, @RequestParam(value = "pageSize") Integer pageSize, @RequestParam(required = false, value = "name") String name, @RequestParam(required = false, value = "status") Integer status, @RequestParam(required = false, value = "handlerName") String handlerName) {
return jobInfoApi.getPage(pageNo, pageSize, name, status, handlerName); return jobInfoApi.getPage(pageNo, pageSize, name, status, handlerName);
}*/ }
@GetMapping("/get")
@Operation(summary = "获得任务详情")
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<JobInfoDetailRespDTO> get(@RequestParam("id") Integer id){
return jobInfoApi.get(id);
}
@PostMapping("/create")
@Operation(summary = "新增任务")
@PreAuthorize("@ss.hasPermission('infra:job:create')")
public CommonResult<Boolean> create(@RequestBody JobInfoSaveReqDTO jobInfoSaveReqDTO){
return jobInfoApi.create(jobInfoSaveReqDTO);
}
@PutMapping("/update")
@Operation(summary = "修改任务")
@PreAuthorize("@ss.hasPermission('infra:job:update')")
public CommonResult<Boolean> update(@RequestBody JobInfoSaveReqDTO jobInfoSaveReqDTO){
return jobInfoApi.update(jobInfoSaveReqDTO);
}
@DeleteMapping("/delete")
@Operation(summary = "删除任务")
@PreAuthorize("@ss.hasPermission('infra:job:delete')")
public CommonResult<Boolean> delete(@RequestParam("id") Integer id){
return jobInfoApi.delete(id);
}
@GetMapping("/export-excel")
@Operation(summary = "导出任务 Excel")
@PreAuthorize("@ss.hasPermission('infra:job:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportJobInfoExcel(@Valid JobInfoPageReqDTO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<JobInfoRespDTO> list = jobInfoApi.getPage(pageReqVO.getPageNo(), pageReqVO.getPageSize(), pageReqVO.getName(), pageReqVO.getStatus(), pageReqVO.getHandlerName()).getData().getList();
// 导出 Excel
ExcelUtils.write(response, "任务调度.xls", "数据", JobInfoRespDTO.class,
list);
}
@PutMapping("/update-status")
@Operation(summary = "任务状态修改")
@PreAuthorize("@ss.hasPermission('infra:job:update')")
public CommonResult<Boolean> updateStatus(@RequestParam("id") Integer id, @RequestParam("status") Integer status){
return jobInfoApi.updateStatus(id, status);
}
@PutMapping("/trigger")
@Operation(summary = "任务立即执行一次")
@PreAuthorize("@ss.hasPermission('infra:job:update')")
public CommonResult<Object> trigger(@RequestParam("id") Integer id){
return jobInfoApi.trigger(id);
}
@GetMapping("/get_next_times")
@Operation(summary = "下n次执行时间")
@PreAuthorize("@ss.hasPermission('infra:job:query')")
public CommonResult<List<String>> getNextTimes(@RequestParam("id") Integer id){
return jobInfoApi.getNextTimes(id);
}
} }

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.infra.controller.admin.joblog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
import com.xxl.job.admin.api.log.JobLogApi;
import com.xxl.job.admin.api.log.dto.JobLogPageReqDTO;
import com.xxl.job.admin.api.log.dto.JobLogRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
@Tag(name = "管理后台 - 定时任务日志")
@RestController
@RequestMapping("/infra/job-log")
@Validated
public class JobLogController {
@Resource
private JobLogApi jobLogApi;
@RequestMapping("/page")
@Operation(summary = "获得任务日志列表")
public CommonResult<PageResult<JobLogRespDTO>> getPage(@Valid JobLogPageReqDTO jobLogPageReqDTO){
return jobLogApi.getPage(jobLogPageReqDTO);
}
}

View File

@ -2,10 +2,11 @@ package cn.iocoder.yudao.module.infra.framework.rpc.config;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import com.xxl.job.admin.api.info.JobInfoApi; import com.xxl.job.admin.api.info.JobInfoApi;
import com.xxl.job.admin.api.log.JobLogApi;
import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@EnableFeignClients(clients = {AdminUserApi.class, JobInfoApi.class}) @EnableFeignClients(clients = {AdminUserApi.class, JobInfoApi.class, JobLogApi.class})
public class RpcConfiguration { public class RpcConfiguration {
} }