[英]3 tiers architecture best practice using Spring Boot
我在 Spring Boot 应用程序中使用 3 层架构。 我创建了 3 个包(模型、服务、控制器),但我所做的是,服务用 try catch 调用了一个 repo 函数,然后我在控制器中调用它
例子:
服务:
public ResponseEntity<List<Customer>> getAllCustomers() {
try {
List<Customer> customers = new ArrayList<Customer>();
cutomerRepository.findAll().forEach(customers::add);
if (customers.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<>(customers, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
控制器
@GetMapping("/viewList")
private ResponseEntity<?> getAllCustomers()
{
try{
return customerService.getAllCustomers();
}catch (Exception exception){
return new ResponseEntity<String>("Customers is not found", HttpStatus.METHOD_FAILURE);
}
}
那是对的吗? 我认为我应该只customerRepository.findAll()
服务,而不需要任何其他逻辑或代码,但我不确定。 任何想法?
服务层应该包含逻辑,这样就可以了。
但它不应包含来自控制器层的任何类,因为这会将信息从“上”层泄漏到“下”层。 这意味着您的服务不应返回 ResponseEntity,因为它来自控制器层。 相反,它应该只返回一个客户列表,并让控制器从中构造 ResponseEntity。
否则,您的服务将始终被限制为由该特定控制器调用。 它不能被不使用 HTTP ResponseEntity 的不同类型控制器的另一个服务调用。
我认为最好的方法如下。
您的服务层不应像当前那样返回ResponseEntity<List<Customer>>
。 它应该返回List<Customer>
。
这已经在上面的答案中,但想回答以进一步扩展内容。
该服务还应在修改为返回List<Customer>
时处理具有应用程序特定异常的异常。 因此,您为您的应用程序创建自己的异常、此异常的模型以及创建一个Exception Advice class
,其中所有这些应用程序异常都以一般方式处理。 因此,您的服务只会抛出异常,控制器不会捕获它,它将由 Advice 类(使用@ControllerAdvice
注释)处理,该类将处理所有未捕获的异常并返回适当的响应。 在 Spring 中还有更多选项可以以通用方式处理异常。
我附上以下代码作为示例
处理从控制器冒出的所有异常的类。
@ControllerAdvice
public class ErrorHandler {
@ExceptionHandler(ApplicationException.class)
public ResponseEntity handleApplicationException(ApplicationException e) {
return ResponseEntity.status(e.getCustomError().getCode()).body(e.getCustomError());
}
}
一些特定于应用程序的异常(名称可能更具体)
@Getter
@Setter
public class ApplicationException extends RuntimeException {
private CustomError customError;
public ApplicationException(CustomError customError){
super();
this.customError = customError;
}
}
发生异常时返回给客户端的 Error 对象
@Getter
@Setter
@NoArgsConstructor
public class CustomError {
private int code;
private String message;
private String cause;
public CustomError(int code, String message, String cause) {
this.code = code;
this.message = message;
this.cause = cause;
}
@Override
public String toString() {
return "CustomError{" +
"code=" + code +
", message='" + message + '\'' +
", cause='" + cause + '\'' +
'}';
}
}
您的服务
public List<Customer> getAllCustomers() {
try {
List<Customer> customers = new ArrayList<Customer>();
cutomerRepository.findAll().forEach(customers::add);
if (customers.isEmpty()) {
throw new ApplicationException(new CustomError(204, "No Content", "Customers do not exist"));
}
return new ResponseEntity<>(customers, HttpStatus.OK);
} catch (Exception e) {
throw new ApplicationException(new CustomError(500, "Server Error", "Disclose to the client or not what the cause of the error in the server was"));
}
}
它自己的控制器还可以检查它接收到的输入信息,如果需要,它可以自己抛出一个应用程序特定的异常,或者只返回一个适当的响应,其中包含输入中的错误信息。
这样控制器只是处理用户和服务层之间的输入/输出。
该服务只是处理来自持久层的数据的输入/输出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.