beetlsql3-dev
Mlxa0324 2 years ago
parent 8bebcff7e1
commit 273d4af046

@ -1,5 +1,13 @@
package cn.jlw.web;
import cn.hutool.core.util.ObjectUtil;
import com.ibeetl.jlw.dao.TeacherOpenCourseQuestionSettingDao;
import com.ibeetl.jlw.entity.TeacherOpenCourseQuestionSetting;
import com.ibeetl.jlw.service.questionSettingQueue.QuestionSettingDelayed;
import com.ibeetl.jlw.service.questionSettingQueue.QuestionSettingRedisDelayQueueImpl;
import com.ibeetl.jlw.web.query.TeacherOpenCourseQuestionSettingQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
@ -12,12 +20,22 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.WebApplicationInitializer;
import java.util.List;
import static com.ibeetl.jlw.enums.GlobalPushStatusEnum.PUSH;
import static com.ibeetl.jlw.service.questionSettingQueue.RedisDelayQueue.QuestionQueueTypeEnum.QUESTION_SETTING;
@SpringBootApplication
@EnableCaching
@EnableAsync
@ComponentScan(basePackages= {"cn.jlw","com.ibeetl.admin","com.ibeetl.jlw"})
@ServletComponentScan(basePackages = "cn.jlw.filter")
public class WebApplication extends SpringBootServletInitializer implements WebApplicationInitializer {
public class WebApplication extends SpringBootServletInitializer implements WebApplicationInitializer, CommandLineRunner {
@Autowired
private QuestionSettingRedisDelayQueueImpl questionSettingRedisDelayQueue;
@Autowired
private TeacherOpenCourseQuestionSettingDao teacherOpenCourseQuestionSettingDao;
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
@ -30,4 +48,43 @@ public class WebApplication extends SpringBootServletInitializer implements WebA
return factory;
}
@Override
public void run(String... args) {
String keys = "1580386808322236416\n" +
"1596869091795312640\n" +
"1596869092516732928\n" +
"1596869093275901952\n" +
"1596869093951184896\n" +
"1596869094697771008\n" +
"1596869095687626752\n" +
"1596869139304194048\n" +
"1596869139954311168\n" +
"1596869140570873856\n" +
"1596869141208408064\n" +
"1596869141871108096\n" +
"1597296145632239616\n" +
"1597601262612946944\n" +
"1597616083567812608\n" +
"1597616347335008256\n" +
"1597619304407408640\n" +
"1597622780457820160";
final String queueKey = QUESTION_SETTING.name();
TeacherOpenCourseQuestionSettingQuery questionSettingQuery = new TeacherOpenCourseQuestionSettingQuery();
questionSettingQuery.setTeacherOpenCourseQuestionSettingId(1580386808322236416L);
questionSettingQuery.setTeacherOpenCourseQuestionSettingStatus(1);
questionSettingQuery.setTeacherOpenCourseQuestionSettingPushStatus(PUSH);
List<TeacherOpenCourseQuestionSetting> list = teacherOpenCourseQuestionSettingDao.getValuesByQueryNotWithPermission(questionSettingQuery);
if (ObjectUtil.isEmpty(list)) {
return;
}
TeacherOpenCourseQuestionSetting info = list.get(0);
QuestionSettingDelayed msg = new QuestionSettingDelayed();
Long teacherOpenCourseQuestionSettingId = info.getTeacherOpenCourseQuestionSettingId();
msg.setQuestionSettingId(teacherOpenCourseQuestionSettingId);
boolean exists = questionSettingRedisDelayQueue.isExists(queueKey, teacherOpenCourseQuestionSettingId.toString());
if (!exists) {
questionSettingRedisDelayQueue.delay(queueKey, msg, info.getTeacherOpenCourseQuestionEndTime().getTime(), 30 * 60 * 1000);
}
}
}

@ -1,10 +1,12 @@
package com.ibeetl.admin.core.conf;
package com.ibeetl.jlw.conf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.lang.reflect.Method;
@ -18,8 +20,8 @@ import java.util.concurrent.ThreadPoolExecutor;
* @Author: 87966
* @Date: 2022/12/8 10:48
*/
//@Configuration
//@EnableAsync
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
private static final Logger log = LoggerFactory.getLogger(AsyncConfig.class);

