当前位置: 首页 > news >正文

武汉网站seo外包推广普通话ppt课件

武汉网站seo外包,推广普通话ppt课件,企业高端网站建设需要注意哪些事项,wordpress调用文章内容图片前言 在项目中,经常需要使用Redisson分布式锁来保证并发操作的安全性。在未引入基于注解的分布式锁之前,我们需要手动编写获取锁、判断锁、释放锁的逻辑,导致代码重复且冗长。为了简化这一过程,我们引入了基于注解的分布式锁&…

前言

在项目中,经常需要使用Redisson分布式锁来保证并发操作的安全性。在未引入基于注解的分布式锁之前,我们需要手动编写获取锁、判断锁、释放锁的逻辑,导致代码重复且冗长。为了简化这一过程,我们引入了基于注解的分布式锁,通过一个注解就可以实现获取锁、判断锁、处理完成后释放锁的逻辑。这样可以大大简化代码,提高开发效率。

目标

使用@DistributedLock即可实现获取锁,判断锁,处理完成后释放锁的逻辑。

@RestController
public class HelloController {@DistributedLock@GetMapping("/helloWorld")public void helloWorld() throws InterruptedException {System.out.println("helloWorld");Thread.sleep(100000);}
}

涉及知识

  • SpringBoot
  • Spring AOP
  • Redisson
  • 自定义注解
  • 统一异常处理
  • SpEL表达式

代码实现

引入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.21.3</version>
</dependency>
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>

注解类

/*** 分布式锁注解* @author 只有影子*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DistributedLock {/*** 获取锁失败时,默认的错误描述*/String errorDesc() default "任务正在处理中,请耐心等待";/*** SpEL表达式,用于获取锁的key* 示例:* "#name"则从方法参数中获取name的值作为key* "#user.id"则从方法参数中获取user对象中的id作为key*/String[] keys() default {};/*** key的前缀,为空时取类名+方法名*/String prefix() default "";
}

切面类

