Java ConstraintViolationException-区分HttpStatus的spring和hibernate
我有一个自定义ConstraintValidator,它检查@RequestParam的有效值。 我还有hibernate实体,其中一些属性用@NotNull注释 默认行为是将ConstraintViolationException转换为HttpStatus=500。 这是从hibernate(即持久化实体等)引发错误所需要的。 但是我想为@RestController中的ConstraintViolations提高HttpStatus=400 @ExceptionHandler可以工作,但它无法区分从hibernate和spring层引发的冲突。我想这两个层都使用hibernate验证器依赖项,但我们应该能够区分它们Java ConstraintViolationException-区分HttpStatus的spring和hibernate,java,spring,validation,Java,Spring,Validation,我有一个自定义ConstraintValidator,它检查@RequestParam的有效值。 我还有hibernate实体,其中一些属性用@NotNull注释 默认行为是将ConstraintViolationException转换为HttpStatus=500。 这是从hibernate(即持久化实体等)引发错误所需要的。 但是我想为@RestController中的ConstraintViolations提高HttpStatus=400 @ExceptionHandler可以工作,但它无
@ExceptionHandler(ConstraintViolationException.class)
protected ResponseEntity<Object> handleConstraintViolationException(ConstraintViolationException ex, WebRequest request) {
return getObjectResponseEntity(ex, request, HttpStatus.BAD_REQUEST);
}
pozadavekFacade仅保存具有以下检查的已创建实体:
@NotBlank
@Column(length = 10, nullable = false)
private String idUzivatele;
由于代码分布在不同的层中,您应该能够在每个层中捕获
ConstraintViolationException
因此,在facade中,您可以捕获它并将其作为RuntimeException
(或任何您想要的异常)重新显示。然后,控制器层将此异常映射到500内部错误
在控制器层中,保留逻辑并将ConstraintViolationException
转换为400个错误请求响应
更新:您不必到处添加try-catch样板代码
示例:(不要复制粘贴此代码。这只是为了演示如何在多个位置摆脱try-catch块)
类服务{
字符串a(){抛出新的RuntimeException();}
字符串b(){抛出新的RuntimeException();}
字符串c(){抛出新的RuntimeException();}
}
类外观{
服务;
字符串a(){return tryRun(()->service.a());}
字符串b(){return tryRun(()->service.b());}
字符串c(){return tryRun(()->service.c());}
字符串tryRun(供应商运行){
试一试{
return run.get();
}
捕获(ConstraintViolationException e){
抛出新的RuntimeException(“”;//不要忘记从ConstraintViolationEx类型中提取有用的信息。
}
}
}
中间有层吗?或者您的控制器直接从用户输入构建实体?也许您可以在问题中添加更多的代码片段实际上是的。很少有层—使用服务的Facade类。我现在要用一些代码片段来编辑这个问题。我尽量避免这样做,因为这将是try/catch everywhere。我编辑我的回答我更喜欢一些技术性的全局解决方案(有很多代码需要修改),但如果我找不到其他解决方案,我会使用你的建议。非常感谢。
@GetMapping(value = "/{requirementId}/export-cisel", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public CisRadDto exportRequirementNumbers(
@PathVariable UUID requirementId,
@SupportedFileTypes @RequestParam(value = "formatSouboru", required = false) String fileFormat
) {
return pozadavekFacade.exportRequirementNumbers(requirementId, fileFormat != null ? fileFormat : "default");
}
@NotBlank
@Column(length = 10, nullable = false)
private String idUzivatele;
class Service {
String a() {throw new RuntimeException();}
String b() {throw new RuntimeException();}
String c() {throw new RuntimeException();}
}
class Facade {
Service service;
String a() {return tryRun(() -> service.a());}
String b() {return tryRun(() -> service.b());}
String c() {return tryRun(() -> service.c());}
String tryRun(Supplier<String> run) {
try {
return run.get();
}
catch(ConstraintViolationException e) {
throw new RuntimeException(""); // don't forget to extract useful information from ConstraintViolationEx type.
}
}
}