Jersey中有一个Interceptor类似于Spring的HandlerInterceptor [英] Is there an Interceptor in Jersey similar to that of Spring's HandlerInterceptor

查看:252
本文介绍了Jersey中有一个Interceptor类似于Spring的HandlerInterceptor的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Jersey 2.x中需要一个拦截器,它提供了请求,响应和与Web服务的路径相匹配的方法的引用。

类似于< Spring的HandlerInterceptor 。



要求:


  1. <
  2. 需要批注 > Request - 获取/设置属性并获取Session对象来验证用户。
  3. 响应甚至在调用相应的方法之前失败。

等价的Spring代码:

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

尝试{
SkipWebServiceIntercept skipWebService = handler.getClass()。getAnnotation(SkipWebServiceIntercept.class);

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



$ b if(securityFails)
{
if(XMLHttpRequest.equals(request.getHeader( X-Requested-With))){
response.setCharacterEncoding(utf-8);
response.setContentType(application / json);
PrintWriter out = response.getWriter();
字符串json;
...
out.println(json);
返回Boolean.FALSE;
}
else {
response.sendRedirect(redirectUrl);
}
}
else
{
return Boolean.TRUE;

} catch(Exception e){
log.error(preHandle中的异常,重定向到登录页面,e);
返回LoginUtil.redirectToLogin(request,response);



$ / code $ / $ p

我找到了 p>


  1. ReaderInterceptor - 仅提供类的注释。无法访问请求/响应。
  2. ContainerRequestFilter - 提供Request对象,但不提供注释/响应

  3. ContainerResponseFilter - 给请求&响应。但在调用web服务/方法之后。

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

编辑:
感谢@peeskillet 回答这就是我的实施方式。

  @Provider 
public class ResourceInterceptor implements DynamicFeature {

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

System.out.println(Resource Interceptor called);
$ b $ if(resourceInfo.getResourceClass()!= null
&& amp; resourceInfo.getResourceClass()。getAnnotation(SkipWebServiceIntercept.class)!= null)
return;

context.register(LoginFilter.class);




$ slf4j
public class LoginFilter implements ContainerRequestFilter {

@Context
私有HttpServletRequest请求;

@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);
$ b ...




//发送JSON / Object作为回应



  ... 
字符串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());
...

这两种方法都很完美,类似于Spring的HandlerInterceptor。有没有其他的方法可以实现,而不使用过滤器。因为只有当相应的Web服务存在时,我才需要这个处理。过滤器的/ *在另一方面总是执行这些验证,即使没有找到资源。

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


  1. 只要正常注册,其结果是过滤器总是被调用。 (你不想要的东西)。


  2. 使用注释进行注册,但名称绑定。这样,只有资源注释才会通过过滤器。 (这是 你想要的东西,唯一的问题是你需要注释每个类)

    $ p $ @Target({TYPE,METHOD})
    @Retention(RetentionPolicy.RUNTIME);
    class @interface已过滤{}

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

    @已过滤
    @Provider
    公共类YourFilter实现ContainerRequestFilter {}


  • 使用DynamicFeature 以编程方式绑定资源,而不是声明性地绑定。 DynamicFeture 将被调用,用于每个资源方法,因此每次调用都可以为每个调用注册一次过滤器。这与注释每个资源类(如上所述)具有名称绑定(这可能是你想要的)相同的影响。

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


    code


    另见:

    Chapter 10.过滤器和拦截器


  • I need an Interceptor in Jersey 2.x which gives references to request, response and the Method which matched the Path to a Web Service.

    Something similar to HandlerInterceptor of Spring.

    Requirements:

    1. Need Annotations used on Class - Perform the below checks, Only if the corresponding Method which needs to be invoked by jersey is NOT Annotated with a custom annotation.
    2. Request - To get/set attributes and get Session Object to validate user.
    3. Response - To re-direct the call in case any validation fails even before invoking the corresponding Methos.

    Spring equivalent code:

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

    I found references of

    1. ReaderInterceptor - This provides just Annotations of the Class. No access to request/response.
    2. ContainerRequestFilter - Provides Request Object but no Annotations/Response.
    3. ContainerResponseFilter - Gives Request & Response. But after the web-service/Method is invoked.

    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.

    Edit: Thanks to @peeskillet answer This is how I implemented it.

    @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());
    ...
    

    Both the approaches worked perfectly, similar to HandlerInterceptor of Spring.

    解决方案

    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.

    There are different ways to register a filter.

    1. Just register it normally, where the result is the filter always getting called. (what you don't want).

    2. Registered with an annotation, though name binding. This way, only resource annotated will go through the filter. (this is kind of what you want, only problem is you would need to annotate every class)

      @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 to bind resource programmatically, rather than declaratively. The DynamicFeture will get called for each of your resource methods, so you can just register the filter for every call. This has the same affect as annotating every resource class (as mentioned above) with name binding (this is probably what you want).

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

    See Also:

    这篇关于Jersey中有一个Interceptor类似于Spring的HandlerInterceptor的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