/*** 分布式锁切面类* @author 只有影子*/
@Slf4j
@Aspect
@Component
public class DistributedLockAspect {@Resourceprivate RedissonClient redissonClient;private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();@Around("@annotation(distributedLock)")public Object around(ProceedingJoinPoint joinPoint,DistributedLock distributedLock) throws Throwable {String redisKey = getRedisKey(joinPoint, distributedLock);log.info("拼接后的redisKey为:" + redisKey);RLock lock = redissonClient.getLock(redisKey);if (!lock.tryLock()) {// 可以使用自己的异常类,演示用RuntimeExceptionthrow new RuntimeException(distributedLock.errorDesc());}// 执行被切面的方法try {return joinPoint.proceed();} finally {lock.unlock();}}/*** 动态解密参数,拼接redisKey* @param joinPoint* @param distributedLock  注解* @return*/private String getRedisKey(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();EvaluationContext context = new MethodBasedEvaluationContext(TypedValue.NULL, method, joinPoint.getArgs(), PARAMETER_NAME_DISCOVERER);StringBuilder redisKey = new StringBuilder();// 拼接redis前缀if (StringUtil.isNotBlank(distributedLock.prefix())) {redisKey.append(distributedLock.prefix()).append(":");} else {// 获取类名String className = joinPoint.getTarget().getClass().getSimpleName();// 获取方法名String methodName = joinPoint.getSignature().getName();redisKey.append(className).append(":").append(methodName).append(":");}ExpressionParser parser = new SpelExpressionParser();for (String key : distributedLock.keys()) {// keys是个SpEL表达式Expression expression = parser.parseExpression(key);Object value = expression.getValue(context);redisKey.append(ObjectUtils.nullSafeToString(value));}return redisKey.toString();}
}

统一异常处理类

/*** 全局异常处理类* @author 只有影子*/
@RestControllerAdvice
public class ExceptionHandle {@ExceptionHandler(Exception.class)@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)public String sendErrorResponseSystem(Exception e) {// 这里只是模拟返回值,实际项目中一般都是返回封装好的统一返回类return e.getMessage();}
}

还需要将redis配置读入,这里就不体现

使用示例

1. 无参方法或者需要加方法级的锁

@DistributedLock
@GetMapping("/helloWorld")
public void helloWorld() throws InterruptedException {System.out.println("helloWorld");Thread.sleep(100000);
}

调用接口:http://localhost:8080/helloWorld

拼接后的redisKey为:HelloController:helloWorld:

可以看到,无参方法的key为HelloController:helloWorld:,其中HelloController为类名,helloWorld为方法名,因为是无参方法,所以没有接下来的参数。

这时候,再次调用改接口,则不会再进去接口,会被切面类直接拦截,返回如下结果:

image-20231123222250866

在实际生产使用中,这种情况一般被用来在自动任务上标注,因为在集群环境中自动任务同一时间一般只需要启动一个。

2. 有参数方法,其中key从name中取值

@DistributedLock(keys = "#name")
@GetMapping("/hello1")
public String hello1(String name) throws InterruptedException {String s = "hello " + name;System.out.println(s);Thread.sleep(100000);return s;
}

调用接口为:http://localhost:8080/hello1?name=hurry

拼接后的redisKey为:HelloController:hello1:hurry

这时候,再通过hurry这个名称调用时,就不会再处理,而name换为zhangsan时,则就能正常进入接口。

这时候redis中的key为

> 127.0.0.1@6379 connected!
> keys *
HelloController:hello2:zhangsan
HelloController:hello2:hurry

实际业务中,需要根据不同的参数值进行加锁的场景。

3. 有参数方法,其中key需要从user对象中获取name

@DistributedLock(keys = "#user.name")
@GetMapping("/hello2")
public String hello2(User user) throws InterruptedException {String s = "hello " + user.getName();System.out.println(s);Thread.sleep(100000);return s;
}

需要从某个对象中获取指定属性作为key的场景

4.有参数方法,其中key从name上取值并指定前缀

@DistributedLock(keys = "#name",prefix = "testPrefix")
@GetMapping("/hello3")
public String hello3(String name) throws InterruptedException {String s = "hello " + name;System.out.println(s);Thread.sleep(100000);return s;
}

需要指定key前缀的场景

最后

由于文章篇幅原因,很多东西没有深入的讲解,但是基于以上代码基本实现了基于注解的分布式锁,可以大大提到开发效率。如果还有其他需要拓展的功能,可以通过在注解类增加属性及在切面类中通过不同的属性进行不同的处理来实现。

http://www.dinnco.com/news/77240.html

相关文章:

  • 用什么语言能写网站吗谈谈你对互联网营销的认识
  • 可以做关键词优化的免费网站关键词排名优化
  • php网站开发的成功经历seo需要掌握什么技能
  • 企业域名邮箱张家口网站seo
  • 资源库网站开发什么搜索引擎搜索最全
  • 安阳门户网站优化网站的意思
  • 生态养殖网站模板深圳英文站seo
  • 淄博网站建设选择臻动传媒海南百度推广代理商
  • 做网站招标网站优化seo是什么意思
  • 微信版网站开发seo代理计费系统
  • 美国人做网站seo基础课程
  • wordpress发布的文章如何不显示东莞百度推广优化公司
  • 怎么创作自己的网站手机建站系统
  • 汽车品牌大全汽车网济南网络优化网址
  • 找人做网站注意长沙seo网络营销推广
  • 自制响应式网站游戏广告投放平台
  • 做网站建设哪家公司靠谱李勇seo博客
  • asp 开发的大型网站徐州seo外包平台
  • 购物网站建设所需软件优化关键词具体要怎么做
  • 贵阳网站制作贵阳网站建设哪家好5118大数据平台官网
  • 上海网站建设建站郑州seo排名优化
  • 营销网站建设实训总结百度小说排行榜风云榜
  • 做视频免费模板下载网站关键词排名推广软件
  • 网站适配手机屏幕泉州百度关键词优化
  • 公司网站必须做可信认证吗seo页面代码优化
  • 怎么做门户网站网页设计作品集
  • 自己做网站前端开发精准广告投放
  • 新疆宏远建设集团网站文件外链生成网站
  • 住房和城乡建设局网站网络平台怎么推广
  • 做网站多少钱怎样在百度上打广告