我要实现的业务是根据年月生成自增的编码
添加所需包
<!-- redis 缓存操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
redis配置及redisson配置
1.yml
# redis 配置
redis:
# 地址
host: ip地址
# 端口,默认为6379
port: 6379
# 密码
password:
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
#编码头
LeaveCodeTop: PD
2.config
package com.ruoyi.framework.config;
import org.redisson.Redisson;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport
{
@Value("${spring.redis.host}")
private String host ;
@Value("${spring.redis.port}")
private String port;
@Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
{
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
@Bean
public Redisson redisson() {
Config config = new Config();
System.err.println("redis://" + host + ":"+port);
config.useSingleServer().setAddress("redis://" + host + ":"+port);
return (Redisson) Redisson.create(config);
}
}
自定义注解
package com.ruoyi.framework.aspectj;
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Rlock {
String localKey() default "redisLockAnnotation::";
long waitTime() default 5;
long leaseTime() default 10;
TimeUnit timeUnit() default TimeUnit.SECONDS;
}
建立aop切面
package com.ruoyi.framework.aspectj;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class RlockAspect {
@Autowired
private RedissonClient redissonClient;
@Pointcut("@annotation(com.ruoyi.framework.aspectj.Rlock)")
public void RlockAspect() { }
@Around("RlockAspect()")
public Object arround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object object = null;
RLock lock = null;
try {
Rlock rlockInfo = getRlockInfo(proceedingJoinPoint);
lock = redissonClient.getLock(getLocalKey(proceedingJoinPoint, rlockInfo));
System.err.println("获取锁");
if (lock != null) {
final boolean status = lock.tryLock(rlockInfo.waitTime(), rlockInfo.leaseTime(), rlockInfo.timeUnit());
if (status) {
System.err.println("执行业务代码");
object = proceedingJoinPoint.proceed();
}else{
throw new RuntimeException("获取锁失败");
}
System.err.println("业务代码执行完毕");
}
} finally {
if (lock != null && lock.isHeldByCurrentThread()) {
lock.unlock();
}
System.err.println("释放锁");
}
return object;
}
public Rlock getRlockInfo(ProceedingJoinPoint proceedingJoinPoint) {
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
return methodSignature.getMethod().getAnnotation(Rlock.class);
}
public String getLocalKey(ProceedingJoinPoint proceedingJoinPoint, Rlock rlockInfo) {
StringBuilder localKey = new StringBuilder();
final Object[] args = proceedingJoinPoint.getArgs();
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
String methodName = methodSignature.getMethod().getName();
localKey.append(rlockInfo.localKey()).append(methodName);
return localKey.toString();
}
}
使用
public static String LEAVE_CODE_TOP = "";
@Value("${LeaveCodeTop}")
private void setLeaveCodeTop(String LeaveCodeTop) {
PlaLeaveApplyServiceImpl.LEAVE_CODE_TOP = LeaveCodeTop;
}
@Transactional
@Rlock(localKey = "redisLockAnnotation", waitTime = 10, leaseTime = 10, timeUnit = TimeUnit.SECONDS)
@Override
public int getsss(PlaLeaveApply plaLeaveApply) {
QueryWrapper<PlaLeaveApply> queryWrapper = new QueryWrapper<>();
Calendar cal = Calendar.getInstance();
int years = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1;
String codeStr;
if (month < 10) {
codeStr = LEAVE_CODE_TOP + years + "0" + month;
} else {
codeStr = LEAVE_CODE_TOP + years + month;
}
queryWrapper.like("apply_no", codeStr);
queryWrapper.orderByDesc("id");
queryWrapper.last("LIMIT 1");
System.err.println("查询");
PlaLeaveApply plaLeaveApplypr = plaLeaveApplyMapper.selectOne(queryWrapper);
String applyNo;
if (StringUtils.isNotNull(plaLeaveApplypr)) {
String code = plaLeaveApplypr.getApplyNo();
System.err.println("code:" + code);
BigInteger codeInteger = new BigInteger(code.split(LEAVE_CODE_TOP)[1]);
applyNo = LEAVE_CODE_TOP + codeInteger.add(new BigInteger("1"));
} else {
applyNo = codeStr + "00001";
}
String personnelType = SecurityUtils.getLoginUser().getUser().getPersonnelType();
QueryWrapper<PlaLeaveFlow> qry = new QueryWrapper<>();
qry.eq("personnel_type", personnelType);
PlaLeaveFlow plaLeaveFlow = plaLeaveFlowMapper.selectOne(qry);
plaLeaveApply.setApplyNo(applyNo);
plaLeaveApply.setApplicantId(SecurityUtils.getLoginUser().getUser().getUserId());
plaLeaveApply.setDeptId(SecurityUtils.getLoginUser().getUser().getDeptId());
plaLeaveApply.setApplyTime(new Date());
plaLeaveApply.setState(1);
plaLeaveApply.setLeaveFlowId(plaLeaveFlow.getId());
plaLeaveApply.setCreateBy(String.valueOf(SecurityUtils.getLoginUser().getUser().getUserId()));
plaLeaveApply.setCreateTime(new Date());
plaLeaveApplyMapper.insert(plaLeaveApply);
PlaLeaveApplyDetail plaLeaveApplyDetail = new PlaLeaveApplyDetail();
plaLeaveApplyDetail.setApplyId(plaLeaveApply.getId());
plaLeaveApplyDetail.setStepId(0L);
return plaLeaveApplyDetailMapper.insert(plaLeaveApplyDetail);
}
效果截图
apply_no为编码字段