在Jersey中是否有类似于Spring的HandlerInterceptor的拦截器

我需要Jersey 2.x中的一个Interceptor,它提供对请求,响应和与Web服务路径匹配的方法的引用.

类似于Spring的HandlerInterceptor的东西.

要求:

>需要在类上使用注释 – 执行以下检查,仅当需要由jersey调用的相应方法未使用自定义注释进行注释时.
>请求 – 获取/设置属性并获取会话对象以验证用户.
>响应 – 即使在调用相应的Methos之前,如果任何验证失败,也要重新定向呼叫.

Spring等效代码:

public class WebServiceInterceptor implements HandlerInterceptor {
     @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        try {
            SkipWebServiceIntercept skipWebService = handler.getClass().getAnnotation(SkipWebServiceIntercept.class);

            if (skipWebService != null) {
                return Boolean.TRUE;
            }

            ...

            if(securityFails)
            {
                if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
                    response.setCharacterEncoding("utf-8");
                    response.setContentType("application/json");
                    PrintWriter out = response.getWriter();
                    String json;
                    ...
                    out.println(json);
                    return Boolean.FALSE;
                }
                else {
                    response.sendRedirect(redirectUrl);
                }
            }
            else
            {
                return Boolean.TRUE;
            }
        }catch (Exception e) {
            log.error("Exception in preHandle, redirecting to Login page", e);
            return LoginUtil.redirectToLogin(request, response);
        }
    }
}

我找到了参考资料

> ReaderInterceptor – 这只提供了类的注释.无法访问请求/响应.
> ContainerRequestFilter – 提供请求对象但不提供注释/响应.
> ContainerResponseFilter – 提供请求&响应.但是在调用web-service / Method之后.

有没有其他方法可以在不使用过滤器的情况下实现.因为只有相应的网络服务存在,才需要进行此处理.
另一方面,使用/ *过滤器将始终执行这些验证,即使找不到资源也是如此.

编辑:
感谢@peeskillet answer这是我实现它的方式.

@Provider
public class ResourceInterceptor implements DynamicFeature {

    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context) {

        System.out.println("Resource Interceptor called");

        if (resourceInfo.getResourceClass() != null
                && resourceInfo.getResourceClass().getAnnotation(SkipWebServiceIntercept.class) != null)
            return;

        context.register(LoginFilter.class);
    }

}


@Slf4j
public class LoginFilter implements ContainerRequestFilter {

    @Context
    private HttpServletRequest      request;

    @Context
    private ServletContext          servletContext;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        try {


WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);

CookieAuthenticator cookieAuthenticator = springContext.getBean(CookieAuthenticator.class);

HttpSession session = request.getSession(true);

...

// Sending JSON/Object back as response

...
String json = gson.toJson(resposeJson);

Response response = new ResponseBuilderImpl().encoding(StandardCharsets.UTF_8.name())
                        .type(MediaType.APPLICATION_JSON).entity(json).build();
requestContext.abortWith(response);
...

// or Sending URL back

...
URI uri = new URI(baseUrl + redirectUrl + "?refback=" + url);
requestContext.abortWith(Response.temporaryRedirect(uri).build());
...

这两种方法都很完美,类似于Spring的HandlerInterceptor.

解决方法:

Is there anyother way this can be achieved without using Filters. because I need this processing to happen ONLY if the corresponding web-service is present. Filter’s with /* on the other hand would always perform these validations even when the resource was not found.

注册过滤器的方法有很多种.

>只需正常注册,结果就是调用过滤器. (你不想要的).
>使用注释注册,但是name binding.这样,只有注释的资源才能通过过滤器. (这是你想要的,只有问题是你需要注释每个类)

@Target({TYPE, METHOD})
@Retention(RetentionPolicy.RUNTIME);
class @interface Filtered {}

@Path("..")
@Filtered
public class YourResource {}

@Filtered
@Provider
public class YourFilter implements ContainerRequestFilter {}

> Use a DynamicFeature以编程方式绑定资源,而不是以声明方式绑定.将为每个资源方法调用DynamicFeture,因此您只需为每个调用注册过滤器.这与使用名称绑定注释每个资源类(如上所述)具有相同的效果(这可能是您想要的).

@Provider
public class MyFeature implements DynamicFeature {
    @Override
    public void configure(ResourceInfo ri, FeatureContext ctx) {
        ctx.register(YourFilter.class);
    }
}

也可以看看:

> Chapter 10. Filters and Interceptors

上一篇:java – Spring Boot – 可以拦截@Async服务方法吗?


下一篇:Linux下切换Python版本的几种方法