我 试图 通过 Spring 来 人为 地 违反 约束 , 而 不是 从 DB 中 抛出 异常 ( 一 位 Maven 说 DB 产生 的 错误 会 造成 很 高 的 性能 代价 ) :
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
@Component
public class AccountValidator implements org.springframework.validation.Validator {
@Autowired
private Validator validator;
private final AccountService accountService;
public AccountValidator(@Qualifier("accountServiceAlias")AccountService accountService) {
this.accountService = accountService;
}
@Override
public boolean supports(Class<?> clazz) {
return AccountRequestDTO.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
Set<ConstraintViolation<Object>> validates = validator.validate(target);
for (ConstraintViolation<Object> constraintViolation : validates) {
String propertyPath = constraintViolation.getPropertyPath().toString();
String message = constraintViolation.getMessage();
errors.rejectValue(propertyPath, "", message);
}
AccountRequestDTO account = (AccountRequestDTO) target;
if(accountService.getPhone(account.getPhone()) != null){
errors.rejectValue("phone", "", "Validator in action! This number is already in use.");
}
}
}
中 的 每 一 个
然而 , * * validate ( ) * * 方法 的 第 二 部分 由于 我 无法 理解 的 原因 而 始终 无法 工作 , 并且 总是 从 控制 器 传递 一 个 调用 , 以便 在 * * try-catch * * 块 中 处理 , 从而 从 DB 抛出 异常 :
public void saveAccount(AccountRequestDTO accountRequestDTO) throws Exception {
LocalDate birthday = LocalDate.parse(accountRequestDTO.getBirthday());
if (LocalDate.from(birthday).until(LocalDate.now(), ChronoUnit.YEARS) < 18) {
throw new RegistrationException("You must be 18+ to register");
}
Account account = new Account(accountRequestDTO.getName(), accountRequestDTO.getSurname(),
accountRequestDTO.getPhone(), birthday, BCrypt.hashpw
(accountRequestDTO.getPassword(), BCrypt.gensalt(4)));
account.addRole(Role.CLIENT);
try {
accountRepository.save(account);
}
catch (RuntimeException exc) {
throw new PersistenceException("Database exception: this number is already in use.");
}
}
格式
下面 是 一 个 控制 器 方法 :
@PostMapping("/confirm")
public String signIn(@ModelAttribute("account") @Valid AccountRequestDTO accountRequestDTO,
BindingResult result, Model model) {
accountValidator.validate(accountRequestDTO, result);
if(result.hasErrors()) {
return "/auth/register";
}
try {
accountService.saveAccount(accountRequestDTO);
}
catch (Exception exc) {
model.addAttribute("message", exc.getMessage());
return "/auth/register";
}
return "/auth/login";
}
格式
服务 时 :
@Transactional(readOnly = true)
public String getPhone(String phone){
return accountRepository.getPhone(phone);
}
格式
JpaRepository 查询 :
@Query("SELECT phone FROM Account accounts WHERE phone=:check")
String getPhone(String check);
格式
测试 为 绿色 :
@BeforeAll
static void prepare() {
search = new String("0000000000");
}
@BeforeEach
void set_up() {
account = new Account
("Admin", "Adminov", "0000000000", LocalDate.of(2001, 01, 01), "superadmin");
accountRepository.save(account);
}
@Test
void check_if_phone_presents() {
assertThat(accountRepository.getPhone(search).equals(account.getPhone())).isTrue();
}
@Test
void check_if_phone_not_presents() {
String newPhone = "9999999999";
assertThat(accountRepository.getPhone(newPhone)).isNull();
}
@AfterEach
void tear_down() {
accountRepository.deleteAll();
account = null;
}
@AfterAll
static void clear() {
search = null;
}
格式
1条答案
按热度按时间lxkprmvk1#
您需要注册您的验证器。
在定义了验证器之后,我们需要将其Map到一个特定的事件,该事件在请求被接受之后生成。
这可以通过三种方式实现:
添加名为“beforeCreateAccountValidator”的组件注解。Sping Boot 将识别前缀beforeCreate,该前缀确定我们要捕获的事件,并且它还将从组件名称中识别WebsiteUser类。
在应用程序上下文中创建带有@Bean注解的Bean:
手动配准: