java CXF/JAX-RS:从拦截器返回自定义响应
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17079790/
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
CXF/ JAX-RS : Return Custom response from interceptor
提问by Bhuvan
We need to return custom error code and error message when exception occurs during REST invocation. We have created a exception mapper provider, it works well for the exceptions from the application code. However, it doesn't work when exception occurs from the CXF code (e.g. form the CustomValidationInterceptor that I wrote).
我们需要在 REST 调用过程中发生异常时返回自定义错误代码和错误消息。我们创建了一个异常映射器提供程序,它适用于应用程序代码中的异常。但是,当 CXF 代码(例如,形成我编写的 CustomValidationInterceptor)发生异常时,它不起作用。
For example, if I request with invalid path parameter (e.g invalid phoneNumber). In this case, we need to return a custom error code and error message in JSON format, but it doesn't work even though we have a exception mapper provider created to handle WebApplicationException.
例如,如果我使用无效的路径参数(例如无效的电话号码)进行请求。在这种情况下,我们需要以 JSON 格式返回自定义错误代码和错误消息,但即使我们创建了一个异常映射器提供程序来处理 WebApplicationException,它也不起作用。
Is there any way to handle exceptions from cxf interceptors and return response to user with something like the following?
有什么方法可以处理来自 cxf 拦截器的异常并使用以下内容向用户返回响应?
{
"errorDetail": {
"errorCode": "404",
"errorMessage": "Bad Request"
}
}
Code Snippet of my CustomValidationInterceptor :
我的 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;
}
}
Code Snippet of my Custom Exception Mapper Provider
我的自定义异常映射器提供程序的代码片段
public class TelusExceptionHandler implements ExceptionMapper<TelusServiceException> {
public Response toResponse(TelusServiceException exception) {
return Response.status(exception.getErrorDetail().getErrorCode()).entity(exception.getErrorDetail()).build();
}
}
Code Snippet of TelusServiceException
TelusServiceException 的代码片段
public class TelusServiceException extends WebApplicationException{
// constructors and other methods
private ErrorDetail errorDetail = null;
public ErrorDetail getErrorDetail() {
return errorDetail;
}
public void setErrorDetail(ErrorDetail errorDetail) {
this.errorDetail = errorDetail;
}
public TelusServiceException(Response response, int errorCode, String errorMessage) {
super(response);
errorDetail = new ErrorDetail();
errorDetail.setErrorCode(errorCode);
errorDetail.setErrorMessage(errorMessage);
}
}
Code Snippet of ErrorDetail class
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;
}
}
回答by Bhuvan
I found a way to send a custom response from the interceptor but still can't figure out a way to call my CustomExceptionHandler from the interceptor
我找到了一种从拦截器发送自定义响应的方法,但仍然无法找到从拦截器调用我的 CustomExceptionHandler 的方法
Code:
代码:
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);
}
}
回答by MandyW
I raised a similar question on the cxf user group, see:
我在cxf用户群上提过类似的问题,见:
I ended up replacing my interceptors with ContainerRequestFilter and ContainerResponseFilter and then the Exception Mapper happily handled both application exceptions and exceptions thrown from the Filter.
我最终用 ContainerRequestFilter 和 ContainerResponseFilter 替换了我的拦截器,然后异常映射器愉快地处理了应用程序异常和过滤器抛出的异常。
Hope this helps.
希望这可以帮助。