@ -114,4 +114,31 @@ public interface TeacherOpenCourseQuestionLogDao extends BaseMapper<TeacherOpenC
.andEq(TeacherOpenCourseQuestionLog::getTeacherOpenCourseQuestionSettingId, questionSettingId)
.count();
}
/**
* : <br>
* ID
*
* @param questionSettingId ID
* @param type
* @return {@link long}
* @Author: lx
* @Date: 2022/12/6 22:59
*/
default List<TeacherOpenCourseQuestionLog> getByQuestionLogAddType(@NotNull Long questionSettingId, String ...type) {
LambdaQuery<TeacherOpenCourseQuestionLog> lambdaQuery = createLambdaQuery();
LambdaQuery<TeacherOpenCourseQuestionLog> andCondition = lambdaQuery.condition();
boolean isNull = Arrays.stream(type).anyMatch(item -> item == null);
List<String> notNullList = Arrays.stream(type).filter(item -> item != null).collect(Collectors.toList());
// 是否添加Null条件
andCondition = isNull ? andCondition.andIsNull(TeacherOpenCourseQuestionLog::getQuestionLogAddType) : andCondition;
andCondition.orIn(TeacherOpenCourseQuestionLog::getQuestionLogAddType, notNullList);
return lambdaQuery.and(andCondition)
.andEq(TeacherOpenCourseQuestionLog::getTeacherOpenCourseQuestionLogStatus, 1)
.andEq(TeacherOpenCourseQuestionLog::getTeacherOpenCourseQuestionSettingId, questionSettingId)
.select();
}
}

@ -30,6 +30,7 @@ public interface TeacherOpenCourseQuestionSettingDao extends BaseMapper<TeacherO
int updateGivenByIds(TeacherOpenCourseQuestionSettingQuery teacherOpenCourseQuestionSettingQuery);
List<TeacherOpenCourseQuestionSetting> getByIds(String ids);
List<TeacherOpenCourseQuestionSetting> getValuesByQuery(TeacherOpenCourseQuestionSettingQuery teacherOpenCourseQuestionSettingQuery);
List<TeacherOpenCourseQuestionSetting> getValuesByQueryNotWithPermission(TeacherOpenCourseQuestionSettingQuery teacherOpenCourseQuestionSettingQuery);
/**
*

@ -1,113 +0,0 @@
//package com.ibeetl.jlw.service.questionSettingQueue;
//
//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.JSONObject;
//import com.alibaba.fastjson.TypeReference;
//import com.ibeetl.jlw.service.TeacherOpenCourseQuestionLogService;
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
//import org.springframework.data.redis.core.StringRedisTemplate;
//import org.springframework.scheduling.annotation.Async;
//import org.springframework.scheduling.annotation.EnableAsync;
//import org.springframework.stereotype.Service;
//import redis.clients.jedis.Jedis;
//
//import java.lang.reflect.Type;
//import java.util.Set;
//import java.util.UUID;
//
///**
// * 功能描述: <br>
// * 作业、考试、章节练习自动延时交卷
// *
// * @Author: 87966
// * @Date: 2022/12/8 10:55
// */
//@Service
//@Slf4j
//@EnableAsync
//@RequiredArgsConstructor
//public class AutoSubmitQuestionSetting<T> {
//
// final private TeacherOpenCourseQuestionLogService teacherOpenCourseQuestionLogService;
//
// static class TaskItem<T> {
// public String id;
// public T msg;
// }
//
// // fastjson序列化对象中存在generic类型时需要使用TypeReference
// private Type TaskType = new TypeReference<TaskItem<T>>() {
// }.getType();
//
// /**
// * 将指定延迟消费的消息放入延时队列
// *
// * @param msg
// */
// public void delay(StringRedisTemplate jedis, String queueKey, T msg, long outTime) {
// TaskItem<T> task = new TaskItem<T>();
// // 分配唯一的uuid
// task.id = UUID.randomUUID().toString();
// task.msg = msg;
// // fastjson 序列化
// String s = JSON.toJSONString(task);
// // 塞入延时队列, outTime 后再试
// jedis.opsForZSet().add(queueKey, System.currentTimeMillis() + outTime, s);
// }
//
// /**
// * 轮训zset获取到期的任务进行处理
// */
// @Async("taskExecutor")
// public void loop(RedisProperties.Jedis jedis, String queueKey) {
// while (!Thread.interrupted()) {
// // 只取一条
// Set<String> values = jedis.zrangeByScore(queueKey, 0, System.currentTimeMillis(), 0, 1);
// if (values.isEmpty()) {
// try {
// // 歇会继续
// Thread.sleep(500);
// } catch (InterruptedException e) {
// break;
// }
// continue;
// }
// String s = values.iterator().next();
// // 抢到了并移除该元素
// if (jedis.zrem(queueKey, s) > 0) {
// // fastjson反序列化
// TaskItem<T> task = JSON.parseObject(s, TaskType);
// this.handleMsg(task.msg);
// }
// }
// }
//
// /**
// * 消费消息
// *
// * @param msg
// */
// private void handleMsg(T msg) {
// // 将订单信息的json字符串转成json对象
// JSONObject orderInfo = JSONObject.parseObject((String) msg);
// String tenant = orderInfo.getString("tenant");
// String flowNo = orderInfo.getString("flowNo");
// // 根据 tenant+flowNo 得到该订单
// Order order = orderDao.getByTenantAndFlowNo(tenant, flowNo);
// // 判断该订单的状态
// // 如果仍然为已提交OrderStatusEnum.SUBMITTED则将该订单状态自动修改为已取消OrderStatusEnum.PAID
// OrderState dbOrderState = orderStateDao.findByTenantAndOwner(tenant, order.getUuid());
// OrderStatusEnum dbState = dbOrderState.getState();
// if (OrderStatusEnum.SUBMITTED == dbState) {
// try {
// orderService.cancel(tenant, flowNo, "订单超时未支付自动取消订单");
// } catch (Exception e) {
// log.error("订单自动取消失败flowNo={}", flowNo);
// e.printStackTrace();
// }
// }
// }
//}

