mirror of
https://gitee.com/lakernote/easy-admin.git
synced 2026-09-03 05:33:47 +08:00
bug fix and code refactor
This commit is contained in:
@@ -20,7 +20,7 @@ public class EasyDefaultUncaughtErrorControllor implements ErrorController {
|
||||
HttpStatus statusCode = getHttpStatusCode(request);
|
||||
String uri = (String) request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI);
|
||||
log.error("error,code:{},uri:{},response:{}", statusCode.value(), uri, response);
|
||||
return Response.error(String.valueOf(statusCode.value()), "未找到接口", uri);
|
||||
return Response.error(String.valueOf(statusCode.value()), statusCode.getReasonPhrase(), uri);
|
||||
}
|
||||
|
||||
private HttpStatus getHttpStatusCode(HttpServletRequest request) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.springframework.stereotype.Component;
|
||||
public class EasyAdminHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
@Override
|
||||
public void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
public void doHealthCheck(Health.Builder builder) {
|
||||
boolean checkHealth = check();
|
||||
if (checkHealth) {
|
||||
builder.up();
|
||||
|
||||
@@ -14,7 +14,7 @@ public class EasyAdminInfo implements InfoContributor {
|
||||
public void contribute(Info.Builder builder) {
|
||||
Map<String, String> info = new HashMap<>();
|
||||
String springBootVersion = SpringBootVersion.getVersion();
|
||||
info.put("springBootVersion", springBootVersion);
|
||||
info.put("boot", springBootVersion);
|
||||
info.put("email", "xxx@xxx.com");
|
||||
builder.withDetail("spring", info);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ public class EasyJarVersionEndpoint {
|
||||
|
||||
@SneakyThrows
|
||||
@PostConstruct
|
||||
// 优化这个方法,将依赖信息缓存起来
|
||||
private void initDependency() {
|
||||
Set<Dependency> dependencies = new LinkedHashSet<>();
|
||||
PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||
@@ -70,6 +71,7 @@ public class EasyJarVersionEndpoint {
|
||||
byte[] data = FileCopyUtils.copyToByteArray(resource.getInputStream());
|
||||
String[] list = new String(data, StandardCharsets.UTF_8).split("\n");
|
||||
for (String string : list) {
|
||||
string = string.replaceAll("\r", "");
|
||||
if (string.startsWith("version=") || string.startsWith("groupId=") || string.startsWith("artifactId=")) {
|
||||
if (string.startsWith("version=")) {
|
||||
dependency.setVersion(string.replace("version=", ""));
|
||||
|
||||
@@ -18,12 +18,8 @@ public class EasyCustomHandler implements IHandler {
|
||||
public void handle(Execution execution) {
|
||||
// 获取参数
|
||||
Map<String, Object> args = execution.getArgs();
|
||||
args.forEach((s, o) -> System.out.println(s + ":" + o));
|
||||
args.forEach((s, o) -> log.info("参数为:{}:{}", s, o));
|
||||
List<Task> tasks = execution.getTasks();
|
||||
tasks.forEach(task -> {
|
||||
System.out.println(task.getTaskName());
|
||||
});
|
||||
|
||||
|
||||
tasks.forEach(task -> log.info("任务名称为:{}", task.getTaskName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public class TraceAnnotationInterceptor implements HandlerInterceptor {
|
||||
throws Exception {
|
||||
|
||||
// 获取处理method
|
||||
if (handler instanceof HandlerMethod == false) {
|
||||
if (!(handler instanceof HandlerMethod)) {
|
||||
return true;
|
||||
}
|
||||
Method method = ((HandlerMethod) handler).getMethod();
|
||||
@@ -33,9 +33,9 @@ public class TraceAnnotationInterceptor implements HandlerInterceptor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) {
|
||||
// 获取处理method
|
||||
if (handler instanceof HandlerMethod == false) {
|
||||
if (!(handler instanceof HandlerMethod)) {
|
||||
return;
|
||||
}
|
||||
TraceContext.stopSpan(1000);
|
||||
|
||||
@@ -26,8 +26,9 @@ import java.util.stream.Collectors;
|
||||
* 这种只能处理查询 不能处理 cud
|
||||
* 且不支持别名
|
||||
*/
|
||||
@Deprecated
|
||||
@Slf4j
|
||||
public class LakerDataPermissionHandler implements DataPermissionHandler {
|
||||
public class EasyDataPermissionHandler implements DataPermissionHandler {
|
||||
|
||||
public static final String WHERE = " where {}";
|
||||
|
||||
@@ -112,7 +113,7 @@ public class LakerDataPermissionHandler implements DataPermissionHandler {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("LakerDataPermissionHandler.err", e);
|
||||
}
|
||||
}
|
||||
return where;
|
||||
}
|
||||
}
|
||||
@@ -10,16 +10,16 @@ import org.springframework.stereotype.Component;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author longli
|
||||
* @author laker
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MyMetaObjectHandler implements MetaObjectHandler {
|
||||
public class EasyMybatisPlusMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
log.info("start insert fill ....");
|
||||
this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class);
|
||||
this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class);
|
||||
this.strictInsertFill(metaObject, "createBy", Long.class, StpUtil.getLoginIdAsLong());
|
||||
UserInfoAndPowers userInfoAndPowers = (UserInfoAndPowers) StpUtil.getSession().get(EasyAdminConstants.CURRENT_USER);
|
||||
this.strictInsertFill(metaObject, "createDeptId", Long.class, userInfoAndPowers.getDeptId());
|
||||
@@ -28,7 +28,7 @@ public class MyMetaObjectHandler implements MetaObjectHandler {
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
log.info("start update fill ....");
|
||||
this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class);
|
||||
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
|
||||
this.strictUpdateFill(metaObject, "operator", String.class, "张三");
|
||||
}
|
||||
}
|
||||
@@ -158,7 +158,7 @@ public class PerformanceInterceptor implements Interceptor {
|
||||
long start = SystemClock.now();
|
||||
String mapperId = ms.getId();
|
||||
TraceContext.addSpan(mapperId, SpanType.Mapper);
|
||||
Object result = null;
|
||||
Object result;
|
||||
try {
|
||||
result = invocation.proceed();
|
||||
} catch (Exception e) {
|
||||
@@ -178,7 +178,7 @@ public class PerformanceInterceptor implements Interceptor {
|
||||
if (this.getMaxTime() >= 1 && timing > this.getMaxTime()) {
|
||||
log.error(formatSql.toString());
|
||||
} else {
|
||||
// log.warn("Execute {}ms,Mapper:{}", timing, mapperId);
|
||||
log.info("Execute {}ms,Mapper:{}", timing, mapperId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -201,7 +201,7 @@ public class PerformanceInterceptor implements Interceptor {
|
||||
this.maxTime = Long.parseLong(maxTime);
|
||||
}
|
||||
if (StringUtils.isNotBlank(format)) {
|
||||
this.format = Boolean.valueOf(format);
|
||||
this.format = Boolean.parseBoolean(format);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public class UserInfoAndPowers {
|
||||
private List<UserDataPower> userDataPowers;
|
||||
|
||||
public Boolean isSuperAdmin() {
|
||||
return userId.longValue() == 1L;
|
||||
return userId == 1L;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,14 +35,12 @@ public class EasyAdminMDCThreadPoolExecutor extends EasyAdminThreadPoolExecutor
|
||||
|
||||
/**
|
||||
* submit Runnable callable 都会走这里,所以我们只需要改写这里即可。
|
||||
*
|
||||
* @param command
|
||||
*/
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
if (command instanceof RunnableFuture) {
|
||||
// submit future
|
||||
super.execute(new EasyAdminFuture((RunnableFuture) command, MDC.getCopyOfContextMap()));
|
||||
super.execute(new EasyAdminFuture<>((RunnableFuture) command, MDC.getCopyOfContextMap()));
|
||||
} else {
|
||||
super.execute(wrapExecuteRunnable(command, MDC.getCopyOfContextMap()));
|
||||
}
|
||||
@@ -52,10 +50,6 @@ public class EasyAdminMDCThreadPoolExecutor extends EasyAdminThreadPoolExecutor
|
||||
|
||||
/**
|
||||
* 封装任务,加入TraceId,无返回值
|
||||
*
|
||||
* @param runnable
|
||||
* @param threadContext
|
||||
* @return
|
||||
*/
|
||||
private static Runnable wrapExecuteRunnable(final Runnable runnable, final Map<String, String> threadContext) {
|
||||
return () -> {
|
||||
@@ -76,8 +70,8 @@ public class EasyAdminMDCThreadPoolExecutor extends EasyAdminThreadPoolExecutor
|
||||
}
|
||||
|
||||
private static class EasyAdminFuture<T> implements RunnableFuture<T> {
|
||||
private RunnableFuture<T> future;
|
||||
private Map<String, String> threadContext;
|
||||
private final RunnableFuture<T> future;
|
||||
private final Map<String, String> threadContext;
|
||||
|
||||
public EasyAdminFuture(RunnableFuture<T> future, Map<String, String> threadContext) {
|
||||
this.future = future;
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
package com.laker.admin.framework.ext.thread;
|
||||
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import cn.hutool.log.LogFactory;
|
||||
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
|
||||
|
||||
/**
|
||||
* 自定义扩展拒绝策略
|
||||
*
|
||||
*
|
||||
* @author laker
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class EasyAdminRejectPolicy extends AbortPolicy {
|
||||
private static final Log LOG = LogFactory.get();
|
||||
|
||||
/** {@inheritDoc} */
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
|
||||
LOG.warn("触发线程拒绝策略:\r\n{}", "Task " + r.toString() + " rejected from "
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.laker.admin.framework.handler;
|
||||
|
||||
import cn.hutool.system.SystemUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class OpenBrowserHandler implements CommandLineRunner {
|
||||
@Value("${server.port}")
|
||||
private int serverPort;
|
||||
@@ -23,7 +25,7 @@ public class OpenBrowserHandler implements CommandLineRunner {
|
||||
System.out.println("==================================================注意====================================================");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
log.error("open browser err.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.laker.admin.framework.lock;
|
||||
|
||||
import com.laker.admin.framework.lock.api.Lock;
|
||||
import com.laker.admin.framework.lock.impl.jdbc.MysqlLock;
|
||||
import com.laker.admin.framework.lock.impl.redis.RedisLock;
|
||||
import com.laker.admin.framework.lock.api.ILock;
|
||||
import com.laker.admin.framework.lock.impl.jdbc.MysqlILock;
|
||||
import com.laker.admin.framework.lock.impl.redis.RedisILock;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -21,14 +21,14 @@ public class EasyLockConfig {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(name = "lock.type", havingValue = "mysql", matchIfMissing = true)
|
||||
public Lock mysqlLock(JdbcTemplate jdbcTemplate, TaskScheduler taskScheduler) {
|
||||
return new MysqlLock(jdbcTemplate, taskScheduler);
|
||||
public ILock mysqlLock(JdbcTemplate jdbcTemplate, TaskScheduler taskScheduler) {
|
||||
return new MysqlILock(jdbcTemplate, taskScheduler);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(name = "lock.type", havingValue = "redis")
|
||||
public Lock redisLock(StringRedisTemplate stringRedisTemplate, TaskScheduler taskScheduler) {
|
||||
return new RedisLock(stringRedisTemplate, taskScheduler);
|
||||
public ILock redisLock(StringRedisTemplate stringRedisTemplate, TaskScheduler taskScheduler) {
|
||||
return new RedisILock(stringRedisTemplate, taskScheduler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.time.Duration;
|
||||
/**
|
||||
* @author laker
|
||||
*/
|
||||
public interface Lock {
|
||||
public interface ILock {
|
||||
/**
|
||||
* 尝试获取锁,
|
||||
*
|
||||
@@ -13,14 +13,12 @@ public interface Lock {
|
||||
* @param expiration 锁过期时间
|
||||
* @return 锁定失败返回null
|
||||
*/
|
||||
LLock acquire(String key, Duration expiration);
|
||||
Locker acquire(String key, Duration expiration);
|
||||
|
||||
/**
|
||||
* 释放锁
|
||||
*
|
||||
* @param key 锁定的key
|
||||
* @param token 用于检查是否是这个锁,防止误删
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean release(LLock lock);
|
||||
boolean release(Locker lock);
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import java.util.concurrent.ScheduledFuture;
|
||||
**/
|
||||
@Data
|
||||
@Builder
|
||||
public class LLock {
|
||||
public class Locker {
|
||||
/**
|
||||
* 锁定的key
|
||||
*/
|
||||
@@ -20,5 +20,8 @@ public class LLock {
|
||||
* 用于检查是否是这个锁,防止误删
|
||||
*/
|
||||
private String token;
|
||||
/**
|
||||
* 每个锁都有一个线程去后台续约
|
||||
*/
|
||||
private ScheduledFuture<?> scheduledFuture;
|
||||
}
|
||||
@@ -2,8 +2,9 @@ package com.laker.admin.framework.lock.core;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.laker.admin.framework.lock.api.LLock;
|
||||
import com.laker.admin.framework.lock.api.Lock;
|
||||
import com.laker.admin.framework.exception.BusinessException;
|
||||
import com.laker.admin.framework.lock.api.ILock;
|
||||
import com.laker.admin.framework.lock.api.Locker;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
|
||||
import java.time.Duration;
|
||||
@@ -12,27 +13,27 @@ import java.util.concurrent.ScheduledFuture;
|
||||
/**
|
||||
* @author laker
|
||||
*/
|
||||
public abstract class AbstractSimpleLock implements Lock {
|
||||
public abstract class AbstractSimpleILock implements ILock {
|
||||
private final TaskScheduler taskScheduler;
|
||||
|
||||
protected AbstractSimpleLock(TaskScheduler taskScheduler) {
|
||||
protected AbstractSimpleILock(TaskScheduler taskScheduler) {
|
||||
this.taskScheduler = taskScheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LLock acquire(final String key, final Duration expiration) {
|
||||
public Locker acquire(final String key, final Duration expiration) {
|
||||
final String token = IdUtil.fastSimpleUUID();
|
||||
String acquire = acquire(key, token, expiration);
|
||||
if (StrUtil.isBlank(acquire)) {
|
||||
return null;
|
||||
throw new BusinessException("其他人正在处理中,请稍后重试");
|
||||
}
|
||||
// 后台线程定时续租 一个锁一个后台线程续约
|
||||
ScheduledFuture<?> scheduledFuture = scheduleLockRefresh(key, acquire, expiration);
|
||||
return LLock.builder().key(key).token(token).scheduledFuture(scheduledFuture).build();
|
||||
return Locker.builder().key(key).token(token).scheduledFuture(scheduledFuture).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean release(LLock lock) {
|
||||
public boolean release(Locker lock) {
|
||||
cancelSchedule(lock);
|
||||
return release0(lock);
|
||||
}
|
||||
@@ -43,16 +44,16 @@ public abstract class AbstractSimpleLock implements Lock {
|
||||
|
||||
}
|
||||
|
||||
private void cancelSchedule(LLock lock) {
|
||||
private void cancelSchedule(Locker lock) {
|
||||
final ScheduledFuture<?> scheduledFuture = lock.getScheduledFuture();
|
||||
if (scheduledFuture != null && !scheduledFuture.isCancelled() && !scheduledFuture.isDone()) {
|
||||
scheduledFuture.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String acquire(String key, String token, Duration expiration);
|
||||
public abstract String acquire(String key, String token, Duration expiration);
|
||||
|
||||
protected abstract boolean release0(LLock lock);
|
||||
public abstract boolean release0(Locker lock);
|
||||
|
||||
protected abstract boolean refresh(String key, String token, Duration expiration);
|
||||
public abstract boolean refresh(String key, String token, Duration expiration);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.laker.admin.framework.lock.impl.jdbc;
|
||||
|
||||
import com.laker.admin.framework.lock.api.LLock;
|
||||
import com.laker.admin.framework.lock.core.AbstractSimpleLock;
|
||||
import com.laker.admin.framework.lock.api.Locker;
|
||||
import com.laker.admin.framework.lock.core.AbstractSimpleILock;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
@@ -15,7 +15,7 @@ import java.time.Duration;
|
||||
* @author laker
|
||||
*/
|
||||
@Slf4j
|
||||
public class MysqlLock extends AbstractSimpleLock {
|
||||
public class MysqlILock extends AbstractSimpleILock {
|
||||
|
||||
/**
|
||||
* 原始sql 需要配合DuplicateKeyException使用,不优雅:INSERT INTO distribute_lock (lock_key, token, expire, thread_id) VALUES (?, ?, ?, ?);
|
||||
@@ -26,14 +26,14 @@ public class MysqlLock extends AbstractSimpleLock {
|
||||
public static final String REFRESH_FORMATTED_QUERY = "UPDATE distribute_lock SET expire = ? WHERE lock_key = ? AND token = ?;";
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
public MysqlLock(JdbcTemplate jdbcTemplate, TaskScheduler taskScheduler) {
|
||||
public MysqlILock(JdbcTemplate jdbcTemplate, TaskScheduler taskScheduler) {
|
||||
super(taskScheduler);
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
protected String acquire(final String key, final String token, final Duration expiration) {
|
||||
public String acquire(final String key, final String token, final Duration expiration) {
|
||||
final long now = System.currentTimeMillis();
|
||||
// 这里是为了删除由于一些异常导致的锁,因为db 没有ttl
|
||||
final int expired = jdbcTemplate.update(DELETE_EXPIRED_FORMATTED_QUERY, now);
|
||||
@@ -45,7 +45,7 @@ public class MysqlLock extends AbstractSimpleLock {
|
||||
|
||||
@Override
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
protected boolean release0(LLock lock) {
|
||||
public boolean release0(Locker lock) {
|
||||
String key = lock.getKey();
|
||||
String token = lock.getToken();
|
||||
final int deleted = jdbcTemplate.update(RELEASE_FORMATTED_QUERY, key, token);
|
||||
@@ -64,7 +64,7 @@ public class MysqlLock extends AbstractSimpleLock {
|
||||
|
||||
@Override
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
protected boolean refresh(final String key, final String token, final Duration expiration) {
|
||||
public boolean refresh(final String key, final String token, final Duration expiration) {
|
||||
final long now = System.currentTimeMillis();
|
||||
final long expireAt = expiration.toMillis() + now;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.laker.admin.framework.lock.impl.redis;
|
||||
|
||||
import com.laker.admin.framework.lock.api.LLock;
|
||||
import com.laker.admin.framework.lock.core.AbstractSimpleLock;
|
||||
import com.laker.admin.framework.lock.api.Locker;
|
||||
import com.laker.admin.framework.lock.core.AbstractSimpleILock;
|
||||
import io.lettuce.core.RedisCommandInterruptedException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.RedisSystemException;
|
||||
@@ -18,7 +18,7 @@ import java.util.List;
|
||||
* @author laker
|
||||
*/
|
||||
@Slf4j
|
||||
public class RedisLock extends AbstractSimpleLock {
|
||||
public class RedisILock extends AbstractSimpleILock {
|
||||
|
||||
private static final String LOCK_SCRIPT = "return redis.call('SET', KEYS[1], ARGV[1], 'PX', tonumber(ARGV[2]), 'NX') and true or false";
|
||||
|
||||
@@ -34,15 +34,15 @@ public class RedisLock extends AbstractSimpleLock {
|
||||
private final RedisScript<Boolean> lockScript = new DefaultRedisScript<>(LOCK_SCRIPT, Boolean.class);
|
||||
private final RedisScript<Boolean> lockReleaseScript = new DefaultRedisScript<>(LOCK_RELEASE_SCRIPT, Boolean.class);
|
||||
private final RedisScript<Boolean> lockRefreshScript = new DefaultRedisScript<>(LOCK_REFRESH_SCRIPT, Boolean.class);
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
private final StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
public RedisLock(final StringRedisTemplate stringRedisTemplate, TaskScheduler taskScheduler) {
|
||||
public RedisILock(final StringRedisTemplate stringRedisTemplate, TaskScheduler taskScheduler) {
|
||||
super(taskScheduler);
|
||||
this.stringRedisTemplate = stringRedisTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String acquire(final String key, final String token, final Duration expiration) {
|
||||
public String acquire(final String key, final String token, final Duration expiration) {
|
||||
|
||||
// final List<String> singletonKeyList = Collections.singletonList(key(key));
|
||||
// 使用这个也行
|
||||
@@ -50,7 +50,7 @@ public class RedisLock extends AbstractSimpleLock {
|
||||
// 这个等价于 SET key token NX PX 5000
|
||||
Boolean locked = stringRedisTemplate.opsForValue().setIfAbsent(key(key), token, expiration);
|
||||
log.info("Tried to acquire lock for key {} with token {}. Locked: {}", key, token, locked);
|
||||
return locked ? token : null;
|
||||
return Boolean.TRUE.equals(locked) ? token : null;
|
||||
}
|
||||
|
||||
private String key(String key) {
|
||||
@@ -58,11 +58,11 @@ public class RedisLock extends AbstractSimpleLock {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean release0(LLock lock) {
|
||||
public boolean release0(Locker lock) {
|
||||
String key = lock.getKey();
|
||||
String token = lock.getToken();
|
||||
final List<String> singletonKeyList = Collections.singletonList(key(key));
|
||||
final boolean released = stringRedisTemplate.execute(lockReleaseScript, singletonKeyList, token);
|
||||
final boolean released = Boolean.TRUE.equals(stringRedisTemplate.execute(lockReleaseScript, singletonKeyList, token));
|
||||
if (released) {
|
||||
log.info("Release script deleted the record for key {} with token {}", key, token);
|
||||
} else {
|
||||
@@ -72,12 +72,12 @@ public class RedisLock extends AbstractSimpleLock {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean refresh(final String key, final String token, final Duration expiration) {
|
||||
public boolean refresh(final String key, final String token, final Duration expiration) {
|
||||
final List<String> singletonKeyList = Collections.singletonList(key(key));
|
||||
|
||||
boolean refreshed = false;
|
||||
try {
|
||||
refreshed = stringRedisTemplate.execute(lockRefreshScript, singletonKeyList, token, String.valueOf(expiration.toMillis()));
|
||||
refreshed = Boolean.TRUE.equals(stringRedisTemplate.execute(lockRefreshScript, singletonKeyList, token, String.valueOf(expiration.toMillis())));
|
||||
if (refreshed) {
|
||||
log.info("Refresh script updated the expiration for key {} with token {} to {}", key, token, expiration);
|
||||
} else {
|
||||
@@ -3,24 +3,21 @@ package com.laker.admin.module.sys.controller;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||
import com.laker.admin.framework.aop.metrics.Metrics;
|
||||
import com.laker.admin.framework.exception.BusinessException;
|
||||
import com.laker.admin.framework.lock.api.LLock;
|
||||
import com.laker.admin.framework.lock.api.Lock;
|
||||
import com.laker.admin.framework.lock.api.ILock;
|
||||
import com.laker.admin.framework.lock.api.Locker;
|
||||
import com.laker.admin.framework.model.PageResponse;
|
||||
import com.laker.admin.framework.model.Response;
|
||||
import com.laker.admin.module.sys.entity.SysDict;
|
||||
import com.laker.admin.module.sys.service.ISysDictService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -36,54 +33,54 @@ import java.util.Objects;
|
||||
@RequestMapping("/sys/dict")
|
||||
@Metrics
|
||||
public class SysDictController {
|
||||
@Autowired
|
||||
ISysDictService sysDictService;
|
||||
final ISysDictService sysDictService;
|
||||
|
||||
@Autowired
|
||||
Lock lock;
|
||||
final ILock ILock;
|
||||
|
||||
public SysDictController(ISysDictService sysDictService, ILock ILock) {
|
||||
this.sysDictService = sysDictService;
|
||||
this.ILock = ILock;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation(value = "分页查询")
|
||||
public PageResponse pageAll(@RequestParam(required = false, defaultValue = "1") long page,
|
||||
@RequestParam(required = false, defaultValue = "10") long limit) {
|
||||
Page roadPage = new Page<>(page, limit);
|
||||
LambdaQueryWrapper<SysDict> queryWrapper = new QueryWrapper().lambda();
|
||||
Page pageList = sysDictService.page(roadPage, queryWrapper);
|
||||
public PageResponse<List<SysDict>> pageAll(@RequestParam(required = false, defaultValue = "1") long page,
|
||||
@RequestParam(required = false, defaultValue = "10") long limit) {
|
||||
Page<SysDict> roadPage = new Page<>(page, limit);
|
||||
LambdaQueryWrapper<SysDict> queryWrapper = new LambdaQueryWrapper<>();
|
||||
Page<SysDict> pageList = sysDictService.page(roadPage, queryWrapper);
|
||||
return PageResponse.ok(pageList.getRecords(), pageList.getTotal());
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@ApiOperation(value = "新增或者更新")
|
||||
@SaCheckPermission("dict.update")
|
||||
public Response saveOrUpdate(@RequestBody SysDict param) {
|
||||
LLock llock = lock.acquire(param.getDictCode(), Duration.ofSeconds(10));
|
||||
if (Objects.isNull(llock)) {
|
||||
throw new BusinessException("其他人正在处理中,请稍后重试");
|
||||
}
|
||||
public Response<Boolean> saveOrUpdate(@RequestBody SysDict param) {
|
||||
Locker locker = ILock.acquire(param.getDictCode(), Duration.ofSeconds(10));
|
||||
try {
|
||||
return Response.ok(sysDictService.saveOrUpdate(param));
|
||||
} finally {
|
||||
lock.release(llock);
|
||||
ILock.release(locker);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@ApiOperation(value = "根据id查询")
|
||||
public Response get(@PathVariable Long id) {
|
||||
public Response<SysDict> get(@PathVariable Long id) {
|
||||
return Response.ok(sysDictService.getById(id));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@ApiOperation(value = "根据id删除")
|
||||
@SaCheckPermission("dict.delete")
|
||||
public Response delete(@PathVariable Long id) {
|
||||
public Response<Boolean> delete(@PathVariable Long id) {
|
||||
return Response.ok(sysDictService.removeById(id));
|
||||
}
|
||||
|
||||
@DeleteMapping("/batch/{ids}")
|
||||
@ApiOperation(value = "根据批量删除ids删除")
|
||||
@SaCheckPermission("dict.delete")
|
||||
public Response batchRemove(@PathVariable Long[] ids) {
|
||||
public Response<Boolean> batchRemove(@PathVariable Long[] ids) {
|
||||
return Response.ok(sysDictService.removeByIds(CollUtil.toList(ids)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user