多くのメソッドを備えたRESTEasy Webサーバーがあります。すべての要求と応答を追跡するためにログバックを実装したいのですが、すべてのメソッドにlog.info()
を追加したくありません。
リクエストとレスポンスを1か所でキャッチしてログに記録する方法があるかもしれません。たぶん、RESTEasyのHTTP要求プロセスチェーンのフィルターのようなものです。
@Path("/rest")
@Produces("application/json")
public class CounterRestService {
//Don't want use log in controler every method to track requests and responces
static final Logger log = LoggerFactory.getLogger(CounterRestService.class);
@POST
@Path("/create")
public CounterResponce create(@QueryParam("name") String name) {
log.info("create "+name)
try {
CounterService.getInstance().put(name);
log.info("responce data"); // <- :((
return new CounterResponce();
} catch (Exception e){
log.info("responce error data"); // <- :((
return new CounterResponce("error", e.getMessage());
}
}
@POST
@Path("/insert")
public CounterResponce create(Counter counter) {
try {
CounterService.getInstance().put(counter);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
...
}
フィルタを作成して、ログに記録する必要があるエンドポイントに簡単にバインドし、エンドポイントを無駄なくビジネスロジックに集中させることができます。
フィルタをREST=エンドポイントにバインドするために、JAX-RSはメタ注釈 _@NameBinding
_ を提供し、次のように使用できます。
_@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Logged { }
_
_@Logged
_アノテーションは、 ContainerRequestFilter
を実装するフィルタークラスを装飾するために使用され、リクエストを処理できます。
_@Logged
@Provider
public class RequestLoggingFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Use the ContainerRequestContext to extract information from the HTTP request
// Information such as the URI, headers and HTTP entity are available
}
}
_
_@Provider
_ 注釈は、プロバイダースキャンフェーズ中にJAX-RSランタイムが検出できる拡張インターフェースの実装をマークします。
ContainerRequestContext
は、HTTPリクエストから情報を抽出するのに役立ちます。
以下は、ログに役立つHTTPリクエストから情報を取得するための ContainerRequestContext
API のメソッドです。
ContainerRequestContext#getMethod()
:リクエストからHTTPメソッドを取得します。ContainerRequestContext#getUriInfo()
:HTTPリクエストからURI情報を取得します。ContainerRequestContext#getHeaders()
:HTTPリクエストからヘッダーを取得します。ContainerRequestContext#getMediaType()
:エンティティのメディアタイプを取得します。ContainerRequestContext#getEntityStream()
:エンティティ入力ストリームを取得します。応答を記録するには、 ContainerResponseFilter
の実装を検討してください。
_@Logged
@Provider
public class ResponseLoggingFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException {
// Use the ContainerRequestContext to extract information from the HTTP request
// Use the ContainerResponseContext to extract information from the HTTP response
}
}
_
ContainerResponseContext
は、HTTP応答から情報を抽出するのに役立ちます。
ログに役立つHTTP応答から情報を取得するための ContainerResponseContext
API のメソッドを次に示します。
ContainerResponseContext#getStatus()
:HTTP応答からステータスコードを取得します。ContainerResponseContext#getHeaders()
:HTTP応答からヘッダーを取得します。ContainerResponseContext#getEntityStream()
:エンティティ出力ストリームを取得します。フィルターをエンドポイントのメソッドまたはクラスにバインドするには、上記で定義した_@Logged
_アノテーションを使用してアノテーションを付けます。注釈が付けられているメソッドやクラスの場合、フィルターが実行されます。
_@Path("/")
public class MyEndpoint {
@GET
@Path("{id}")
@Produces("application/json")
public Response myMethod(@PathParam("id") Long id) {
// This method is not annotated with @Logged
// The logging filters won't be executed when invoking this method
...
}
@DELETE
@Logged
@Path("{id}")
@Produces("application/json")
public Response myLoggedMethod(@PathParam("id") Long id) {
// This method is annotated with @Logged
// The request logging filter will be executed before invoking this method
// The response logging filter will be executed before invoking this method
...
}
}
_
上記の例では、ログフィルターは_@Logged
_アノテーションが付けられているため、myLoggedMethod(Long)
に対してのみ実行されます。
ContainerRequestContext
および ContainerResponseFilter
インターフェイスで利用可能なメソッドに加えて、 ResourceInfo
を注入できます _@Context
_ を使用してフィルターで:
_@Context
ResourceInfo resourceInfo;
_
要求されたURLと一致する Method
および Class
を取得するために使用できます。
_Class<?> resourceClass = resourceInfo.getResourceClass();
Method resourceMethod = resourceInfo.getResourceMethod();
_
HttpServletRequest
および HttpServletResponse
も注入に使用できます。
_@Context
HttpServletRequest httpServletRequest;
@Context
HttpServletResponse httpServletResponse;
_
_@Context
_ で挿入できるタイプについては、これを参照してください answer 。
インターセプターを試してください(Vanilla EJBインターセプターだけでなく、CDIを使用できます)。
彼らは横断的関心事(側面)を実装するためにそこにいます。