@ -0,0 +1,20 @@
package com.ibeetl.jlw.service.questionSettingQueue;
import lombok.Data;
/**
* : <br>
*
* @author: mlx
* @description:
* @date: 2022/12/9 1:02
* @version: 1.0
*/
@Data
public class QuestionSettingDelayed {
/**
* ID
*/
private Long questionSettingId;
}

@ -0,0 +1,67 @@
package com.ibeetl.jlw.service.questionSettingQueue;
import com.ibeetl.jlw.dao.TeacherOpenCourseQuestionLogDao;
import com.ibeetl.jlw.entity.TeacherOpenCourseQuestionLog;
import com.ibeetl.jlw.enums.QuestionLogAddTypeEnum;
import com.ibeetl.jlw.service.TeacherOpenCourseQuestionLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.stream.Collectors;
import static com.ibeetl.jlw.enums.QuestionLogAddTypeEnum.PRE_SUBMIT;
import static com.ibeetl.jlw.service.questionSettingQueue.RedisDelayQueue.QuestionQueueTypeEnum.QUESTION_SETTING;
/**
* : <br>
*
* @author: mlx
* @description:
* @date: 2022/12/9 0:41
* @version: 1.0
*/
@Service
public class QuestionSettingRedisDelayQueueImpl extends RedisDelayQueue<QuestionSettingDelayed> {
@Autowired
private TeacherOpenCourseQuestionLogDao teacherOpenCourseQuestionLogDao;
@Autowired
private TeacherOpenCourseQuestionLogService teacherOpenCourseQuestionLogService;
@Autowired @Lazy
private QuestionSettingRedisDelayQueueImpl questionSettingRedisDelayQueue;
public QuestionSettingRedisDelayQueueImpl(RedisTemplate redisTemplate) {
super(redisTemplate);
}
@Override
public void handleMsg(QuestionSettingDelayed msg) {
final Long questionSettingId = msg.getQuestionSettingId();
// 查询需要更新状态的题目日志
List<TeacherOpenCourseQuestionLog> list = teacherOpenCourseQuestionLogDao.getByQuestionLogAddType(questionSettingId, PRE_SUBMIT.name(), null);
// 获取需要修改的日志IDs
List<TeacherOpenCourseQuestionLog> logList = list.stream().map(item -> {
TeacherOpenCourseQuestionLog questionLog = new TeacherOpenCourseQuestionLog();
questionLog.setTeacherOpenCourseQuestionLogId(item.getTeacherOpenCourseQuestionLogId());
// 更改为交卷状态
questionLog.setQuestionLogAddType(QuestionLogAddTypeEnum.FINALLY_SUBMIT);
return questionLog;
}).collect(Collectors.toList());
// 逻辑提交试卷
teacherOpenCourseQuestionLogService.updateBatchTemplate(logList);
}
@PostConstruct
public void consumer() {
new Thread(() -> {
// 为了走异步
questionSettingRedisDelayQueue.loop(QUESTION_SETTING.name());
}).start();
}
}

