如何正确处理服务异常(spring boot rest)

How to correctly handle exceptions from the service (spring boot rest)

当使用 spring 引导构建 rest api 时,从服务级别处理异常并将它们传递 到控制器的最佳方法是什么,所以客户端收到 自定义 json 错误消息 .

{
    "message": "some error"
}

来自控制器的端点

@PostMapping("/login")
public String login(@RequestBody @Valid LoginDto loginDto) {
    return gson.toJson(userService.login(loginDto.getUsername(), loginDto.getPassword()));
} 

服务级别代码

public LoginResponseDto login(String username, String password) {

        try {
            //performs some checks
            ...
            return new LoginResponseDto(token.get());
        } catch (AuthenticationException e){
            LOGGER.info("Log in failed for user {}", username);
        }
    return new LoginResponseDto("login failed");
}

LoginResponseDto class

String token;
String message;

public LoginResponseDto(String message) {
    this.message = message;
}

目前它显然返回了正确的消息但不是正确的状态代码,它将显示状态 200 和 json 中的错误消息。

您有一些选择:

1) 返回消息:

如果你想return这样的消息,

{
    "message": "some error"
}

您可以做的是:

选项 1:创建自定义 POJO class 用于错误消息和 return 对该 POJO 对象的引用 class。

像这样:

ErrorMessage.java

package org.example;

public class ErrorMessage {
    private String message;

    public ErrorMessage(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

控制器中的请求处理程序方法:

@GetMapping("/login{?username, password}")
public ErrorMessage isUserAuthenticated(@RequestParam String username, @RequestParam String password) { 

    if (username.toLowerCase().contentEquals("root") && password.contentEquals("system")) {
        return new ErrorMessage("authenticated");
    }

    return null;
}

选项 2:创建一个映射并插入您希望在消息中包含的键值对。

像这样:

@GetMapping("/login{?username, password}")
public Map<String, String> isUserAuthenticated(@RequestParam String username, @RequestParam String password) { 
    Map<String, String> message = new HashMap<>();

    if (username.toLowerCase().contentEquals("root") && password.contentEquals("system")) {
        message.put("message", "authenticated");
    }

    return message;
}

2) 返回错误状态码(我强烈推荐):

您可以为此目的使用 ResponseEntity。

@GetMapping("/login{?username, password}")
public ResponseEntity<?> isUserAuthenticated(@RequestParam String username, @RequestParam String password) { 
    if (username.toLowerCase().contentEquals("root") && password.contentEquals("system")) {
        return new ResponseEntity<>(HttpStatus.OK);
    }

    return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}