package com.bessky.common.task;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.bessky.common.core.function.TeConsumer;
import com.bessky.common.core.util.ContextUtils;
import com.bessky.common.core.util.ThreadUtils;
import com.xxl.job.core.context.XxlJobHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
public abstract class BaseJobHandler
{
/**
* 日志记录器
*/
protected final Logger log = LoggerFactory.getLogger(this.getClass());
@Resource
protected StringRedisTemplate stringRedisTemplate;
/**
* 循环执行任务
*
* @param items
* @param action
* @param error
* @param size
* @param <T>
*/
protected <T> void execute(Collection<T> items, Consumer<T> action, BiConsumer<T, Exception> error, int size)
{
if (CollUtil.isEmpty(items))
{
return;
}
// 创建执行线程
ExecutorService executor = ThreadUtil.newExecutor(size, size, items.size());
// 循环执行任务
items.forEach(item -> executor.execute(() -> {
try
{
action.accept(item);
}
catch (Exception e)
{
log.error(e.getMessage(), e);
if (error != null)
{
error.accept(item, e);
}
else
{
XxlJobHelper.log(e);
}
}
}));
// 等待执行完成
ThreadUtils.await(executor);
}
/**
* 循环执行任务
*
* @param items
* @param action
* @param error
* @param <T>
*/
protected <T> void execute(Collection<T> items, Consumer<T> action, BiConsumer<T, Exception> error)
{
this.execute(items, action, error, 100);
}
/**
* 循环执行任务
*
* @param map
* @param action
* @param error
* @param size
* @param <K>
* @param <V>
*/
protected <K, V> void execute(Map<K, V> map, BiConsumer<K, V> action, TeConsumer<K, V, Exception> error, int size)
{
if (MapUtil.isEmpty(map) || action == null)
{
return;
}
// 创建执行线程
ExecutorService executor = ThreadUtil.newExecutor(size, size, map.size());
// 循环执行任务
map.forEach((key, value) -> executor.execute(() -> {
try
{
action.accept(key, value);
}
catch (Exception e)
{
log.error(e.getMessage(), e);
if (error != null)
{
error.accept(key, value, e);
}
else
{
XxlJobHelper.log(e);
}
}
}));
// 等待执行完成
ThreadUtils.await(executor);
}
/**
* 循环执行任务
*
* @param map
* @param action
* @param error
* @param <K>
* @param <V>
*/
protected <K, V> void execute(Map<K, V> map, BiConsumer<K, V> action, TeConsumer<K, V, Exception> error)
{
this.execute(map, action, error, 100);
}
/**
* 获取用户标识
*
* @return
*/
protected String getUserId()
{
Integer userId = ContextUtils.getUserId();
return userId != null ? userId.toString() : "0";
}
/**
* 记录调试日志
*
* @param format
* @param arguments
*/
protected void debug(String format, Object... arguments)
{
log.debug(format, arguments);
XxlJobHelper.log(format, arguments);
}
/**
* 记录警告日志
*
* @param format
* @param arguments
*/
protected void warn(String format, Object... arguments)
{
log.warn(format, arguments);
XxlJobHelper.log(format, arguments);
}
/**
* 记录错误日志
*
* @param format
* @param arguments
*/
protected void error(String format, Object... arguments)
{
log.error(format, arguments);
XxlJobHelper.log(format, arguments);
}
/**
* 记录错误日志
*
* @param msg
* @param t
*/
protected void error(String msg, Throwable t)
{
log.error(msg, t);
XxlJobHelper.log(t);
}
/**
* 指定操作限流
*
* @param key
* @param timeout
* @param unit
* @return
*/
protected Boolean limit(String key, long timeout, TimeUnit unit)
{
String userId = ContextUtils.getUserId(0).toString();
return stringRedisTemplate.opsForValue().setIfAbsent(key, userId, timeout, unit);
}
/**
* 限流两个小时
*
* @param key
* @return
*/
protected Boolean limit2hour(String key)
{
return this.limit(key, 2, TimeUnit.HOURS);
}
/**
* 解析字符参数
*
* @param key
* @return
*/
protected String parseStringParam(String key)
{
// 获取作业参数
String jobParam = XxlJobHelper.getJobParam();
if (!JSON.isValidObject(jobParam))
{
return null;
}
// 解析作业参数
return JSON.parseObject(jobParam).getString(key);
}
/**
* 解析字符参数
*
* @param key
* @param other
* @return
*/
protected String parseStringParam(String key, String other)
{
return Optional.ofNullable(key).map(this::parseStringParam).filter(StringUtils::isNotBlank).orElse(other);
}
/**
* 解析字符参数
*
* @param key
* @param other
* @return
*/
protected String parseStringParam(String key, Supplier<String> other)
{
return Optional.ofNullable(key).map(this::parseStringParam).filter(StringUtils::isNotBlank).orElseGet(other);
}
/**
* 解析对象参数
*
* @param key
* @param clazz
* @param <T>
* @return
*/
protected <T> T parseObjectParam(String key, Class<T> clazz)
{
// 获取作业参数
String jobParam = XxlJobHelper.getJobParam();
if (!JSON.isValidObject(jobParam))
{
return null;
}
// 解析作业参数
return JSON.parseObject(jobParam).getObject(key, clazz);
}
/**
* 解析对象参数
*
* @param key
* @param clazz
* @param other
* @param <T>
* @return
*/
protected <T> T parseObjectParam(String key, Class<T> clazz, T other)
{
T value = this.parseObjectParam(key, clazz);
return Optional.ofNullable(value).orElse(other);
}
/**
* 解析对象参数
*
* @param key
* @param other
* @param clazz
* @param <T>
* @return
*/
protected <T> T parseObjectParam(String key, Supplier<T> other, Class<T> clazz)
{
T value = this.parseObjectParam(key, clazz);
return Optional.ofNullable(value).orElseGet(other);
}
/**
* 解析列表参数
*
* @param key
* @param clazz
* @param <T>
* @return
*/
protected <T> List<T> parseListParam(String key, Class<T> clazz)
{
// 获取作业参数
String jobParam = XxlJobHelper.getJobParam();
if (!JSON.isValidObject(jobParam))
{
return null;
}
// 解析作业参数
JSONArray jsonArray = JSON.parseObject(jobParam).getJSONArray(key);
if (CollectionUtils.isEmpty(jsonArray))
{
return null;
}
// 转换参数列表
return jsonArray.toJavaList(clazz);
}
/**
* 解析映射参数
*
* @param key
* @return
*/
protected Map<String, String> parseMapParam(String key)
{
// 获取作业参数
String jobParam = XxlJobHelper.getJobParam();
if (!JSON.isValidObject(jobParam))
{
return null;
}
// 解析作业参数
return JSON.parseObject(jobParam).getObject(key, new TypeReference<Map<String, String>>()
{
});
}
/**
* 解析作业参数
*
* @param key
* @return
*/
protected JSONObject parseJsonObject(String key)
{
// 获取作业参数
String jobParam = XxlJobHelper.getJobParam();
if (!JSON.isValidObject(jobParam))
{
return null;
}
// 解析作业参数
return JSON.parseObject(jobParam).getJSONObject(key);
}
}