我实现了两个枚举类,作为在RestController中作为输入接收的UserDTO类的参数
package com.example.enumhandler.enumerator;
import com.example.enumhandler.exception.NotValidEnumTypeException;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
public enum GenderTypeEnum {
MALE("male"),
FEMALE("female");
private final String value;
private GenderTypeEnum(String value) {
this.value = value;
}
private static String[] getNames(Class<? extends Enum<?>> e) {
return Arrays.stream(e.getEnumConstants())
.map(Enum::name)
.toArray(String[]::new);
}
private static String[] getNamesValue(){
return Arrays
.stream(values())
.map(e -> valueOf(e.name()).value)
.toArray(String[]::new);
}
@JsonValue
public String getGender(){
return this.value;
}
@JsonCreator
public static GenderTypeEnum fromValues(String value) {
for (GenderTypeEnum category : GenderTypeEnum.values()) {
if (category.getGender().equalsIgnoreCase(value)) {
return category;
}
}
throw new NotValidEnumTypeException(
"Unknown enum type "
+ value
+ ", allowed values are "
+ Arrays.toString(getNamesValue()));
}
}
和/或
package com.example.enumhandler.enumerator;
import com.example.enumhandler.exception.NotValidEnumTypeException;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
public enum HobbyTypeEnum {
BIKE("bike"),
CLIMB("climb"),
TENNIS("tennis");
private final String value;
private HobbyTypeEnum(String value) {
this.value = value;
}
@JsonValue
public String getGender(){
return this.value;
}
private static String[] getNames(Class<? extends Enum<?>> e) {
return Arrays.stream(e.getEnumConstants())
.map(Enum::name)
.toArray(String[]::new);
}
private static String[] getNamesValue(){
return Arrays
.stream(values())
.map(e -> valueOf(e.name()).value)
.toArray(String[]::new);
}
@JsonCreator
public static HobbyTypeEnum fromValues(String value) {
for (HobbyTypeEnum category : HobbyTypeEnum.values()) {
if (category.getGender().equalsIgnoreCase(value)) {
return category;
}
}
throw new NotValidEnumTypeException(
"Unknown enum type "
+ value
+ ", allowed values are "
+ Arrays.toString(getNamesValue()));
}
}
此时,我已经创建了一个自定义Exception来处理异常,以防传递的值与各种Enum类所包含的值相比不正确
package com.example.enumhandler.exception;
import java.io.Serial;
public class NotValidEnumTypeException extends RuntimeException{
@Serial
private static final long serialVersionUID = 1L;
public NotValidEnumTypeException() {
super();
}
public NotValidEnumTypeException(String message, Throwable cause) {
super(message, cause);
}
public NotValidEnumTypeException(String message) {
super(message);
}
public NotValidEnumTypeException(Throwable cause) {
super(cause);
}
}
和/或
package com.example.enumhandler.dto;
import com.example.enumhandler.enumerator.GenderTypeEnum;
import com.example.enumhandler.enumerator.HobbyTypeEnum;
import com.example.enumhandler.validator.ValidGenderTypeEnum;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Max;
import lombok.*;
import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Builder
public class UserDTO {
private String name;
@Min(18)
@Max(25)
private Integer age;
@NotNull
private GenderTypeEnum gender;
@NotNull
@NotEmpty
private List<HobbyTypeEnum> hobby;
}
最后,我创建了一个@RestControllerAdvice来处理这个异常:
package com.example.enumhandler.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@RestControllerAdvice
public class UserExceptionHandler {
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = {NotValidEnumTypeException.class})
public final ResponseEntity<?> handleInvalidEnumTypeArgument(
NotValidEnumTypeException ex
){
HttpStatus badRequest = HttpStatus.BAD_REQUEST;
final Throwable rootCause = org
.apache
.commons
.lang3
.exception
.ExceptionUtils
.getRootCause(ex);
List<String> details = new ArrayList<>();
details.add(rootCause.getLocalizedMessage());
ErrorResponse error = ErrorResponse
.builder()
.timestamp(LocalDateTime.now())
.status(badRequest.getReasonPhrase())
.code(badRequest.value())
.message(details)
.build();
return new ResponseEntity<>(error, badRequest);
}
}
带有自定义错误消息
package com.example.enumhandler.exception;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@AllArgsConstructor
@Data
@Builder
class ErrorResponse {
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private LocalDateTime timestamp;
private String status;
private int code;
private List<String> message;
}
一切正常,但我希望如果两个或更多的枚举是错误的,返回一个唯一的消息,捕获所有这些异常:
1条答案
按热度按时间0qx6xfy61#
经过一段时间试图弄清楚Jackson如何抛出
HttpMessageNotReadableException
,我发现如果在反序列化当前字段时抛出异常,Jackson将不会继续反序列化下一个字段。因此,我们必须忽略并存储反序列化字段时抛出的异常。然后在反序列化完成后抛出这些异常。首先,我们必须创建一个上下文持有者来为每个用户单独存储异常。现在,您必须捕获反序列化时抛出的异常并存储它们。当反序列化失败时,我们应该返回null。
反序列化成功后,你必须抛出我们存储的所有异常:
然后,为
RequestBodyDeserializationException
添加自定义异常处理程序:最后,请确保在请求继续进行后清理上下文:
这是我得到的结果,希望对你有帮助: