如何解决在SpringBoot中管理并发POST请求最佳实践
我正在使用SpringBoot构建REST-API并使用此Controller。
foo
我想确保API使用者不会向具有相同@RestController
class EmployeeController {
private final EmployeeRepository repository;
EmployeeController(EmployeeRepository repository) {
this.repository = repository;
}
@GetMapping("/employees")
List<Employee> all() {
return repository.findAll();
}
@PostMapping("/employees")
Employee newEmployee(@RequestBody Employee newEmployee) {
return repository.save(newEmployee);
}
的多个并发POST请求发送垃圾邮件。我知道可以在保存数据库之前检查该实体是否已经存在,但是恐怕性能会很差。我还已经注意到,您可以在实体中使用Employee
之类的注释来对现有Entity的更新进行更多保存。
但是在Spring中,还有没有一种方法或最佳实践来处理带有潜在新实体的POST请求?
解决方法
您对POST /employees
端点有什么样的请求吞吐量?虽然性能很重要,但过早的优化几乎总是会导致您的代码比所需要的更丑陋,从而几乎没有收益。
按照您当前的代码立场,多个并发POST /employees
请求将以先到先得的原则结束,在此基础上,您的应用程序中具有给定UNIQUE
约束的第一位用户(有望实施)由您的基础DBMS创建),此后(针对同一用户)的所有其他操作都会由于例如ConstraintViolationException
(映射到例如DataIntegrityViolationException
)。从这个角度来看(只要您没有复杂的分布式DBMS设置),仍然可以保证数据的一致性。
当然,缺点是将返回的错误消息是:
- 特定于供应商并泄漏了底层实现(例如,我们正在向客户端显示我们正在使用Hibernate)
- 客户端可能无法解析。
如果相反,请将实现更改为以下内容:
@PostMapping("/employees")
Employee newEmployee(@RequestBody Employee newEmployee) {
verifyEmployeeDoesNotExist(newEmployee);
return repository.save(newEmployee);
}
private void verifyUserDoesNotExist(Employee employee) {
if (repository.exists(newEmployee) {
throw new EmployeeAlreadyExistsException("Employee " + newEmployee.getName() + " already exists";
}
}
然后,您可以更轻松地控制端点和基础流程的控制流,这有可能允许更容易消化的异常处理。甚至可以通过添加例如自定义异常,其中还包含一些预定义的error code
代码,例如error 409 code 1010 Employee already exists
。
当然,Spring为Hibernate内置的异常转换(例如HibernateExceptionTranslator
)对于您的用例可能已经足够好了,甚至可以扩展,甚至可以泛化此扩展。
最后,最佳实践是使您的代码干净,可读和可维护。然后开始添加功能来监视您的代码。 之后,只有如果您对性能有疑问,仍可以对其进行优化。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。