言尽于此,完结
无论是一个初级的 coder,高级的程序员,还是顶级的系统架构师,应该都有深刻的领会到设计模式的重要性。
- 第一,设计模式能让专业人之间交流方便,如下:
程序员A:这里我用了XXX设计模式
程序员B:那我大致了解你程序的设计思路了
- 第二,易维护
项目经理:今天客户有这样一个需求…
程序员:明白了,这里我使用了XXX设计模式,所以改起来很快
- 第三,设计模式是编程经验的总结
程序员A:B,你怎么想到要这样去构建你的代码
程序员B:在我学习了XXX设计模式之后,好像自然而然就感觉这样写能避免一些问题
- 第四,学习设计模式并不是必须的
程序员A:B,你这段代码使用的是XXX设计模式对吗?
程序员B:不好意思,我没有学习过设计模式,但是我的经验告诉我是这样写的
从设计思想解读开源框架,一步一步到Spring、Spring5、SpringMVC、MyBatis等源码解读,我都已收集整理全套,篇幅有限,这块只是详细的解说了23种设计模式,整理的文件如下图一览无余!
搜集费时费力,能看到此处的都是真爱!
需要注意的是,为了防止多次请求同时到达服务器,导致多次同时处理,我们需要在Redis中加锁,可以使用Redis的setnx命令或者分布式锁来实现。另外,为了保证幂等性,我们需要保证请求是幂等的,即多次请求的结果都是一致的。如果请求不是幂等的,那么我们需要对请求进行去重处理,以保证只有一个请求被处理。
2. 实现方案
2.1 自定义注解
为了实现接口的幂等性,我们需要先定义一个自定义注解。注解的作用是标记一个方法是否支持幂等性。如果支持幂等性,那么就需要对该方法进行特殊处理,使得多次调用该方法不会对结果产生影响。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Idempotent {
}
2.2 AOP切面
我们可以使用AOP来判断一个方法是否被标记了@Idempotent
注解。如果被标记了注解,那么就需要对该方法进行特殊处理,以实现幂等性。
@Aspect
@Component
public class IdempotentAspect {
private final RedisTemplate redisTemplate;
@Autowired
public IdempotentAspect(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Around("@annotation(com.example.demo.annotation.Idempotent)")
public Object idempotent(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取请求参数
Object[] args = joinPoint.getArgs();
// 获取请求方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 获取注解信息
Idempotent idempotent = method.getAnnotation(Idempotent.class);
String key = getKey(joinPoint);
// 判断是否已经请求过
if (redisTemplate.hasKey(key)) {
throw new RuntimeException("请勿重复提交");
}
// 标记请求已经处理过
redisTemplate.opsForValue().set(key, "1", idempotent.expire(), TimeUnit.SECONDS);
// 处理请求
return joinPoint.proceed(args);
}
/\*\*
\* 获取redis key
\*/
private String getKey(ProceedingJoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
String methodName = method.getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
Object[] args = joinPoint.getArgs();
StringBuilder sb = new StringBuilder();
sb.append(className).append(":").append(methodName);
for (Object arg : args) {
sb.append(":").append(arg.toString());
}
return sb.toString();
}
}
2.3 Redis存储
我们使用Redis来存储请求的处理状态。当一个请求被处理过后,我们会将请求的处理状态存储到Redis中,并设置一个过期时间,以保证不会一直占用Redis的内存空间。
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
return redisTemplate;
}
}
2.4 示例代码
下面是一个示例代码,该代码演示了如何使用@Idempotent
注解来实现接口的幂等性。
@RestController
public class DemoController {
@Autowired
private RedisTemplate redisTemplate;
@GetMapping("/demo")
@Idempotent(expire = 60)
public String demo(@RequestParam("id") Long id) {
// 处理请求
return "success";
}
}
3. 总结
本文介绍了如何使用SpringBoot自定义注解+AOP+redis来实现防接口幂等性重复提交。
我们首先定义了一个自定义注解@Idempotent,然后使用AOP来判断一个方法是否被标记了该注解。如果被标记了该注解,那么就需要对该方法进行特殊处理,以实现幂等性。最后,我们使用Redis来存储请求的处理状态,并设置一个过期时间,以保证不会一直占用Redis的内存空间。
以上就是本文的全部内容,更多技术类干货,点我主页持续追更~ 大家如果有技术类问题,欢迎和我们一起交流讨论
祝天天开心!
总结
这份面试题几乎包含了他在一年内遇到的所有面试题以及答案,甚至包括面试中的细节对话以及语录,可谓是细节到极致,甚至简历优化和怎么投简历更容易得到面试机会也包括在内!也包括教你怎么去获得一些大厂,比如阿里,腾讯的内推名额!
某位名人说过成功是靠99%的汗水和1%的机遇得到的,而你想获得那1%的机遇你首先就得付出99%的汗水!你只有朝着你的目标一步一步坚持不懈的走下去你才能有机会获得成功!
成功只会留给那些有准备的人!
ING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)收录**