Java CXF/JAX-RS:从拦截器返回自定义响应

Java CXF/JAX-RS:从拦截器返回自定义响应,java,exception,cxf,jax-rs,interceptor,Java,Exception,Cxf,Jax Rs,Interceptor,当REST调用期间发生异常时,我们需要返回自定义错误代码和错误消息。我们已经创建了一个异常映射器提供程序,它可以很好地处理来自应用程序代码的异常。但是,当CXF代码(例如,我编写的CustomValidationInterceptor表单)出现异常时,它不起作用 例如,如果我请求的路径参数无效(例如无效的电话号码)。在本例中,我们需要返回JSON格式的自定义错误代码和错误消息,但即使创建了异常映射器提供程序来处理WebApplicationException,它也无法工作 有没有办法处理来自cx

当REST调用期间发生异常时,我们需要返回自定义错误代码和错误消息。我们已经创建了一个异常映射器提供程序,它可以很好地处理来自应用程序代码的异常。但是,当CXF代码(例如,我编写的CustomValidationInterceptor表单)出现异常时,它不起作用

例如,如果我请求的路径参数无效(例如无效的电话号码)。在本例中,我们需要返回JSON格式的自定义错误代码和错误消息,但即使创建了异常映射器提供程序来处理WebApplicationException,它也无法工作

有没有办法处理来自cxf拦截器的异常并返回 对用户做出如下响应

{
"errorDetail": {
"errorCode": "404",
"errorMessage": "Bad Request"
}
}
my CustomValidationInterceptor的代码段:

public class CustomValidationInterceptor extends AbstractPhaseInterceptor<Message>{

    public CustomValidationInterceptor() {
        super(Phase.PRE_INVOKE); // Put this interceptor in this phase
    }

    public void handleMessage(Message message) {

        MetadataMap<String, String> metadataMap = (MetadataMap<String, String>) message.get("jaxrs.template.parameters");

        if(null != metadataMap) {
            List<String> list = metadataMap.get("phoneNumber");
            if(null != list) {
                String phoneNumber = list.get(0);
                boolean result = validatePhoneNumber(phoneNumber);
                if(!result){
                    throw new TelusServiceException(Response.status(Response.Status.BAD_REQUEST).build(), 400, "phone number not valid");
                }
            } else {
                throw new TelusServiceException(Response.status(Response.Status.BAD_REQUEST).build(), 400, "phone number not valid");
            }
        } else {
            throw new TelusServiceException(Response.status(Response.Status.BAD_REQUEST).build(), 400, "phone number not valid");
        }
    }

    public boolean validatePhoneNumber(String phoneNumber) {

          Pattern pattern = Pattern.compile("^[1-9]\\d{9}$");
          Matcher matcher = pattern.matcher(phoneNumber);

          if (!matcher.matches()) {
              return false;
          }
          return true;
     }

}
ErrorDetail类的代码段

@XmlRootElement(name="errorDetail")
public class ErrorDetail {

    private int errorCode;
    private String errorMessage;

    @XmlElement(name = "errorCode")
    public int getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(int errorCode) {
        this.errorCode = errorCode;
    }
    @XmlElement(name = "errorMessage")
    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

}

我找到了从拦截器发送自定义响应的方法,但仍然无法找到从拦截器调用CustomExceptionHandler的方法

代码:

public void handleMessage(Message message) {

        MetadataMap<String, String> metadataMap = (MetadataMap<String, String>) message.get("jaxrs.template.parameters");

        if(null != metadataMap) {
            List<String> list = metadataMap.get("phoneNumber");
            if(null != list) {
                String phoneNumber = list.get(0);
                boolean result = validatePhoneNumber(phoneNumber);
                if(!result){
// Create a response object and set it in the message. 
// calling getExchange() will not call your service
                    Response response = Response
                .status(Response.Status.BAD_REQUEST)
                .entity(new ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode(), Response.Status.BAD_REQUEST.toString()))
                .build();
        message.getExchange().put(Response.class, response);
// That's it
                }
            } else {
                Response response = Response
                .status(Response.Status.BAD_REQUEST)
                .entity(new ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode(), Response.Status.BAD_REQUEST.toString()))
                .build();
        message.getExchange().put(Response.class, response);
            }
        } else {
            Response response = Response
                .status(Response.Status.BAD_REQUEST)
                .entity(new ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode(), Response.Status.BAD_REQUEST.toString()))
                .build();
        message.getExchange().put(Response.class, response);
        }
    }
public void handleMessage(消息消息消息){
MetadataMap MetadataMap=(MetadataMap)message.get(“jaxrs.template.parameters”);
if(null!=metadataMap){
List=metadataMap.get(“电话号码”);
如果(空!=列表){
字符串phoneNumber=list.get(0);
布尔结果=validatePhoneNumber(phoneNumber);
如果(!结果){
//创建一个响应对象并在消息中设置它。
//调用getExchange()将不会调用您的服务
响应=响应
.状态(响应.状态.错误请求)
.entity(新的ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode()、Response.Status.BAD_REQUEST.toString())
.build();
message.getExchange().put(Response.class,Response);
//就这样
}
}否则{
响应=响应
.状态(响应.状态.错误请求)
.entity(新的ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode()、Response.Status.BAD_REQUEST.toString())
.build();
message.getExchange().put(Response.class,Response);
}
}否则{
响应=响应
.状态(响应.状态.错误请求)
.entity(新的ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode()、Response.Status.BAD_REQUEST.toString())
.build();
message.getExchange().put(Response.class,Response);
}
}

我对cxf用户组提出了类似的问题,请参见:

我最终用ContainerRequestFilter和ContainerResponseFilter替换了我的拦截器,然后异常映射器愉快地处理了应用程序异常和从过滤器抛出的异常


希望这有帮助。

我已经更正了JSON。请查看
TelusServiceException
.getErrorDetail()
的代码是什么?添加了TelusServiceException和ErrorDetail对象的代码片段您是否尝试过过滤器?我认为无论cxf调用链如何,每个响应都会调用它们!很久以前,我在我的一个项目中研究过这个问题。下面的答案起了作用,所以不知道过滤器是否有用也许你也有类似的问题:
@XmlRootElement(name="errorDetail")
public class ErrorDetail {

    private int errorCode;
    private String errorMessage;

    @XmlElement(name = "errorCode")
    public int getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(int errorCode) {
        this.errorCode = errorCode;
    }
    @XmlElement(name = "errorMessage")
    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

}
public void handleMessage(Message message) {

        MetadataMap<String, String> metadataMap = (MetadataMap<String, String>) message.get("jaxrs.template.parameters");

        if(null != metadataMap) {
            List<String> list = metadataMap.get("phoneNumber");
            if(null != list) {
                String phoneNumber = list.get(0);
                boolean result = validatePhoneNumber(phoneNumber);
                if(!result){
// Create a response object and set it in the message. 
// calling getExchange() will not call your service
                    Response response = Response
                .status(Response.Status.BAD_REQUEST)
                .entity(new ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode(), Response.Status.BAD_REQUEST.toString()))
                .build();
        message.getExchange().put(Response.class, response);
// That's it
                }
            } else {
                Response response = Response
                .status(Response.Status.BAD_REQUEST)
                .entity(new ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode(), Response.Status.BAD_REQUEST.toString()))
                .build();
        message.getExchange().put(Response.class, response);
            }
        } else {
            Response response = Response
                .status(Response.Status.BAD_REQUEST)
                .entity(new ErrorDetail(Response.Status.BAD_REQUEST.getStatusCode(), Response.Status.BAD_REQUEST.toString()))
                .build();
        message.getExchange().put(Response.class, response);
        }
    }