注意:部分代码将使用西班牙语。
嗨。我为我的 Spring Boot 应用程序创建了一个很好的异常模型,这样我抛出的每个个性化异常都会创建一个个性化响应(在本例中,它是一个名为
ErrorModel
的类),这样我就可以在 @RestControllerAdvice
中使用@ExceptionHandler
,然后返回该特定异常创建的 errorModel
。在个性化例外中创建的每个 errorModel
的特殊之处在于 code
和 description
。
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ClienteSinMorasException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
public ErrorModel manejoDeClienteSinMoras(ClienteSinMorasException ex) {
return ex.getErrorModel();
}
}
@Getter
@AllArgsConstructor
public class ErrorModel {
private final String codigo;
private final String descripcion;
private final ArrayList<HashMap<String, String>> errores; //don't take this into consideration
}
因此,因为每个异常都是相同的,并且工作原理相同,唯一的区别是
code
(codigo
) 和 description
(descipcion
),我创建了这个,并且运行良好:
public abstract class IErrorException extends RuntimeException {
@Getter
private final ErrorModel errorModel;
public abstract String getCodigo();
public abstract String getDescripcion();
public IErrorException() {
super();
this.errorModel = new ErrorModel(this.getCodigo(), this.getDescripcion(), null);
}
public IErrorException(ArrayList<HashMap<String, String>> errores) {
super();
this.errorModel = new ErrorModel(this.getCodigo(), this.getDescripcion(), errores);
}
public IErrorException(String errorKey, String errorValue) {
super();
ArrayList<HashMap<String, String>> errores = new ArrayList<>();
errores.add(new HashMap<>(Map.of(errorKey, errorValue)));
this.errorModel = new ErrorModel(this.getCodigo(), this.getDescripcion(), errores);
}
}
// One of the exceptions
@Getter
public class ClienteSinMorasException extends IErrorException {
private final String codigo = "code";
private final String descripcion = "desc";
public ClienteSinMorasException() {
super();
}
public ClienteSinMorasException(ArrayList<HashMap<String, String>> errores) {
super(errores);
}
public ClienteSinMorasException(String errorKey, String errorValue) {
super(errorKey, errorValue);
}
}
这是完美的(除了那些超级,但无论如何),但最近,他们要求我更改它,以便从 .yml 属性读取
code
和 description
,以便可以在运行时更改值,而无需需要重新运行应用程序。这个简单的改变打破了一切。
我开始明白,这样做有效的唯一原因是因为当我在抽象类中执行
final
时,explicit primitive
类型的this.getCodigo()
字段“有点已经存在”(在本例中,这返回“代码”)。如果它不是 final
也不是 explicit primitive
类型,则这不起作用,它会在构造函数执行后加载所有内容,因此我最终创建了一个 new ErrorModel(null, null, null)
。另外,super()
必须是构造函数中的第一件事,所以我无法完全正确地初始化变量。
// One of the exceptions
@Getter
public class ClienteSinMorasException extends IErrorException {
private final String codigo = Yml.get("cod");
private final String descripcion = Yml.get("desc");
public ClienteSinMorasException() {
super();
}
public ClienteSinMorasException(ArrayList<HashMap<String, String>> errores) {
super(errores);
}
public ClienteSinMorasException(String errorKey, String errorValue) {
super(errorKey, errorValue);
}
}
这行不通,老实说我不知道该怎么办。
字段初始值设定项稍后才会运行。但是,您拥有的这两个字段似乎没有任何功能。你不需要它们。充其量,它们只是作为缓存 Yml 读取器值的一种有点蹩脚的方式而存在。糟糕的是,异常的每个实例都会重新创建它们,如果缓存是重点,那么在 Yml 类本身中执行此操作会更有效。
因此,完全摆脱田地。要么它们根本没有任何意义,要么重点是充当缓存(即避免重复敲击磁盘以多次重新读取该 YML 文件)。如果它是缓存 - 这是错误的位置,请编辑
Yml
的代码以在此处添加缓存行为。无论哪种方式,对此异常类型的正确看法是:
public class ClienteSinMorasException extends IErrorException {
@Override public String getCodigo() {
return Yml.get("cod");
}
@Override public String getDescripcion() {
return Yml.get("desc");
}
public ClienteSinMorasException() {
super();
}
public ClienteSinMorasException(ArrayList<HashMap<String, String>> errores) {
super(errores);
}
public ClienteSinMorasException(String errorKey, String errorValue) {
super(errorKey, errorValue);
}
}
这避免了这个问题:没有字段,因此没有字段初始值设定项,因此您不会遇到任何有关初始化序列问题的问题。