@ -0,0 +1,138 @@
package com.ibeetl.jlw.service.questionSettingQueue;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.ibeetl.admin.core.util.PlatformException;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Set;
import static cn.hutool.core.util.ArrayUtil.join;
/**
* : <br>
*
*
* @Author: 87966
* @Date: 2022/12/8 10:55
*/
@Slf4j
@EnableAsync
public abstract class RedisDelayQueue<T> {
private ZSetOperations<String, Object> zSetOperations;
public RedisDelayQueue(RedisTemplate<String, Object> redisTemplate) {
zSetOperations = redisTemplate.opsForZSet();
}
@Data
@RequiredArgsConstructor
public static class QuestionSettingTaskItem<T> {
final public String id;
final public T msg;
}
public enum QuestionQueueTypeEnum {
QUESTION_SETTING
}
/**
* fastjsongeneric使TypeReference
*/
private Type TaskType = new TypeReference<QuestionSettingTaskItem<T>>() {
}.getType();
/**
* : <br>
* ZSetKey
*
* @param ids
* @return {@link String}
* @Author: lx
* @Date: 2022/12/9 0:38
*/
public String zSetKeyRule(Object ...ids) {
return join(Arrays.asList(ids).toArray(), "_");
}
/**
* : <br>
*
*
* @param queueKey Key
* @param msg
* @param dataTime
* @param outTime
* @Author: lx
* @Date: 2022/12/9 1:58
*/
public void delay(String queueKey, T msg, long dataTime, long outTime) {
QuestionSettingTaskItem<T> task = new QuestionSettingTaskItem(UUID.fastUUID().toString(), msg);
// fastjson 序列化
String taskEntity = JSON.toJSONString(task);
// 塞入延时队列, outTime 后再试
zSetOperations.add(queueKey, taskEntity, dataTime + outTime);
}
/**
* : <br>
* Key
*
* @param queueKey ZSetKey
* @param otherKey MapValue
* @return {@link boolean}
* @Author: lx
* @Date: 2022/12/9 2:42
*/
public boolean isExists(String queueKey, String otherKey) {
Set<Object> objects = zSetOperations.rangeByScore(queueKey, 0, -1);
return objects.stream().anyMatch(item -> JSON.parseObject(item.toString()).containsValue(otherKey));
}
/**
* zset
*/
@Async("taskExecutor")
public void loop(String queueKey) {
while (!Thread.interrupted()) {
// 只取一条
Set<Object> values = zSetOperations.rangeByScore(queueKey, 0, System.currentTimeMillis(), 0, 1);
if (values.isEmpty()) {
try {
// 歇会继续
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
continue;
}
String s = values.iterator().next().toString();
// 抢到了并移除该元素
if (zSetOperations.remove(queueKey, s) > 0) {
// fastjson反序列化
QuestionSettingTaskItem<T> task = JSON.parseObject(s, TaskType);
handleMsg(task.msg);
}
}
}
/**
*
*
* @param msg
*/
public void handleMsg(T msg) {
throw new PlatformException("需要实现的消费方法!");
}
}

@ -509,6 +509,93 @@ getValuesByQuery
and find_in_set(t.user_id,#userIdPlural#)
@}
getValuesByQueryNotWithPermission
===
* 根据不为空的参数进行查询
select t.*
from teacher_open_course_question_setting t
where 1=1
@if(!isEmpty(teacherOpenCourseQuestionSettingId)){
and t.teacher_open_course_question_setting_id =#teacherOpenCourseQuestionSettingId#
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingIdPlural)){
and find_in_set(t.teacher_open_course_question_setting_id,#teacherOpenCourseQuestionSettingIdPlural#)
@}
@if(!isEmpty(teacherOpenCourseId)){
and t.teacher_open_course_id =#teacherOpenCourseId#
@}
@if(!isEmpty(teacherOpenCourseIdPlural)){
and find_in_set(t.teacher_open_course_id,#teacherOpenCourseIdPlural#)
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingSchoolClassIds)){
and t.teacher_open_course_question_setting_school_class_ids =#teacherOpenCourseQuestionSettingSchoolClassIds#
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingDoCount)){
and t.teacher_open_course_question_setting_do_count =#teacherOpenCourseQuestionSettingDoCount#
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingQuestionNoOrder)){
and t.teacher_open_course_question_setting_question_no_order =#teacherOpenCourseQuestionSettingQuestionNoOrder#
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingOptionNoOrder)){
and t.teacher_open_course_question_setting_option_no_order =#teacherOpenCourseQuestionSettingOptionNoOrder#
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingEndShowQa)){
and t.teacher_open_course_question_setting_end_show_qa =#teacherOpenCourseQuestionSettingEndShowQa#
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingEndShowTrueFalse)){
and t.teacher_open_course_question_setting_end_show_true_false =#teacherOpenCourseQuestionSettingEndShowTrueFalse#
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingName)){
and t.teacher_open_course_question_setting_name =#teacherOpenCourseQuestionSettingName#
@}
@if(!isEmpty(teacherOpenCourseQuestionStartTime)){
and t.teacher_open_course_question_start_time =#teacherOpenCourseQuestionStartTime#
@}
@if(!isEmpty(teacherOpenCourseQuestionEndTime)){
and t.teacher_open_course_question_end_time =#teacherOpenCourseQuestionEndTime#
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingType)){
and t.teacher_open_course_question_setting_type =#teacherOpenCourseQuestionSettingType#
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingFile)){
and t.teacher_open_course_question_setting_file =#teacherOpenCourseQuestionSettingFile#
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingPushStatus)){
and t.teacher_open_course_question_setting_push_status =#teacherOpenCourseQuestionSettingPushStatus#
@}
@if(isEmpty(teacherOpenCourseQuestionSettingStatus) && isEmpty(teacherOpenCourseQuestionSettingStatusPlural)){
and t.teacher_open_course_question_setting_status != 2
@}else{
@if(!isEmpty(teacherOpenCourseQuestionSettingStatus)){
and t.teacher_open_course_question_setting_status =#teacherOpenCourseQuestionSettingStatus#
@}else if(!isEmpty(teacherOpenCourseQuestionSettingStatusPlural)){
and find_in_set(t.teacher_open_course_question_setting_status,#teacherOpenCourseQuestionSettingStatusPlural#)
@}
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingAddTime)){
and t.teacher_open_course_question_setting_add_time =#teacherOpenCourseQuestionSettingAddTime#
@}
@if(!isEmpty(teacherOpenCourseQuestionSettingRequire)){
and t.teacher_open_course_question_setting_require =#teacherOpenCourseQuestionSettingRequire#
@}
@if(!isEmpty(teacherOpenCourseMergeCourseInfoId)){
and t.teacher_open_course_merge_course_info_id =#teacherOpenCourseMergeCourseInfoId#
@}
@if(!isEmpty(orgId)){
and t.org_id =#orgId#
@}
@if(!isEmpty(orgIdPlural)){
and find_in_set(t.org_id,#orgIdPlural#)
@}
@if(!isEmpty(userId)){
and t.user_id =#userId#
@}
@if(!isEmpty(userIdPlural)){
and find_in_set(t.user_id,#userIdPlural#)
@}
analysisOld
===
* 题目配置,统计分析接口

Loading…
Cancel
Save