当我尝试在 spring 引导应用程序中将自定义错误传递给客户端时出现异常

Exception occurs when I try to pass a custom error to client in spring boot application

java.lang.IllegalStateException: Cannot call sendError() after the response has been committed

如上所述,我在行响应 .sendError() 方法中遇到错误。我已经在互联网上搜索了 4 天。但我无法弄清楚问题所在。这个问题的原因是什么?

我有一个自定义异常 class。 在下面的代码中,catch 块成功捕获了我的自定义异常。但是当我尝试将它发送到客户端时,它 returns 上面提到的异常。

我已经试过了 解决方案 1 – Controller 级别的@ExceptionHandler 解决方案 2 – HandlerExceptionResolver 解决方案 3 – @ControllerAdvice 解决方案 4 – ResponseStatusException

解决上述问题的方法。但是对我不起作用:(

我已将错误代码和错误消息添加到响应正文中。然后我就可以成功获取错误了。但这不是我想要的方式。

@RequestMapping(value="/getMemberID/", method=RequestMethod.POST ,headers ="Accept=application/json")
public  ResponseMemberID getMemberID(@RequestBody RequestMemberID request,HttpServletResponse response, @Context HttpServletRequest _request ) throws Exception {

    Member_info memberinfo = new Member_info();
    ResponseMemberID _response =new ResponseMemberID();

    try {
          memberinfo = memberinfoservice.getMemberID(request.getPin(),request.getMsisdn());
          _response.setMember_id(memberinfo.getMember_id()); 

    }catch(MemberNotFoundException exp) {

                 response.sendError(exp.getErrorCode(), exp.getErrorMessage());
    } 

    return _response;
}

我需要使用上述 sendError() 方法获取错误代码和错误消息作为 JSON 响应。异常成功进入 catch 块。

在这里, 1)您需要为自定义异常添加错误处理程序 2) 并且错误处理程序将抛出异​​常

一些有用的link:

注意:此方法已经过测试,我正在我的应用程序中使用它。

@RestControllerAdvice
    @RequestMapping(produces = "application/json")
    public class DefaultExceptionHandler extends ResponseEntityExceptionHandler {


       @ExceptionHandler(MemberNotFoundException .class)
        @ResponseStatus(value = HttpStatus.CONFLICT)
        public Map<String, String> handleConstraintViolationException(ConstraintViolationException ex) {
         Map<String, String> response = new HashMap);
        // set your response
        return new ResponseEntity<>(response, ex.getStatus());
       }

    }

来自 getMemberID,删除 trycatch 块。

@RestController
@CrossOrigin(origins = "*")
public class MemberController {

@Autowired
MemberInfoService memberinfoservice;


@RequestMapping(value="/getMemberID/", method=RequestMethod.POST ,headers = "Accept=application/json")
public ResponseMemberID getMemberID(@RequestBody RequestMemberID request) throws  Exception{

    Member_info memberinfo = new Member_info();
    ResponseMemberID _response =new ResponseMemberID();

       memberinfo = memberinfoservice.getMemberID(request.getPin(),request.getMsisdn());

       if(memberinfo == null) {

           throw new PINNotValidException();

       }
       _response.setMember_id(memberinfo.getMember_id());

    return _response;

}

@ExceptionHandler(PINNotValidException.class)
public ResponseEntity<ErrorResponse> exceptionHandler(Exception ex) {
    ErrorResponse error = new ErrorResponse();
    error.setErrorCode(PSAExceptionCodes.PIN_VALIDATION_FAIL);
    error.setMessage(ex.getMessage());
    return new ResponseEntity<ErrorResponse>(error, HttpStatus.OK);
}

上面提到的是我根据link http://www.jcombat.com/spring/exception-handling-in-spring-restful-web-service修改的代码,它满足了我的问题。

此外,我还尝试在我创建的应用程序中使用 HttpServletResponse class 的 sendError() 方法,但是它总是返回空响应。

但是通过在创建单独的 PINNotValidException.class,ErrorResponse.class 时将 @ExceptionHandler 用于自定义异常,PSAException.classPSAExceptionCodes.class 我可以很容易地解决我提到的 problem.Below 分别是那些 classes。

PINNotValidException.class

public class PINNotValidException extends PSAException{

private static final long serialVersionUID = 1L;
private static String errorMessage = "Pin Number and Mobile Number mismatch.";
private static int errorCode = PSAExceptionCodes.PIN_VALIDATION_FAIL;

public PINNotValidException() {
    super(errorMessage, errorCode);
 }
}

ErrorResponse.class

public class ErrorResponse {

    private int errorCode;
    private String message;

    public int getErrorCode() {
        return errorCode;
    }
    public void setErrorCode(int errorCode) {
        this.errorCode = errorCode;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

PSAException.class

public class PSAException extends Exception {
private static final long serialVersionUID= 100L;

private String errorMessage;
private int errorCode;

public String getErrorMessage() {
    return errorMessage;
}
public int getErrorCode(){
    return errorCode;
}
public PSAException(String errorMessage) {
    super(errorMessage);
    this.errorMessage = errorMessage;
}
public PSAException(String errorMessage, int errorCode) {
    super(errorMessage);
    this.errorMessage = errorMessage;
    this.errorCode=errorCode;
}
public PSAException() {
    super();
}
}

PSAExceptionCodes.class

public class PSAExceptionCodes {

public static final int PIN_VALIDATION_FAIL = 251;      //Pin and mobile mismatch 
public static final int ACCOUNT_TYPE_NOT_FOUND = 300;     //Account type mismatch
public static final int NO_MEMBER_FOUND = 250;            //Member Not Found
public static final int MEMBER_NOT_REGISTERED = 256;      //Member not registered

}