开发中遇到的问题

1. 项目运行问题:

  springboot项目编译不报错,运行就直接出错,在其他机器上可以运行,则很有可能是maven依赖问题,将pom坐标下的所有包都清掉,从新导入,打开idea maven工具查看是否有报错,有时会出现早就将依赖去掉,但是maven并没有清理掉包的现象,导致项目依赖出现问题。

2. spring boot 运行测试类时:Error creating bean with name 'serverEndpointExporter' 问题

  这是因为 WebSocket需要依赖Tomcat容器,解决方案,在springBootTest加入以下内容

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

@SpringBootTest的webEnvironment属性来进一步优化测试的运行方式:

  • MOCK : 加载一个WebApplicationContext并提供一个模拟servlet环境。嵌入式servlet容器在使用此注释时不会启动。如果servlet API不在你的类路径上,这个模式将透明地回退到创建一个常规的非web应用程序上下文。可以与@AutoConfigureMockMvc结合使用,用于基于MockMvc的应用程序测试。
  • RANDOM_PORT : 加载一个EmbeddedWebApplicationContext并提供一个真正的servlet环境。嵌入式servlet容器启动并在随机端口上侦听。
  • DEFINED_PORT 加载一个EmbeddedWebApplicationContext并提供一个真正的servlet环境。嵌入式servlet容器启动并监听定义的端口(即从application.properties或默认端口8080)。
  • NONE : 使用SpringApplication加载ApplicationContext,但不提供任何servlet环境(模拟或其他)。

3.高并发下的幂等性问题和解决方案

  幂等:只要调用接口成功且参数一致,外部对接口的多次调用得到的结果是相同的。即执行多次和一次的效果是一样的。

  场景:在订单支付过程中一般会存在两步骤,①先查询一下订单是否已经支付过,②如果已经支付过,则返回支付成功;如果没有支付,进行支付流程,修改订单状态为‘已支付’。

  问题:因为第②步依赖第①步的查询结果,无法保证原子性的。在高并发下就会出现下面的情况:第二次请求的时候,如果第一次请求第②步订单状态还没有修改为‘已支付状态’,那么又会发起一次相同的业务处理,导致最终产生两条相同的数据。

解决:

    1.使用乐观锁:采用版本号来识别本次操作的版本号是否和上次一致,一般使用自增的字段做版本号,这样可以避免原子性问题。

      更新语句:UPDATE tab1 SET col1=1,version=version+1 WHERE version=#version#

  2.加入防重表:使用订单号orderNo做为防重表的唯一索引,每次请求都根据订单号向防重表中插入一条数据。第一次请求查询订单支付状态,如果订单没有支付,进行支付操作,无论成功与否,执行完后更新订单状态为成功或失败,然后删除防重表中的数据。后续的订单因为防重表中唯一索引而插入失败,则返回操作失败。直到第一次的请求完成(成功或失败)。可以看出防重表作用是加锁的功能。

  3.分布式锁:这里使用的防重表可以使用分布式锁代替,比如Redis,Redis是单线程的,保证原子性操作。订单发起支付请求,支付系统会去Redis缓存中查询是否存在该订单号的Key,如果不存在,则向Redis增加Key为订单号。查询订单支付已经支付,如果没有则进行支付,支付完成后删除该订单号的Key。通过Redis做到了分布式锁,只有这次订单订单支付请求完成,下次请求才能进来。相比去重表,将放并发做到了缓存中,较为高效。思路相同,同一时间只能完成一次支付请求。

    

  






原文地址:https://www.cnblogs.com/lwjQAQ/p/11288510.html