JAX-RS:抑制错误消息
JAX-RS : Suppress Error Message
我有一个 class,它采用像 Male,Female @POST 这样的枚举值。当我发送一个错误的值,如 'male' 而不是 'Male' 时,它会在 rest 客户端中显示 400 Bad Request 消息:Can not construct instance of constants.Constants$GenderEnum from String value 'male': value 不是声明的 Enum 实例名称之一
在[来源:org.apache.catalina.connector.CoyoteInputStream@718a453d;行:7,列:23](通过引用链:valueobjects.ConsumerValueObject["gender"])
我的休息终点如下所示:
@Consumes("application/json")
@Produces("application/json")
@POST
public Response addConsumer(ConsumerValueObject consumerVO)
此处 ConsumerValueObject 包含枚举。
如何在 Rest 客户端中抑制该错误消息?我尝试使用 ExceptionMapper,但它没有帮助!由于安全问题,我需要禁止显示消息!
您真的要取消错误消息还是要修复实际的问题?
您实际上可以使用像
这样的自定义异常映射器捕获所有抛出的异常
@Provider
public class CustomExceptionMapper implements ExceptionMapper<Throwable> {
@Override
public Response toResponse(Throwable t) {
return Response.ok().build();
}
}
尽管如此,这将处理所有捕获的异常和 return 一个 200 OK
欺骗客户认为请求实际上成功了 - 但事实并非如此!除了 Throwable
之外,您还应该能够捕获具体的异常(即使它是 RuntimeException)——也许您没有将其声明为提供者或没有指定正确的异常 class?
不过,正如已经提到的,return为异常设置不同的状态代码通常是不好的做法,应该避免。在这种情况下,解决实际问题可能更合适。
JAX-RS 提供 MessageBodyReader
和 MessageBodyWriter
接口,您可以声明 un/marshall 对象的输入流或 return 输出流的对象.官方documentation on MessageBodyReader在这方面有更详细的信息。
因此,一个实现可以是以下步骤:
- 读取输入流到 f.e。字符串
- 用大写版本替换所有
"male"
或 "female"
标记
- 将字符串解析为 json 表示(使用 org.json.JSONObject f.e)
- 使用 ObjectMapper 将 JSON 表示转换为 Java 对象
- return映射对象
如果输入失败只是一个简单的 upper/lower 案例问题,这将起作用。如果有拼写错误或语义替代可用,但您的枚举中还没有,您需要付出更多努力。
但是,如果您未能创建正确的对象表示,您应该 return 向客户端发送用户故障(在 400 范围内)以通知客户端出现问题。
这是 JsonParseExceptionMapper
or JsonMappingExceptionMapper
对杰克逊的回应。这些 classes 带有依赖性
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${2.x.version}</version>
</dependency>
无论您有这种显式依赖还是有 resteasy-jackson2-provider(它在幕后使用上述内容),映射器很可能是通过 class 路径扫描隐式注册的。例如你有一个空的 Application
class.
@ApplicationPath("/")
public class ResteasyApplication extends Application {}
这将导致 disovery/registration 通过 class 路径扫描。如果您没有这些依赖项中的任何一个,并且如果您在 Wildfly 中,我不确定它们是如何注册的,但这就是正在发生的事情。
您可以 write/register 您自己的 ExceptionMappers
JsonParseException
和 JsonMappingException
@Provider
public class JsonMappingExceptionMapper
implements ExceptionMapper<JsonMappingException> {
@Override
public Response toResponse(JsonMappingException e) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
但根据我的测试,要注册哪一个,你的还是杰克逊的,这是一个折腾。映射器被放入一个集合(如此无序),然后被推入一个地图,所以只有一个被推入。他们被推入的顺序就像我说的那样是一个折腾。
我想这实际上只是部分答案,因为除了显式注册所有 classes(最终 ),但这很麻烦。
不过现在战局缩小了。以后有机会我会再试一次
更新
所以这不是一个解决方案,只是一个半概念验证来展示我们如何让它使用我们的 ExceptionMapper。
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.my.pkg.JsonMappingExceptionMapper;
@Path("/init")
public class InitResource {
@GET
public Response init() {
ResteasyProviderFactory factory = ResteasyProviderFactory.getInstance();
factory.getExceptionMappers().put(JsonMappingException.class,
new JsonMappingExceptionMapper());
return Response.ok("Done!").build();
}
}
一旦我们第一次到达 init
端点,我们的 JsonMappingExcpetionMapper
将注册并覆盖现有的,无论是 Jackson 的还是我们的。
当然我们不想真的这样做,它只是展示如何覆盖映射器。我不知道该把这段代码放在哪里。我在 Application
构造函数中尝试了一个 ServletContextListener
,在一个低优先级的 Feature
中。我想不通。 None 以上发生在 RESTeasy 其 最终注册之前。
我有一个 class,它采用像 Male,Female @POST 这样的枚举值。当我发送一个错误的值,如 'male' 而不是 'Male' 时,它会在 rest 客户端中显示 400 Bad Request 消息:Can not construct instance of constants.Constants$GenderEnum from String value 'male': value 不是声明的 Enum 实例名称之一 在[来源:org.apache.catalina.connector.CoyoteInputStream@718a453d;行:7,列:23](通过引用链:valueobjects.ConsumerValueObject["gender"])
我的休息终点如下所示:
@Consumes("application/json")
@Produces("application/json")
@POST
public Response addConsumer(ConsumerValueObject consumerVO)
此处 ConsumerValueObject 包含枚举。
如何在 Rest 客户端中抑制该错误消息?我尝试使用 ExceptionMapper,但它没有帮助!由于安全问题,我需要禁止显示消息!
您真的要取消错误消息还是要修复实际的问题?
您实际上可以使用像
这样的自定义异常映射器捕获所有抛出的异常@Provider
public class CustomExceptionMapper implements ExceptionMapper<Throwable> {
@Override
public Response toResponse(Throwable t) {
return Response.ok().build();
}
}
尽管如此,这将处理所有捕获的异常和 return 一个 200 OK
欺骗客户认为请求实际上成功了 - 但事实并非如此!除了 Throwable
之外,您还应该能够捕获具体的异常(即使它是 RuntimeException)——也许您没有将其声明为提供者或没有指定正确的异常 class?
不过,正如已经提到的,return为异常设置不同的状态代码通常是不好的做法,应该避免。在这种情况下,解决实际问题可能更合适。
JAX-RS 提供 MessageBodyReader
和 MessageBodyWriter
接口,您可以声明 un/marshall 对象的输入流或 return 输出流的对象.官方documentation on MessageBodyReader在这方面有更详细的信息。
因此,一个实现可以是以下步骤:
- 读取输入流到 f.e。字符串
- 用大写版本替换所有
"male"
或"female"
标记 - 将字符串解析为 json 表示(使用 org.json.JSONObject f.e)
- 使用 ObjectMapper 将 JSON 表示转换为 Java 对象
- return映射对象
如果输入失败只是一个简单的 upper/lower 案例问题,这将起作用。如果有拼写错误或语义替代可用,但您的枚举中还没有,您需要付出更多努力。
但是,如果您未能创建正确的对象表示,您应该 return 向客户端发送用户故障(在 400 范围内)以通知客户端出现问题。
这是 JsonParseExceptionMapper
or JsonMappingExceptionMapper
对杰克逊的回应。这些 classes 带有依赖性
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${2.x.version}</version>
</dependency>
无论您有这种显式依赖还是有 resteasy-jackson2-provider(它在幕后使用上述内容),映射器很可能是通过 class 路径扫描隐式注册的。例如你有一个空的 Application
class.
@ApplicationPath("/")
public class ResteasyApplication extends Application {}
这将导致 disovery/registration 通过 class 路径扫描。如果您没有这些依赖项中的任何一个,并且如果您在 Wildfly 中,我不确定它们是如何注册的,但这就是正在发生的事情。
您可以 write/register 您自己的 ExceptionMappers
JsonParseException
和 JsonMappingException
@Provider
public class JsonMappingExceptionMapper
implements ExceptionMapper<JsonMappingException> {
@Override
public Response toResponse(JsonMappingException e) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
但根据我的测试,要注册哪一个,你的还是杰克逊的,这是一个折腾。映射器被放入一个集合(如此无序),然后被推入一个地图,所以只有一个被推入。他们被推入的顺序就像我说的那样是一个折腾。
我想这实际上只是部分答案,因为除了显式注册所有 classes(最终
不过现在战局缩小了。以后有机会我会再试一次
更新
所以这不是一个解决方案,只是一个半概念验证来展示我们如何让它使用我们的 ExceptionMapper。
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.my.pkg.JsonMappingExceptionMapper;
@Path("/init")
public class InitResource {
@GET
public Response init() {
ResteasyProviderFactory factory = ResteasyProviderFactory.getInstance();
factory.getExceptionMappers().put(JsonMappingException.class,
new JsonMappingExceptionMapper());
return Response.ok("Done!").build();
}
}
一旦我们第一次到达 init
端点,我们的 JsonMappingExcpetionMapper
将注册并覆盖现有的,无论是 Jackson 的还是我们的。
当然我们不想真的这样做,它只是展示如何覆盖映射器。我不知道该把这段代码放在哪里。我在 Application
构造函数中尝试了一个 ServletContextListener
,在一个低优先级的 Feature
中。我想不通。 None 以上发生在 RESTeasy 其 最终注册之前。