繁体   English   中英

使用 Spring Boot 的 3 层架构最佳实践

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM