1.什么是接口幂等性?
接口程序多次执行所产生的影响均与一次执行的影响相同。
2.什么情况下要用到幂等性
在写入数据时,保证某个数据多次写入而数据库只插入一次数据,比如支付问题,用户支付一次就可完成商品交易,当网络卡顿时,用户多次点击付款按钮,最终只执行一次支付,避免重复支付给用户带来的经济损失。
3.使用拦截器实现接口幂等性
这里,模拟一个场景:在数据库中添加商品(name)与编号(code),code是商品的唯一标识id,不可重复,也就是说多次写入某个商品时数据库添加的数据只能有一个,避免了数据的重复性。
下面开始用拦截器实现功能:
首先,项目的代码(springboot项目)如下:
mapper:
public interface MiMapper {
/*
* 插入数据
* */
int insert(Mi mi);
/*
* 查询
* */
List find(String code);
}
MiMapper.xml:
<mapper namespace="com.example.mideng.mapper.MiMapper">
<insert id="insert" parameterType="com.example.mideng.pojo.Mi">
insert into t_mi(name,code) values (#{name},#{code})
</insert>
<select id="find" parameterType="String" resultType="com.example.mideng.pojo.Mi">
select code from t_mi where code=#{code}
</select>
</mapper>
service:
public interface MiService {
int insert(Mi mi);
/*
* 查询
* */
List find(String code);
}
serviceImpl:
@Service
public class MiServiceImplimplements MiService {
@Autowired
private MiMappermiMapper;
@Override
public int insert(Mi mi) {
return miMapper.insert(mi);
}
@Override
public List find(String code) {
return miMapper.find(code);
}
}
controller:
@Controller
public class WelcomeController {
@RequestMapping("/welcome")
public String wel(){
return "welcome";
}
}
@Controller
@RequestMapping("/mideng")
public class MiController {
@Autowired
private MiServicemiService;
@RequestMapping("/tijiao")
public String tijiao(Mi mi){
int insert =miService.insert(mi);
return "ok";
}
@RequestMapping("/tip")
public String tip(){
return "tip";
}
}
html文件就不特意写出了,就是简单的数据提交,记得加上th:标签,因为我这是用的thymeleaf模板。
添加拦截器实现幂等
(1)首先自定义拦截器,这里思路是获取http中的code参数,然后在调用MiService 查询该code在数据库中是否已经写入,返回的是list,如果list的容量为0,说明数据表还没插入数据,那么返回true,否则重定向到提示界面并且返回false,不让程序往下执行。
@Component
public class MiDengIntercepterimplements HandlerInterceptor {
@Autowired
private MiService miService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {
String code = request.getParameter("code");
List mi =miService.find(code);
if (mi.size()==0){
return true;
}else {
response.sendRedirect("/mideng/tip");
return false;
}
}
}
(2)配置拦截器
拦截器写好后记得配置,这里添加的拦截路径只有一个,就是提交接口,提交接口实现的功能是将数据写入数据表
@Configuration
public class TiJiaoConfigureimplements WebMvcConfigurer {
@Autowired
private MiDengIntercepter miDengIntercepter;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(miDengIntercepter).addPathPatterns("/mideng/tijiao");
}
}
演示:
运行项目,访问http://localhost:8080/welcome
先看下数据表,因为目前还没添加数据,所以是空的。
开始写入:
点击添加:
查看数据库:
数据成功写入。下面继续添加,这时code仍是123
点击添加:
会出现提示,查看数据库:
发现仍然只有一条数据,现在换一下名称看看效果:
点击添加:
查看数据库:
分析:因为是对code的拦截判断,所以表中不能有重复的code。下面换一下code试试:
点击添加:
查看数据库:
继续:
点击添加:
查看数据库:
发现只要code不同就可插入数据,如果插入的code相同,那么无论点击多少次添加,都只能执行一次,所以简单的幂等实现也就完成了。