手动触发更新逻辑,新增 stockInfo api 接口
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -255,11 +255,11 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||||
</dependency>
|
</dependency><!-- https://mvnrepository.com/artifact/com.github.yulichang/mybatis-plus-join-boot-starter -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.yulichang</groupId>
|
<groupId>com.github.yulichang</groupId>
|
||||||
<artifactId>mybatis-plus-join-boot-starter</artifactId>
|
<artifactId>mybatis-plus-join-boot-starter</artifactId>
|
||||||
<version>1.4.11</version>
|
<version>1.5.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package link.at17.mid.tushare.api.common;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.github.yulichang.query.MPJLambdaQueryWrapper;
|
||||||
|
|
||||||
|
import link.at17.mid.tushare.data.models.StockInfo;
|
||||||
|
import link.at17.mid.tushare.data.service.StockInfoService;
|
||||||
|
import link.at17.mid.tushare.enums.ListStatus;
|
||||||
|
import link.at17.mid.tushare.enums.StockMarket;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/common/stockInfo")
|
||||||
|
@Slf4j
|
||||||
|
public class StockInfoController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
StockInfoService stockInfoService;
|
||||||
|
|
||||||
|
@GetMapping("list")
|
||||||
|
private List<StockInfo> list(
|
||||||
|
@Param("listStatus") ListStatus listStatus,
|
||||||
|
@Param("stockMarket") StockMarket stockMarket) {
|
||||||
|
MPJLambdaQueryWrapper<StockInfo> ew = new MPJLambdaQueryWrapper<StockInfo>();
|
||||||
|
ew.setAlias("i");
|
||||||
|
ew.eq(Objects.nonNull(listStatus), StockInfo::getListStatus, listStatus);
|
||||||
|
ew.likeLeft(Objects.nonNull(stockMarket), StockInfo::getTsCode, stockMarket);
|
||||||
|
return stockInfoService.list(ew);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ public class StockCodeUtil {
|
|||||||
* @return
|
* @return
|
||||||
* @throws UnsupportedOperationException
|
* @throws UnsupportedOperationException
|
||||||
*/
|
*/
|
||||||
public static String toStandardCode(String code) throws UnsupportedOperationException {
|
public static String eastmoneyToTushare(String code) throws UnsupportedOperationException {
|
||||||
if (StringUtils.isEmpty(code)) {
|
if (StringUtils.isEmpty(code)) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,6 +178,14 @@ public class R<T> implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行带返回值的方法后返回,该返回值会作为 R 的 data。发生异常时,抛出 RException,包裹异常信息
|
||||||
|
* @param supplier 带返回值的方法如 R.judgeThrow(() -> service.getString())
|
||||||
|
* @return
|
||||||
|
* @see {@link #judgeThrow(ThrowingSupplier)}
|
||||||
|
* @see {@link #judge(ThrowingSupplier)}
|
||||||
|
* @see {@link #judge(ThrowingRunnable)}
|
||||||
|
*/
|
||||||
public static R<?> judge(ThrowingSupplier<?> supplier) {
|
public static R<?> judge(ThrowingSupplier<?> supplier) {
|
||||||
try {
|
try {
|
||||||
return R.ok(supplier.get());
|
return R.ok(supplier.get());
|
||||||
@@ -187,11 +195,48 @@ public class R<T> implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行无返回值的方法后返回,发生异常时,抛出 RException,包裹异常信息
|
||||||
|
* @param throwingRunnable void 方法如 R.judgeThrow(() -> service.someMethod())
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
* @see {@link #judgeThrow(ThrowingSupplier)}
|
||||||
|
* @see {@link #judge(ThrowingSupplier)}
|
||||||
|
* @see {@link #judge(ThrowingRunnable)}
|
||||||
|
*/
|
||||||
|
public static R<?> judge(ThrowingRunnable throwingRunnable) {
|
||||||
|
try {
|
||||||
|
throwingRunnable.run();
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw RException.badRequest(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行带返回值的方法后返回,该返回值会作为 R 的 data。发生异常时,抛出异常而非返回一个包含异常信息的 R
|
||||||
|
* @param supplier
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
public static R<?> judgeThrow(ThrowingSupplier<?> supplier) throws Exception {
|
public static R<?> judgeThrow(ThrowingSupplier<?> supplier) throws Exception {
|
||||||
return R.ok(supplier.get());
|
return R.ok(supplier.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行无返回值的方法后返回,发生异常时,抛出异常而非返回一个包含异常信息的 R
|
||||||
|
* @param throwingRunnable void 方法如 R.judgeThrow(() -> service.someMethod())
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
* @see {@link #judgeThrow(ThrowingSupplier)}
|
||||||
|
* @see {@link #judge(ThrowingSupplier)}
|
||||||
|
*/
|
||||||
|
public static R<?> judgeThrow(ThrowingRunnable throwingRunnable) throws Exception {
|
||||||
|
throwingRunnable.run();
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据布尔值判断返回<br>
|
* 根据布尔值判断返回<br>
|
||||||
* true 返回 R.ok(T okData)<br>
|
* true 返回 R.ok(T okData)<br>
|
||||||
@@ -219,4 +264,9 @@ public class R<T> implements Serializable {
|
|||||||
public static interface ThrowingSupplier<T> {
|
public static interface ThrowingSupplier<T> {
|
||||||
T get() throws Exception;
|
T get() throws Exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ThrowingRunnable {
|
||||||
|
void run() throws Exception;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.quartz.CronTrigger;
|
|||||||
import org.quartz.JobBuilder;
|
import org.quartz.JobBuilder;
|
||||||
import org.quartz.JobDataMap;
|
import org.quartz.JobDataMap;
|
||||||
import org.quartz.JobDetail;
|
import org.quartz.JobDetail;
|
||||||
|
import org.quartz.JobExecutionContext;
|
||||||
import org.quartz.JobKey;
|
import org.quartz.JobKey;
|
||||||
import org.quartz.Scheduler;
|
import org.quartz.Scheduler;
|
||||||
import org.quartz.SchedulerException;
|
import org.quartz.SchedulerException;
|
||||||
@@ -104,8 +105,8 @@ public class UpdatePlanService extends BaseServiceImpl<UpdatePlanDao, UpdatePlan
|
|||||||
* @throws SchedulerException
|
* @throws SchedulerException
|
||||||
*/
|
*/
|
||||||
public void rescheduleTask(@Validated UpdatePlan updatePlan) throws SchedulerException {
|
public void rescheduleTask(@Validated UpdatePlan updatePlan) throws SchedulerException {
|
||||||
JobKey jobKey = JobKey.jobKey(updatePlan.getId().toString(), JOB_GROUP_NAME);
|
JobKey jobKey = getJobKey(updatePlan);
|
||||||
TriggerKey triggerKey = TriggerKey.triggerKey(updatePlan.getId().toString(), JOB_GROUP_NAME);
|
TriggerKey triggerKey = getTriggerKey(updatePlan);
|
||||||
|
|
||||||
deleteTask(updatePlan.getId());
|
deleteTask(updatePlan.getId());
|
||||||
|
|
||||||
@@ -139,6 +140,33 @@ public class UpdatePlanService extends BaseServiceImpl<UpdatePlanDao, UpdatePlan
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 立即触发任务
|
||||||
|
* @param updatePlan
|
||||||
|
*/
|
||||||
|
public void triggerTask(@Valid UpdatePlan updatePlan) throws SchedulerException {
|
||||||
|
JobKey jobKey = getJobKey(updatePlan);
|
||||||
|
for (JobExecutionContext context : scheduler.getCurrentlyExecutingJobs()) {
|
||||||
|
if (context.getJobDetail().getKey().equals(jobKey)) {
|
||||||
|
throw new IllegalStateException("已有同名任务在运行中");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scheduler.getJobDetail(jobKey) == null) {
|
||||||
|
throw new SchedulerException("指定的任务不存在");
|
||||||
|
}
|
||||||
|
scheduler.triggerJob(jobKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void interruptTask(@Valid UpdatePlan updatePlan) throws SchedulerException {
|
||||||
|
JobKey jobKey = getJobKey(updatePlan);
|
||||||
|
for (JobExecutionContext context : scheduler.getCurrentlyExecutingJobs()) {
|
||||||
|
if (context.getJobDetail().getKey().equals(jobKey)) {
|
||||||
|
scheduler.interrupt(jobKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new SchedulerException("任务未在执行");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行方法
|
* 执行方法
|
||||||
* @param updatePlan
|
* @param updatePlan
|
||||||
@@ -159,4 +187,21 @@ public class UpdatePlanService extends BaseServiceImpl<UpdatePlanDao, UpdatePlan
|
|||||||
return list(new LambdaQueryWrapper<UpdatePlan>().orderByAsc(UpdatePlan::getId));
|
return list(new LambdaQueryWrapper<UpdatePlan>().orderByAsc(UpdatePlan::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 UpdatePlan 生成 JobKey
|
||||||
|
* @param updatePlan
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private JobKey getJobKey(UpdatePlan updatePlan) {
|
||||||
|
return JobKey.jobKey(updatePlan.getId().toString(), JOB_GROUP_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 UpdatePlan 生成 TriggerKey
|
||||||
|
* @param updatePlan
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private TriggerKey getTriggerKey(UpdatePlan updatePlan) {
|
||||||
|
return TriggerKey.triggerKey(updatePlan.getId().toString(), JOB_GROUP_NAME);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package link.at17.mid.tushare.task.job;
|
|||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import org.quartz.DisallowConcurrentExecution;
|
||||||
|
import org.quartz.InterruptableJob;
|
||||||
import org.quartz.Job;
|
import org.quartz.Job;
|
||||||
import org.quartz.JobExecutionContext;
|
import org.quartz.JobExecutionContext;
|
||||||
import org.quartz.JobExecutionException;
|
import org.quartz.JobExecutionException;
|
||||||
|
import org.quartz.UnableToInterruptJobException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -17,7 +20,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Validated
|
@Validated
|
||||||
public class UpdatePlanJob implements Job {
|
@DisallowConcurrentExecution
|
||||||
|
public class UpdatePlanJob implements Job, InterruptableJob {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UpdatePlanService updatePlanService;
|
private UpdatePlanService updatePlanService;
|
||||||
@@ -58,4 +62,10 @@ public class UpdatePlanJob implements Job {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void interrupt() throws UnableToInterruptJobException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import org.springframework.stereotype.Controller;
|
|||||||
import org.springframework.validation.Validator;
|
import org.springframework.validation.Validator;
|
||||||
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.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -95,11 +94,11 @@ public class UpdatePlanController extends BaseController {
|
|||||||
return R.judge(updatePlanService.update(new UpdateWrapper<UpdatePlan>().eq(idField, id).set(dbField, value)));
|
return R.judge(updatePlanService.update(new UpdateWrapper<UpdatePlan>().eq(idField, id).set(dbField, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/execute")
|
@PostMapping("/manualTrigger")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public void execute(Integer id) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, InvocationTargetException {
|
public R<?> manualTrigger(Integer id) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, InvocationTargetException {
|
||||||
UpdatePlan updatePlan = updatePlanService.getById(id);
|
UpdatePlan updatePlan = updatePlanService.getById(id);
|
||||||
updatePlanService.execute(updatePlan);
|
return R.judge(() -> updatePlanService.triggerTask(updatePlan));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ td[handler] {cursor: move}
|
|||||||
</script>
|
</script>
|
||||||
<script type="text/html" id="barDemo">
|
<script type="text/html" id="barDemo">
|
||||||
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
|
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
|
||||||
|
<a class="layui-btn layui-btn-xs" lay-event="trigger">触发</a>
|
||||||
|
<a class="layui-btn layui-btn-xs" lay-event="interrupt">停止</a>
|
||||||
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
|
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
@@ -147,7 +149,7 @@ td[handler] {cursor: move}
|
|||||||
d.valid ? '<font color="green">有效</font>' : '<font color="red">无效</font>' +
|
d.valid ? '<font color="green">有效</font>' : '<font color="red">无效</font>' +
|
||||||
'</span>';
|
'</span>';
|
||||||
}}
|
}}
|
||||||
,{fixed: 'right', title:'操作', width: 125, minWidth: 125, toolbar: '#barDemo'}
|
,{fixed: 'right', title:'操作', minWidth: 125, toolbar: '#barDemo'}
|
||||||
]]
|
]]
|
||||||
,done: function(){
|
,done: function(){
|
||||||
var id = this.id;
|
var id = this.id;
|
||||||
@@ -368,13 +370,29 @@ td[handler] {cursor: move}
|
|||||||
table.on('tool(plan-table)', function(obj){ // 双击 toolDouble
|
table.on('tool(plan-table)', function(obj){ // 双击 toolDouble
|
||||||
var data = obj.data;
|
var data = obj.data;
|
||||||
//console.log(obj)
|
//console.log(obj)
|
||||||
if(obj.event === 'del'){
|
if(obj.event === 'edit'){
|
||||||
|
openNewForm(obj.data.id)
|
||||||
|
}
|
||||||
|
else if(obj.event === 'del'){
|
||||||
layer.confirm('真的删除行么', function(index){
|
layer.confirm('真的删除行么', function(index){
|
||||||
obj.del();
|
obj.del();
|
||||||
layer.close(index);
|
layer.close(index);
|
||||||
});
|
});
|
||||||
} else if(obj.event === 'edit'){
|
}
|
||||||
openNewForm(obj.data.id)
|
else if(obj.event === 'trigger'){
|
||||||
|
var load = layui.layer.load(4);
|
||||||
|
$.ajax({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/admin/manage/reviews/plans/manualTrigger',
|
||||||
|
data: {id: obj.data.id},
|
||||||
|
success: res => {
|
||||||
|
layer.msg('操作成功', {time: 1000});
|
||||||
|
},
|
||||||
|
error: res => {
|
||||||
|
layer.msg(res.responseJSON.message || '操作失败', {time: 2000});
|
||||||
|
},
|
||||||
|
complete: () => {if (load) layui.layer.close(load)}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user