简体   繁体   中英

Programmatically change http response status using spring 3 restful

I have a controller like below

@Controller("myController")
@RequestMapping("api")
public class MyController {

     @RequestMapping(method = RequestMethod.GET, value = "/get/info/{id}", headers = "Accept=application/json")
    public @ResponseBody
    Student getInfo(@PathVariable String info) {
.................
}




    @ExceptionHandler(Throwable.class)
    @ResponseStatus( HttpStatus.EXPECTATION_FAILED)
    @ResponseBody
    public String handleIOException(Throwable ex) {
        ErrorResponse errorResponse = errorHandler.handelErrorResponse(ex);
        return errorResponse.toString();
    }

}

The controller has an error handling mechanism, in the error handling option it always return expectation fail status code 417. But I need to set a dynamic error Http status code like 500, 403 etc depending on type of error. How do I do this?

You need to change the type of the output value ResponseEntity . Answer here: How to respond with HTTP 400 error in a Spring MVC @ResponseBody method returning String?

I get a solution and going to share this and also like to know any good suggestions.

@Controller("myController")
@RequestMapping("api")
public class MyController {

    @RequestMapping(method = RequestMethod.GET, value = "/get/info/{id}", headers = "Accept=application/json")
    public @ResponseBody
    Student getInfo(@PathVariable String info) {
        // ...
    }

}


// ...    
    @ExceptionHandler(Throwable.class)
    //@ResponseStatus( HttpStatus.EXPECTATION_FAILED)<<remove this line
    @ResponseBody
    public String handleIOException(HttpServletResponse httpRes,Throwable ex){ // <<Change this 
        if (some condition) {
            httpRes.setStatus(HttpStatus.BAD_GATEWAY.value());
        } else {
            httpRes.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        }                 
        ErrorResponse errorResponse = errorHandler.handleErrorResponse(ex);
        return errorResponse.toString();
    }

Expected out in rest client :

502 Bad Gateway
{
    "status":"BAD_GATEWAY",
    "error":"java.lang.UnsupportedOperationException",
    "message":"Some error message"
}

Thanks for your replies. I still need pointers for good practices.

Going by the code above, you need to be more careful about which exceptions you are throwing and handling. Setting up an exception handler for Throwable seems overly broad.

The way I do this is to create an ErrorMessage class with my XML/JSON marshalling annotations.

@XmlRootElement(name = "error")
public class ErrorMessage {
    private Throwable exception;
    private String message;
    public ErrorMessage() {
        this.message = "";
    }
    public ErrorMessage(String message) {
        this.message = message;
    }
    public ErrorMessage(Throwable exception) {
        this.exception = exception;
        this.message = exception.getLocalizedMessage();
    }
    @XmlTransient
    @JsonIgnore
    public Throwable getException() {
        return exception;
    }
    public void setException(Throwable exception) {
        this.exception = exception;
    }
    @XmlElement(name = "message")
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

With that in place, I tend to create my own application exceptions and then create my exception handler methods such as:

@ExceptionHandler(ResourceNotFoundException.class)
@ResponseBody
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorMessage handleResourceNotFoundException(ResourceNotFoundException e, HttpServletRequest req) {
    return new ErrorMessage(e);
}

@ExceptionHandler(InternalServerErrorException.class)
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorMessage handleInternalServerErrorException(InternalServerErrorException e, HttpServletRequest req) {
    return new ErrorMessage(e);
}

With those in place, I just need to throw appropriate exceptions from my controller methods. For instance, if I throw a ResourceNotFoundException, then Spring will redirect that to my handleResourceNotFoundException method, which returns a 404, and that will also return JSON or XML representing the error.

You can use an Aspect for your API. If you define an @Around interceptor for your service, you can change the response content.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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