79

RESTEasy JAX-RS実装を使用して、Web サービス コンポーネントをJBoss Application Server 7にデプロイします。

JAX-RSで必須、必須の @QueryParamパラメータを宣言するために使用できる注釈はありますか? そうでない場合、そのようなパラメーターが欠落している状況に対処する「標準的な」方法は何ですか?

私の Web サービス (リソース) メソッドは、すべての必須引数で適切に呼び出されると JSON 文字列化された結果を返しますが、必須パラメーターが欠落していることを呼び出し元に示す最良の方法がわかりません。

4

4 に答える 4

77

良い質問。残念ながら(または幸いなことに)、JAX-RSにはパラメータを必須にするメカニズムがありません。パラメータが指定されていない場合、その値はにNULLなり、リソースはそれに応じて処理する必要があります。WebApplicationExceptionユーザーに通知するために使用することをお勧めします。

@GET
@Path("/some-path")
public String read(@QueryParam("name") String name) {
  if (name == null) {
    throw new WebApplicationException(
      Response.status(Response.Status.BAD_REQUEST)
        .entity("name parameter is mandatory")
        .build()
    );
  }
  // continue with a normal flow
}
于 2012-12-20T19:44:15.770 に答える
68

javax.validation注釈を使用して、パラメーターに@javax.validation.constraints.NotNull. Jersey の例RESTeasyの例を参照してください。

したがって、メソッドは次のようになります。

@GET
@Path("/some-path")
public String read(@NotNull @QueryParam("name") String name) {
  String something = 
  // implementation
  return something;
}

例外は、JAX-RS プロバイダーによって何らかのエラー コードに変換されることに注意してください。通常は、独自の の実装を登録することでオーバーライドできますjavax.ws.rs.ext.ExceptionMapper<javax.validation.ValidationException>

これにより、必須パラメータをエラー レスポンスに変換する一元化された方法が提供され、コードの重複は必要ありません。

于 2014-02-20T21:56:55.937 に答える
18

私は同じ問題に遭遇し、無数のボイラープレートの null チェックを REST コード全体に分散させたくないと判断したため、これを行うことにしました。

  1. 必須パラメーターが指定されていない場合に例外をスローするアノテーションを作成します。
  2. スローされた例外を、REST コードでスローされた他のすべての例外を処理するのと同じ方法で処理します。

1)については、次の注釈を実装しました。

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Required
{
    // This is just a marker annotation, so nothing in here.
}

ContainerRequestFilter...そしてそれを強制する次のJAX-RS :

import java.lang.reflect.Parameter;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;

@Provider
public class RequiredParameterFilter implements ContainerRequestFilter
{
    @Context
    private ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext requestContext)
    {
        // Loop through each parameter
        for (Parameter parameter : resourceInfo.getResourceMethod().getParameters())
        {
            // Check is this parameter is a query parameter
            QueryParam queryAnnotation = parameter.getAnnotation(QueryParam.class);

            // ... and whether it is a required one
            if (queryAnnotation != null && parameter.isAnnotationPresent(Required.class))
            {
                // ... and whether it was not specified
                if (!requestContext.getUriInfo().getQueryParameters().containsKey(queryAnnotation.value()))
                {
                    // We pass the query variable name to the constructor so that the exception can generate a meaningful error message
                    throw new YourCustomRuntimeException(queryAnnotation.value());
                }
            }
        }
    }
}

他のクラスを JAX-RS ライブラリにContainerRequestFilter登録するのと同じ方法でを登録する必要があります。@Providerおそらく、RESTEasy が自動的にそれを行います。

2)については、一般的な JAX-RS を使用してすべての実行時例外を処理しますExceptionMapper

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class MyExceptionMapper implements ExceptionMapper<RuntimeException>
{
    @Override
    public Response toResponse(RuntimeException ex)
    {
        // In this example, we just return the .toString() of the exception. 
        // You might want to wrap this in a JSON structure if this is a JSON API, for example.
        return Response
            .status(Response.Status.BAD_REQUEST)
            .entity(ex.toString())
            .build();
    }
}

以前と同様に、クラスを JAX-RS ライブラリに登録することを忘れないでください。

于 2015-08-08T13:29:44.350 に答える
2

おそらく最も簡単な方法は、@Nonnullfromを使用しjavax.annotationてこれを実現することです。@QueryParam以下に示すように、前に追加するだけなので、使い方は非常に簡単です。

ただし、これはパラメーターが null の場合に をスローするIllegalArgumentExceptionため、返される応答は例外に対して何を行っても返されることに注意してください。あなたがそれを傍受しなければ、それは になります500 Server Errorが、送り返す正しいものは400 Bad Request. それを傍受IllegalArgumentExceptionして処理し、適切な応答を返すことができます。


例:

import javax.annotation.Nonnull;
...

    @GET
    @Path("/your-path")
    public Response get(@Nonnull @QueryParam("paramName") String paramName) {
        ... 
    }

呼び出し元に返されるデフォルトのエラー メッセージは次のようになります。

{"timestamp":1536152114437,"status":500,"error":"Internal Server Error","exception":"java.lang.IllegalArgumentException","message":"com の @Nonnull パラメータ 'paramName' の引数/example/YourClass.get は null であってはなりません","path":"/path/to/your-path"}

于 2018-09-05T13:11:17.610 に答える