如何在Rest API中编写自定义验证?

时间:2019-05-15 13:11:14

标签: java spring spring-boot spring-mvc spring-data-jpa

在Spring引导中。 我想进行字段验证,如果输入在数据库中不存在,则返回错误。 我正在尝试为多个输入字段编写自定义注释。 控制器如下

@RestController
@Api(description = "The Mailer controller which provides send email functionality")
@Validated
public class SendMailController {
    @Autowired
    public SendMailService sendemailService;
    org.slf4j.Logger logger = LoggerFactory.getLogger(SendMailService.class);

    @RequestMapping(method = RequestMethod.POST, value = "/sendMail", consumes = {MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}, produces = {"text/xml", "application/json"})
    @ResponseBody
    @Async(value = "threadPoolTaskExecutor")
    @ApiOperation("The main service operation which sends one mail to one or may recipient as per the configurations in the request body")
    public Future<SendMailResult> sendMail(@ApiParam("Contains the mail content and configurations to be used for sending mail") @Valid @RequestBody MailMessage message) throws InterruptedException {

        SendMailResult results = new SendMailResult();
        try {
            sendemailService.sendMessages(message);
            long txnid = sendemailService.createAudit (message);
            results.setTxnid (txnid);
            results.setStatus("SUCCESS");
        } catch(MessagingException | EmailServiceException e) {
            logger.error("Exception while processing sendMail " + e);
            results.setStatus("FAILED");
            // TODO Handle error create results
            e.printStackTrace();
        } catch(Exception e) {
            logger.error("Something went wrong " + e);
            results.setStatus("FAILED");
            // TODO Handle error create results
            e.printStackTrace();
        }

        return new AsyncResult<SendMailResult>(results);
    }

}

与请求映射的一个DTO

public class MailContext {
    @NotNull
    private String clientId;
    @NotNull
    private String consumer;


    public int getClientId() {
        return Integer.parseInt(clientId);
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }


    public String toJson() throws JsonProcessingException {

        ObjectMapper mapper = new ObjectMapper();
        String writeValueAsString = mapper.writeValueAsString(this);
        return writeValueAsString;
    }
    }

请求xml

<mailMessage>
    <mailContext>
        <clientId>10018</clientId>
        <consumer>1</consumer>
    </mailContext>
</mailMessage>
  1. 如果要在请求中提供,我想编写一个自定义批注来验证数据库中存在的客户端(表client_tbl)。
  2. 消费者:存在于数据库表cunsumer_tbl

如果这些不存在于数据库中则发送错误消息,否则调用服务方法。

请提出如何编写带有错误的自定义注释。

1 个答案:

答案 0 :(得分:1)

我知道另一种验证方法。 在控制器内部,您可以注册验证器。

@InitBinder
public void setup(WebDataBinder webDataBinder) {
    webDataBinder.addValidators(dtoValidator);
}

例如dtoValidator是Spring Bean的实例,它必须实现org.springframework.validation.Validator。

因此,您只需要实现两种方法:supports()和validate(Object target,Errors errors);

在supports()方法中,您可以执行任何决定对象是否应由此验证器验证的操作。 (例如,您可以创建一个WithClientIdDto接口,如果被测试的对象是AsAssignableFrom(),则可以执行此验证。也可以使用反射功能检查自定义注释是否出现在任何字段上)

例如:(AuthDtoValidator.class)

@Override
public boolean supports(Class<?> clazz) {
    return AuthDto.class.isAssignableFrom(clazz);
}

@Override
public void validate(Object target, Errors errors) {
    final AuthDto dto = (AuthDto) target;
    final String phone = dto.getPhone();
    if (StringUtils.isEmpty(phone) && StringUtils.isEmpty(dto.getEmail())) {
        errors.rejectValue("email", "", "The phone or the email should be defined!");
        errors.rejectValue("phone", "", "The phone or the email should be defined!");
    }

    if (!StringUtils.isEmpty(phone)) {
        validatePhone(errors, phone);
    }
}

更新: 你可以做到的。

创建注释 例如:

@Target({ FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = ClientIdValidator.class)
@Documented
public @interface ClientId {

  String message() default "{some msg}";

  Class<?>[] groups() default { };

  Class<? extends Payload>[] payload() default { };

}

并实现此验证器:

class ClientIdValidator implements ConstraintValidator<ClientId, Long> {

  @Override
  public boolean isValid(Long value, ConstraintValidatorContext context) {
   //validation logc
   }
}

您可以在这里找到更多详细信息:https://reflectoring.io/bean-validation-with-spring-boot/