我有一个类,它接受像男性,女性@POST这样的枚举值。当我发送一个错误的值,如'male'而不是'Male'时,它会在休息客户端显示400 Bad Request with this message: 无法构造constants.Constants $ GenderEnum from String value'male' :value不是声明的Enum实例名称之一 在[来源:org.apache.catalina.connector.CoyoteInputStream@718a453d; line:7,column:23](通过引用链:valueobjects.ConsumerValueObject [“gender”])
我的休息终点如下所示:
@Consumes("application/json")
@Produces("application/json")
@POST
public Response addConsumer(ConsumerValueObject consumerVO)
这里ConsumerValueObject包含枚举。
如何在Rest客户端中抑制该错误消息?我尝试使用ExceptionMapper但它没有帮助!我需要因安全问题而禁止显示消息!
答案 0 :(得分:1)
你真的想要压制错误信息,还是想修复实际的问题?
您实际上可以使用自定义异常映射器(如
)捕获所有抛出的异常@Provider
public class CustomExceptionMapper implements ExceptionMapper<Throwable> {
@Override
public Response toResponse(Throwable t) {
return Response.ok().build();
}
}
但是,这将处理所有捕获的异常并返回200 OK
,这会诱使客户认为请求实际成功 - 事实并非如此!而不是Throwable
你应该能够捕获具体的异常(即使它是一个RuntimeException) - 也许你没有将它声明为提供者或者没有指定正确的异常类?
尽管如前所述,为异常返回不同的状态代码通常是不好的做法,应该避免。在这种情况下,修复实际问题可能更合适。
JAX-RS提供MessageBodyReader
和MessageBodyWriter
接口,您可以声明这些接口取消/编组对象或对象的输入流以返回到输出流。官方documentation on MessageBodyReader提供了有关这方面的更详细信息。
因此,一个实施可以是以下步骤:
"male"
或"female"
令牌替换为大写版本如果输入失败只是一个简单的大/小写问题,这是有效的。如果有错字或语义替代可用,但尚未在你的枚举中,你需要付出更多的努力。
但是,如果您无法创建正确的对象表示,则应将用户失败(400范围内的某些内容)返回给客户端,以通知客户端出现了问题。
答案 1 :(得分:1)
这是杰克逊对JsonParseExceptionMapper
或JsonMappingExceptionMapper
的回应。这些类带有依赖
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${2.x.version}</version>
</dependency>
无论您是否具有此显式依赖关系,或者您拥有resteasy-jackson2-provider(使用上面的内容),很可能是通过类路径扫描隐式注册映射器。例如,您有一个空的Application
类。
@ApplicationPath("/")
public class ResteasyApplication extends Application {}
这将通过类路径扫描导致发送/注册。如果您没有这些依赖项,并且如果您在Wildfly中,我不确定它们是如何注册的,但这就是发生的事情。
您可以为ExceptionMappers
和JsonParseException
JsonMappingException
@Provider
public class JsonMappingExceptionMapper
implements ExceptionMapper<JsonMappingException> {
@Override
public Response toResponse(JsonMappingException e) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
但是从我测试的内容来看,它是一个关于注册哪个,你的或杰克逊的翻版。映射器被放入一个Set(如此无序),然后被推入一个Map,所以只有一个得到了推进。按照我说的推进它们的顺序是一个折腾。
我想这实际上只是一个部分答案,因为除了明确注册所有类(最终disabling the classpath scanning)之外,我还没有找到保证使用你的mapper的解决方案,但那是麻烦。
但现在战斗已经缩小了。如果我以后有机会,我会再试一次
所以这不是一个解决方案,只是一个半概念证明,以展示我们如何使用我们的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
会注册,并覆盖现有的端点,无论是杰克逊还是我们的。
当然我们不想真正做到这一点,它只是展示了如何覆盖映射器。我无法弄清楚的是放置此代码的位置。我在ServletContextListener
构造函数中尝试了Application
Feature
的优先级较低的app.directive('myDraggable', function($document) {
return function($scope, $element, $attr) {
document.body.addEventListener('click', function () {
$scope.loggedInOpened = !$scope.loggedInOpened;
$scope.$apply();
}, false);
}
});
。我无法弄明白。在RESTeasy 最终注册之前,上述情况均未发生。