【问题标题】:How to get access HttpServletRequest in constructor of resource-parentclass?如何在资源父类的构造函数中访问 HttpServletRequest?
【发布时间】:2013-08-06 06:14:33
【问题描述】:

我过滤了我的 REST 服务的 BasicAuth 并将用户名存储在 HttpServletRequest 中

AuthFilter相关代码

public class AuthFilter implements ContainerRequestFilter {

    @Context
    public transient HttpServletRequest servletRequest;    

    @Override
    public ContainerRequest filter(ContainerRequest containerRequest) throws WebApplicationException {

        // all the auth filter actions...  

        // Set data
        servletRequest.setAttribute("auth_username", username);

        return containerRequest;
    }
}

然后我有一个资源父类(称为 BaseResource,只有一些通用属性)和扩展它的特定类

示例特定类

@Path("/Plant")
public class PlantResource  extends BaseResource  {

    private List<Plant> plantlist = new LinkedList<Plant>();

    @GET
    @Path("/GetPlantById/plantid/{plantid}")
    @Produces("application/json")
    public String getPlantById(@PathParam("plantid") String plantid, @Context HttpServletRequest hsr) {

        String username = (String)hsr.getAttribute("auth_username");

        // do something 
    }
}

如您所见,我通过“@Context HttpServletRequest hsr”将 HttpServletRequest 处理到函数(如其中所述:Get HttpServletRequest in Jax Rs / Appfuse application?)。这工作正常,我可以正确访问数据!

我现在要做的是在父类的构造函数中访问这个Data,所以我不必在我指定资源的每个函数中都这样做,而是在一个地方进行

我的尝试:

public class BaseResource {

    @Context protected HttpServletRequest hsr; // Also tried private and public: 

    /* ... */

    public BaseResource() {

        String username = (String)hsr.getAttribute("auth_username"); // line 96

        System.out.println("constructur of BaseResource" + username);   
    }    
}

但这最终是:

Aug 05, 2013 3:40:18 PM com.sun.jersey.spi.container.ContainerResponse mapMappableContainerException
Schwerwiegend: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
java.lang.NullPointerException
  at de.unibonn.sdb.mobilehelper.resources.BaseResource.<init>(BaseResource.java:96)

那里似乎没有设置 HttpServletRequest。那么如何在父类的构造函数中访问呢?

【问题讨论】:

    标签: java rest servlets constructor jax-rs


    【解决方案1】:

    BaseResource 的字段是在创建实例后注入的,因此您不能在构造函数本身中引用它们。在您的BaseResource 中创建一个属性方法:

    public class BaseResource {
    
        @Context
        protected HttpServletRequest hsr;
    
        /* ... */
    
        protected String getUsername() {
            return (String)hsr.getAttribute("auth_username");
        }    
    }
    

    或创建一个层次结构,如:

    public class BaseResource {
    
        protected HttpServletRequest hsr;
    
        /* ... */
    
        public BaseResource(HttpServletRequest hsr) {
            this.hsr = hsr;
    
            String username = (String)hsr.getAttribute("auth_username");
            System.out.println("constructur of BaseResource" + username);   
        }    
    }
    

    @Path("/Plant")
    public class PlantResource  extends BaseResource  {
    
        private List<Plant> plantlist = new LinkedList<Plant>();
    
        public PlantResource(@Context HttpServletRequest hsr) {
            super(hsr);
        }
    
        @GET
        @Path("/GetPlantById/plantid/{plantid}")
        @Produces("application/json")
        public String getPlantById(@PathParam("plantid") String plantid) {
            String username = (String)hsr.getAttribute("auth_username");
            // do something 
        }
    }
    

    【讨论】:

    • 非常感谢您通过子类的构造函数将 httpServletRequest 传递给父类的想法。完全忘记了这种方式,只考虑了父类中的构造函数,但它运行良好,并且实现了避免重复源代码的目标!
    【解决方案2】:

    你必须通过一个函数来传递它。正如您所指出的,@Context 之类的 JAX-RS 注释在父级中不可用。他们也没有继承下来。此外,您不能在构建时执行此操作,因为不能保证 @Context 引用在构建期间可用(取决于容器如何创建资源)。

    【讨论】:

      猜你喜欢
      • 2011-06-13
      • 1970-01-01
      • 1970-01-01
      • 2014-09-07
      • 2019-05-21
      • 2018-06-16
      • 2013-12-27
      • 2020-03-16
      • 2011-02-05
      相关资源
      最近更新 更多