我目前正在开发一个简单的验证器,该验证器将检查我的REST API消费者发送的注释输入值(我们称之为code
(是否已在我的数据库中注册,如果未注册,则返回BAD REQUEST。要做到这一点,我要求外部服务提供注册代码列表。然而,我使用的是微服务,我需要处理外部服务没有正确响应的情况,例如externalServiceClient.getCodes()
返回503。这是我的验证器代码:
import com.company.myservice.externalService.ExternalServiceClient;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class CodeAnnotationValidator implements ConstraintValidator<CodeAnnotation, String> {
private final ExternalServiceClient externalServiceClient;
@Override
public boolean isValid(String code, ConstraintValidatorContext context ){
if(code == null) {
return false;
}
String codeUpperCase = code.toUpperCase();
if (!codeUpperCase.matches("^[A-Z][A-Z]\d$")) {
return false;
}
List<String> expectedCodes = externalServiceClient.getCodes();
return expectedCodes.contains(codeUpperCase);
}
}
我面临的问题是,当我在尝试联系外部服务时遇到任何异常时,无论是503还是404,我都希望返回INTERNAL_SERVER_ERROR。然而,isValid
方法返回400,这错误地归咎于我的API消费者:
c.e.c.e.advice.CommonControllerAdvice : Validation exception: HV000028: Unexpected exception during isValid call.
我已经尝试捕获异常,但它不起作用,因为isValid
是一个被覆盖的方法,我不能只在它上面添加throws
有没有可能克服这个问题并返回错误代码500而不是400?
我不知道是否有更简单的方法,但你可以:
- 捕获来自
externalServiceClient.getCodes()
的任何异常并手动设置ConstraintViolation(请参阅ConstraintValidatorContext
上的方法( - 使用
@ControllerAdvice
捕获ConstraintViolationException
并检查消息,然后返回适当的状态代码
但这似乎很复杂,可能表明您想要做的并不是验证器的工作,因此可能不应该在验证阶段进行此检查,而应该在正常的服务调用阶段进行。