当前位置: 首页 > 知识库问答 >
问题:

Jersey-在无效的POST请求上未调用自定义异常映射器

丁阳羽
2023-03-14

我正在使用泽西2.22.1来实现REST API。

我创建了一个自定义异常映射器,将运行时异常映射到我选择的特定HTTP响应代码。

@Provider
public class MyExceptionMapper implements ExceptionMapper<RuntimeException>
{
    @Override
    public Response toResponse(RuntimeException exception)
    {
        ....
    }
}

我的资源类配置为接受POST请求的多个参数。

@Path("rest/api/1.0/test")
public class MyResource
{
    @NotNull(message = "Missing parameter 'param1'")
    @FormParam("param1")
    private String m_param1;

    @NotNull(message = "Missing parameter 'param2'")
    @FormParam("param2")
    private String m_param2;

    @POST
    @Produces(MediaType.TEXT_PLAIN)
    @Consumes("application/x-www-form-urlencoded")
    public Response test(String body)
    {
        ...
    }
}

当我发送不带任何参数的POST请求时:

curl -X POST http://192.168.0.2:9989/myApp/rest/api/1.0/test

我希望调用我的自定义异常映射器,但它没有被调用。相反,我得到了一堆非法状态异常。

WARNING: The following warnings have been detected: WARNING: Unknown HK2 failure detected:
MultiException stack 1 of 6
java.lang.IllegalStateException: The @FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded
    at org.glassfish.jersey.server.internal.inject.FormParamValueFactoryProvider$FormParamValueFactory.ensureValidRequest(FormParamValueFactoryProvider.java:183)
    at org.glassfish.jersey.server.internal.inject.FormParamValueFactoryProvider$FormParamValueFactory.getForm(FormParamValueFactoryProvider.java:167)
    at org.glassfish.jersey.server.internal.inject.FormParamValueFactoryProvider$FormParamValueFactory.provide(FormParamValueFactoryProvider.java:118)
    at org.glassfish.jersey.server.internal.inject.ParamInjectionResolver.resolve(ParamInjectionResolver.java:134)
    at org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:211)
    at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:234)
    at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:357)
    at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
    at org.glassfish.jersey.process.internal.RequestScope.findOrCreate(RequestScope.java:162)
    at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2072)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:767)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:706)
    at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:172)
    at org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:284)
    at org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:74)
    at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:109)
    at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112)
    at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112)
    at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112)
    at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:92)
    at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:61)
    at org.glassfish.jersey.process.internal.Stages.process(Stages.java:197)
    at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:318)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
    at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:384)
    at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:224)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
    at java.lang.Thread.run(Thread.java:745)

有人能解释为什么我的自定义异常映射器没有被调用吗?

注意,如果我在资源方法中抛出一个RuntimeException,然后发送一个有效的POST请求,那么就会调用异常映射器。所以我知道它在某种程度上起作用。

更新

我发现如果我将以下内容添加到HTTP请求中:

-H“内容类型:应用程序/x-www-form-urlencoded”

然后调用我的ConstraintViolationExceptionMapper。

@Provider
public class ConstraintViolationExceptionMapper implements ExceptionMapper<ConstraintViolationException>
{
    ...
}

但是如果我删除ConstraintViolationExceptionMapper,我的自定义异常映射器仍然没有被调用。

共有2个答案

司空温书
2023-03-14

公认的答案似乎不再正确。

所以我们从来没有机会处理它。

现在不是这样。检查中的正确解决方案https://stackoverflow.com/a/45478604/1271372.

我遵循这一点,实现了ExceptionMapper

当然,这应该返回代码400。我必须将响应体定制为JSON,而不是纯文本。

晏正豪
2023-03-14

遵循JAX-RS规范,对于@FormParam和其他@XxxParams,当参数解析过程中发生异常时,泽西抛出一个已经映射的异常。这是为了遵循规范以返回正确的响应状态。所以我们永远没有机会处理它。

泽西已经有一个ValidationException的映射器,它是ConstraintViolationException的超类。因此,当您为ConstrainViolationException提供映射器时,它比ValidationException的映射器更具体,因此它被调用。

即使我为ValidationException提供了映射器,当我发送没有头的请求时也不会调用它。你知道为什么吗?

因为参数解析发生在验证之前。

 类似资料:
  • 我有以下资源,它使用映射到POJO的JSON。 下面是 POJO 类: 当我发送带有正文{“title”:“Test title”}的POST请求时,一切正常。正如预期的那样,响应是测试。但是,当我将请求更改为{“titlee”:“Test title”}时,服务器会回复如下: 无法识别的字段“titlee”(类com.my.package.MyObject),在[Source:org.glass

  • 首先,我对这个问题太长表示最诚挚的歉意,但老实说,我不知道如何缩短它,因为每个部分都是一个特例。诚然,我可能对此视而不见,因为我已经把头撞到墙上好几天了,我开始绝望了。 我向所有通读这本书的人表示最大的尊重和感谢。 我希望能够通过使用Jersey ExceptionMapers将Shiro的AuthenticationException及其子类映射到JAX-RS响应,Jersey例外映射器是使用G

  • 再一次在布罗斯沃尔,一切都很完美。在PhoneGap应用程序上仅GET request有效

  • 我能够使用Json输出运行Jersey,并且能够在没有任何问题的情况下使用Json映射获得“get”请求。 我也有一些JSON方法,它们是“post”方法,它们映射到Java类,如下面的方法- 供您参考,我在这里或这里遵循指南 在给出一个有效的post请求时,它们都开始抛出下面的错误-

  • 我正在使用ApacheCXF、Spring和JAX-RS构建一个REST web服务,当输入JSON验证失败时,我需要在其中发送自定义异常。 我没有使用业务逻辑,而是尝试使用CXF、JAX-RS的现成bean验证功能。 Bean验证工作正常,但是,它总是抛出500个异常,这是不太有用的。根据留档,它是org.apache.cxf.jaxrs.validation.ValidationExcepti

  • 我想在从AbstractEndPoint派生的endpoint上使用不同的jackson ObjectMapper实例(而不是在其他映射URL上使用的实例)。 为了澄清这个问题,我不想更改或自定义对象映射器,它由不同的URL使用,不同的URL来自AbstractEndpoints(如HealtEndpoint、MetricsEndpoint)。我想专门将新的对象映射器注入到管理endpoint中。