浏览Java EE Tutorial for JAX-RS,似乎他们没有提及jsr339-jaxrs-2.0-final-spec 中有关过滤器和拦截器的概念。您可能应该下载一份副本以获取完整信息。
过滤器和实体拦截器可以注册以在 JAX-RS 中定义明确的扩展点处执行
实施。它们用于扩展实现以提供诸如日志记录、
机密性、身份验证、实体压缩
实体拦截器在特定的扩展点包装方法调用。 过滤器在扩展点执行代码,但不包装方法调用。
最后一段基本上是说拦截器与方法调用发生在同一个执行堆栈中,而过滤器则没有。这并不意味着我们不能为您的日志记录案例使用过滤器。传递给过滤器接口方法的过滤器上下文实际上有更多可以使用的信息。
ContainerRequestFilter 和ContainerResponseFilter 分别通过ContainerRequestContext 和ContainerResponseContext,我们可以获取UriInfo 之类的东西来获取路径。
public interface ContainerResponseFilter {
void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext)
}
public interface ContainerRequestFilter {
void filter(ContainerRequestContext requestContext)
}
这是一个简单的日志过滤器示例。有几种不同的方法来绑定过滤器,但在这个例子中,我将使用dynamic binding 显式实例化过滤器,因此我没有容器管理状态,并将类和方法名称传递给过滤器
public class LoggingFilter implements ContainerRequestFilter,
ContainerResponseFilter {
private static final Logger logger
= Logger.getLogger(LoggingFilter.class.getName());
protected String className;
protected String methodName;
public NewLoggingFilter(String className, String methodName) {
this.className = className;
this.methodName = methodName;
}
@Override
public void filter(ContainerRequestContext requestContext)
throws IOException {
logger.log(Level.INFO, "Request path: {0}",
requestContext.getUriInfo().getAbsolutePath().toString());
logger.log(Level.INFO, "Starting Method: {0}.{1}",
new Object[]{className, methodName});
}
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext)
throws IOException {
logger.log(Level.INFO, "Finished Method: {0}.{1}",
new Object[]{className, methodName});
}
}
以下是我将方法绑定到过滤器的方法。每个资源方法都经过这个活页夹。如果它或它的类是带有我们自定义注解的注解,它将被绑定到LoggingFilter。我们还传递了LogginFilter 资源方法的类和方法名。我们将使用这些名称进行日志记录
@Provider
public class LoggingBinder implements DynamicFeature {
@Override
public void configure(ResourceInfo ri, FeatureContext fc) {
Class<?> clazz = ri.getResourceClass();
Method method = ri.getResourceMethod();
if (method.isAnnotationPresent(Logged.class)
|| clazz.isAnnotationPresent(Logged.class)) {
fc.register(new LoggingFilter(clazz.getName(), method.getName()));
}
}
}
它检查方法或类是否有注解@Logged(这是一个自定义注解——你可以很容易地调用它@Foo)
@NameBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface Logged {
}
使用这个资源类
@Path("/log")
public class LogResource {
@GET
@Logged
public Response getLoggingResourceMethod() {
return Response.ok("Hello Logging Response").build();
}
}
我们在日志中得到以下结果
Oct 25, 2014 4:36:05 PM jaxrs.stackoverflow.filter.NewLoggingFilter filter
INFO: Request path: http://localhost:8081/rest/log
Oct 25, 2014 4:36:05 PM jaxrs.stackoverflow.filter.NewLoggingFilter filter
INFO: Starting Method: jaxrs.stackoverflow.filter.LogResource.getLoggingResourceMethod
Oct 25, 2014 4:36:05 PM jaxrs.stackoverflow.filter.NewLoggingFilter filter
INFO: Finished Method: jaxrs.stackoverflow.filter.LogResource.getLoggingResourceMethod
Oct 25, 2014 4:36:05 PM jaxrs.stackoverflow.filter.NewLoggingFilter filter
INFO: Method successful.
不要忘记下载规范以获取更多详细信息。