java 将正文添加到 404 Not Found 异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36848562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 01:55:53  来源:igfitidea点击:

Add a body to a 404 Not Found Exception

javarestspring-mvcspring-bootjhipster

提问by luso

In an REST API generated with JHipster, I want to throw some 404 exceptions. It is normally done with

在使用 JHipster 生成的 REST API 中,我想抛出一些 404 异常。它通常是用

return new ResponseEntity<>(HttpStatus.NOT_FOUND);

which actualy results in a 404 response to the xhr request. The problem is that in the front side, JHipster parses the response with

这实际上会导致对 xhr 请求的 404 响应。问题是在前端,JHipster 解析响应

angular.fromJson(result)

and such result is empty when the 404 is the actual response, which makes the parse to fail.

当404是实际响应时,这样的结果是空的,这使得解析失败。

If I point to an unmapped URI, lets say /api/userwhile my controller maps to /api/users(note the plural) the 404 I got from the API has a body in it:

如果我指向一个未映射的 URI,假设/api/user当我的控制器映射到/api/users(注意复数)时,我从 API 获得的 404 中有一个主体:

{
    "timestamp": "2016-04-25T18:33:19.947+0000",
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/api/user/myuser/contact"
}

which is correctly parse in angular.

这是正确解析的角度。

How can I create a body like this? Is this exception thrown by spring or is tomcat who throws it?

我怎样才能创造出这样的身体?这个异常是spring抛出的还是tomcat抛出的?

I tried this: Trigger 404 in Spring-MVC controller?but I cant set the parameters of the response.

我试过这个:在 Spring-MVC 控制器中触发 404?但我无法设置响应的参数。

回答by Ali Dehghani

Basic Idea

基本理念



First option is to define error objects and return them as 404 Not Foundbody. Something like following:

第一个选项是定义错误对象并将它们作为404 Not Found正文返回。类似于以下内容:

Map<String, String> errors = ....;
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errors);

Instead of returning a typical ResponseEntity, you can throw an Exceptionthat will be resolved to a 404 Not Found. Suppose you have a NotFoundExceptionlike:

ResponseEntity您可以抛出Exception将解析为 a的,而不是返回典型的404 Not Found。假设你有一个NotFoundException喜欢:

@ResponseStatus(code = HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException {}

Then if you throw this exception in your controllers, you would see something like:

然后,如果您在控制器中抛出此异常,您会看到如下内容:

{  
   "timestamp":1461621047967,
   "status":404,
   "error":"Not Found",
   "exception":"NotFoundException",
   "message":"No message available",
   "path":"/greet"
}

If you want to customize the message and other parts of body, you should define a ExceptionHandlerfor NotFoundException.

如果你想自定义消息和正文的其他部分,你应该定义一个ExceptionHandlerfor NotFoundException

Introducing Exception Hierarchies

引入异常层次结构



If you're creating a RESTful API and want to have different Error Codesand Error Messagesfor different exceptional cases, you can create a hierarchy of exceptions representing those cases and extract message and code from each one.

如果您正在创建 RESTful API 并希望针对不同的异常情况使用不同的错误代码错误消息,您可以创建代表这些情况的异常层次结构,并从每个异常中提取消息和代码。

For example, you can introduce an exception, say, APIExceptionwhich is super-class of all other exceptions thrown by your controllers. This class defines a code/message pair like:

例如,您可以引入一个异常,例如,APIException它是您的控制器抛出的所有其他异常的超类。这个类定义了一个代码/消息对,如:

public class APIException extends RuntimeException {
    private final int code;
    private final String message;

    APIException(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public int code() {
        return code;
    }

    public String message() {
        return message;
    }
}

Each subclass depending on the nature of its exception can provide some sensible values for this pair. For example, we could have an InvalidStateException:

每个子类根据其异常的性质可以为这对提供一些合理的值。例如,我们可以有一个InvalidStateException

@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public class InvalidStateException extends APIException {
    public InvalidStateException() {
        super(1, "Application is in invalid state");
    }
}

Or that notorious not found ones:

或者臭名昭著的未找到的:

@ResponseStatus(code = HttpStatus.NOT_FOUND)
public class SomethingNotFoundException extends APIException {
    public SomethingNotFoundException() {
        super(2, "Couldn't find something!");
    }
}

Then we should define an ErrorControllerthat catches those exceptions and turn them to meaningful JSON representations. That error controller may look like following:

然后我们应该定义一个ErrorController捕获这些异常并将它们转换为有意义的 JSON 表示的方法。该错误控制器可能如下所示:

@RestController
public class APIExceptionHandler extends AbstractErrorController {
    private static final String ERROR_PATH = "/error";
    private final ErrorAttributes errorAttributes;

    @Autowired
    public APIExceptionHandler(ErrorAttributes errorAttributes) {
        super(errorAttributes);
        this.errorAttributes = errorAttributes;
    }

    @RequestMapping(path = ERROR_PATH)
    public ResponseEntity<?> handleError(HttpServletRequest request) {
        HttpStatus status = getStatus(request);

        Map<String, Object> errors = getErrorAttributes(request, false);
        getApiException(request).ifPresent(apiError -> {
            errors.put("message" , apiError.message());
            errors.put("code", apiError.code());
        });
        // If you don't want to expose exception!
        errors.remove("exception");


        return ResponseEntity.status(status).body(errors);
    }

    @Override
    public String getErrorPath() {
        return ERROR_PATH;
    }

    private Optional<APIException> getApiException(HttpServletRequest request) {
        RequestAttributes attributes = new ServletRequestAttributes(request);
        Throwable throwable = errorAttributes.getError(attributes);
        if (throwable instanceof APIException) {
            APIException exception = (APIException) throwable;
            return Optional.of(exception);
        }

        return Optional.empty();
    }
}

So, if you throw an SomethingNotFoundException, the returned JSON would be like:

因此,如果您抛出SomethingNotFoundException,则返回的 JSON 将类似于:

{  
   "timestamp":1461621047967,
   "status":404,
   "error":"Not Found",
   "message":"Couldn't find something!",
   "code": 2,
   "path":"/greet"
}

回答by AbdusSalam

I guess you can do this if you want to return some message or test with your error code

如果您想返回一些消息或使用错误代码进行测试,我想您可以这样做

@ResponseBody
public ResponseEntity somthing() {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json; charset=utf-8");
return new ResponseEntity<>(new Gson().toJson("hello this is my message"), headers, HttpStatus.NOT_FOUND);
}