2016-03-01 100 views
1

我需要Jersey 2.x中的Interceptor,它提供了对请求,响应和与Web服务的路径匹配的方法的引用。Jersey中是否存在类似于Spring的HandlerInterceptor的拦截器

类似的东西到春天的的HandlerInterceptor

要求:

  1. 需要对 Class用于注解 - 执行下面的检查,只有当需要由球衣调用相应的方法不是使用自定义注解。
  2. 请求 - 获取/设置属性并获取会话对象来验证用户。
  3. 响应 - 重新定向的情况下,任何验证,甚至调用相应Methos之前失败的呼叫。

春等效代码:

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); 
     } 
    } 
} 

我发现

  1. ReaderInterceptor的引用 - 这只是提供了类的注释。无法访问请求/响应。
  2. ContainerRequestFilter - 提供请求对象但不提供注释/响应。
  3. ContainerResponseFilter - 给请求&响应。但是在调用Web服务/方法之后。

有任何其它方式这可以在不使用过滤器来实现。因为只有当相应的Web服务存在时,我才需要进行此处理。 另一方面,使用/ *的过滤器将始终执行这些验证,即使资源未找到。

编辑: 感谢@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); 

... 

//发送JSON /对象回到作为响应

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

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

//或发送URL背面

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

两者的方法完美地工作,类似于HandlerInterce春天的ptor。

回答

1

有任何其它方式这可以在不使用过滤器来实现。因为只有当相应的Web服务存在时,我才需要进行此处理。另一方面,使用/ *的过滤器将始终执行这些验证,即使找不到该资源。

有不同的方法来注册一个过滤器。

  1. 只需注册就正常,其结果为过滤总是获取调用。 (你不想要的)。

  2. 注册了注释,但是name binding。这样,只有资源注释才会通过过滤器。 (这是你想要什么,唯一的问题是,你需要注释的每个类)

    @Target({TYPE, METHOD}) 
    @Retention(RetentionPolicy.RUNTIME); 
    class @interface Filtered {} 
    
    @Path("..") 
    @Filtered 
    public class YourResource {} 
    
    @Filtered 
    @Provider 
    public class YourFilter implements ContainerRequestFilter {} 
    
  3. Use a DynamicFeature以编程方式绑定的资源,而不是声明。 DynamicFeture将被调用您的每个资源方法,因此您可以每调用注册筛选器。这与使用名称绑定注释每个资源类(如上所述)具有相同的影响(这可能是您想要的)。

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

另请参见:

+0

使用'ContainerRequestFilter'的是,我不会有响应对象与我的问题。我可以访问ResourceInfo来检查注释,但如果验证失败,那么我将不得不从过滤器本身重定向而不调用资源。 使用** Servlet过滤器**我可以使用response.sendRedirect()来实现这一点。我如何使用ContainerRequestFilter来做到这一点?我探索了ContainerRequestContext的所有API,但无法找到响应。 那么有没有办法从ContainerRequestFilter重定向到另一个URL呢? –

+0

您可以使用'requestContext.abortWith(Response)'...('Response.seeOther(...)'进行重定向) –

+0

或者您可以抛出异常并在[ExceptionMapper]中处理重定向(https:// jersey.java.net/documentation/latest/representations.html#d0e6665) –