java - SpringBoot DTO 验证
问题描述
我是 spring-boot 的新手,我正在尝试向我的 DTO 类添加验证,如下所示。
import javax.validation.constraints.NotBlank;
@Getter
@Setter
public class EmployeeDto {
private Long id;
@NotBlank(message = "Employee first name is required")
private String firstName;
private String lastName;
@NotBlank(message = "EmployeeNUM is required")
private String employeeNum;
}
下面是我用来保存员工的 REST 端点。
import javax.validation.Valid;
@PostMapping("/employee")
public ResponseEntity<?> addEmployee(@Valid @RequestBody EmployeeDto employeeDto) throws ClassNotFoundException {
return ResponseEntity.ok(employeeService.saveEmployee(deptId,employeeDto));
}
我创建了一个如下所示的验证类来验证 DTO 字段。
@ControllerAdvice
@RestController
public class Validation {
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Map<String, String> handleValidationExceptions(
MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return errors;
}
}
预期输出是
{ "firstName":"员工名字是必填项", "employeeNum":"EmployeeNUM 是必填项" }
但是当通过邮递员到达端点时,我只收到 400 错误请求。我的代码有什么问题?如上所述,如何修复并获得预期的输出?
解决方案
尝试ResponseEntityExceptionHandler
像这样扩展类:
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import javax.validation.ConstraintViolationException;
import java.time.Instant;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* * Handle all exceptions and java bean validation errors for all endpoints income data that use the @Valid annotation
*
* @author Ehab Qadah
*/
@ControllerAdvice
public class GeneralExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException exception, HttpHeaders headers,
HttpStatus status, WebRequest request) {
List<String> validationErrors = exception.getBindingResult()
.getFieldErrors()
.stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.collect(Collectors.toList());
return getExceptionResponseEntity(HttpStatus.BAD_REQUEST, request, validationErrors);
}
@ExceptionHandler({ConstraintViolationException.class})
public ResponseEntity<Object> handleConstraintViolation(
ConstraintViolationException exception, WebRequest request) {
List<String> validationErrors = exception.getConstraintViolations().stream().
map(violation -> violation.getPropertyPath() + ": " + violation.getMessage())
.collect(Collectors.toList());
return getExceptionResponseEntity(HttpStatus.BAD_REQUEST, request, validationErrors);
}
private ResponseEntity<Object> getExceptionResponseEntity(final HttpStatus status, WebRequest request, List<String> errors) {
final Map<String, Object> body = new LinkedHashMap<>();
final String errorsMessage = CollectionUtils.isNotEmpty(errors) ? errors.stream().filter(StringUtils::isNotEmpty).collect(Collectors.joining(",")):status.getReasonPhrase();
final String path = request.getDescription(false);
body.put("TIMESTAMP", Instant.now());
body.put("STATUS", status.value());
body.put("ERRORS", errorsMessage);
body.put("PATH", path);
body.put("MESSAGE", status.getReasonPhrase());
return new ResponseEntity<>(body, status);
}
}
推荐阅读
- node.js - 即使 json.parse 不工作也无法访问 json 数据
- c++ - 使用 CMAKE 为 C++ 设置 Neovim
- ios - Flutter 应用程序未在具有 M1 芯片的 MacBook 上运行 iPhone 13 模拟器
- python - 使用 Python 访问 AWS Redshift
- html - 我无法将徽标添加到我的网站。它占据了整个页面。请帮我
- influxdb - 在 CLI 中将通量 (Influxdb 2.0) 数据库导出到 csv
- python - 从字符串列表中提取不带任何空格的子字符串
- speech-to-text - 如何使用节点红色将 Google Home 设备设置为“收听模式”
- java - Java 中的 While 循环问题
- flutter - 将文件从 Flutter 应用程序存储到外部存储