私は、ユーザーのIDと各要求にSLF4J MDCを豊かにしようとしています。問題は、ID、カスタムによって時々体に、時にはパスパラメータとして、多くの方法で渡され、時には注入することができるということであるValueFactoryProvider
という最初の解読こと。
私は何とかすべて注入し(つまり、アクセスすることができれば、すでに直列化復元)パラメータ値を、私は簡単にこれらすべてのケースを扱うことができます。
たとえば、
次のようなリソースのために
@GET
//@Encrypted params are injected by a custom ValueFactoryProvider
public Something getSomething(@Encrypted("userId") String userId) {
return ...;
}
@POST
public Something getSomething(@RequestBody RequestWithUserId requestWithUserId) {
return ...;
}
私は、フィルタなどを持つことができます:
public class MdcFilter implements ContainerRequestFilter, ContainerResponseFilter {
@Context
private ResourceInfo resourceInfo;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
Method theMethod = resourceInfo.getResourceMethod();
for (Parameter parameter : theMethod.getParameters()) {
//Deal with the @Encrypted case
if (parameter.isAnnotationPresent(Encrypted.class) && parameter.getAnnotation(Encrypted.class).value().equals("userId")) {
MDC.put("userId", somehowGetTheValue());
}
//Deal with the @RequestBody case
if (parameter.isAnnotationPresent(RequestBody.class) && parameter.getType().equals(RequestWithUserId.class)) {
MDC.put("userId", ((RequestWithUserId)somehowGetTheValue()).getUserId());
}
... //other possibilities
}
}
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
MDC.clear();
}
}
しかし、私は実装する方法が表示されないsomehowGetTheValue
から、どちらかのContainerRequestFilter
迎撃や何かを...
ジャージーは使用していますHK2を依存性注入のためにボンネットの下に。そして、HK2はありAOPサポートを。ご利用の場合の1つのオプションは、このAOPサポートを使用するだろう。あなたがする必要があるすべては実装しているMethodInterceptor
とInterceptionService
。ではMethodInterceptor
、あなたはからすべての引数を取得することができMethodInvocation
、あなたはからパラメータの注釈を取得することができますMethod
class MyMethodInteceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
Object[] args = invocation.getArguments();
// do your logging or whatever with the args.
// invoke method and get return value.
Object returnValue = invocation.proceed();
// if you want to do something with the return
// value before returning it, you can.
return returnValue;
}
}
インターセプターを使用するには、設定しますInterceptionService
。
public class MyInterceptionService implements InterceptionService {
private final static MethodInterceptor METHOD_INTERCEPTOR
= new MyMethodInterceptor();
private final static List<MethodInterceptor> METHOD_LIST
= Collections.singletonList(METHOD_INTERCEPTOR);
@Override
public Filter getDescriptorFilter() {
return BuilderHelper.allFilter();
}
@Override
public List<MethodInterceptor> getMethodInterceptors(Method method) {
// you implement shouldIntercept
if (shouldIntercept(method)) {
return METHOD_LIST;
}
return null;
}
@Override
public List<ConstructorInterceptor> getConstructorInterceptors(Constructor<?> constructor) {
return null;
}
}
あなたには傍受されるべき方法を決定getMethodInterceptors()
する方法。この方法は、傍受されなければならない場合は、そうでない場合はnullを返し、インターセプタのリストを返します。これを処理する一般的な方法は、カスタムアノテーションを作成し、ちょうど方法に注釈を付けることです。上記の方法では、単にチェック
if (method.isAnnotationPresent(YourAnno.class)) {
return METHOD_LIST;
}
それはすべてを動作させるために、あなただけ登録する必要がありInteceptionService
HK2と。あなたにはそれを行うことができAbstractBinder
、あなたのDIを設定するには、ジャージーアプリで使用されているものです。
ResourceConfig config = new ResourceConfig();
config.register(new AbstractBinder() {
@Override
protected void configure() {
bind(MyInterceptionService.class)
.to(InterceptionService.class)
.in(Singleton.class);
}
});
あなたには、完全な例を参照することができ、このGitHubのレポ。HK2サイトでの公式の例もあります。ただ、ポストの上部にある「AOPサポート」のリンクを参照してください。