如何在resource-parentclass的构造函数中访问HttpServletRequest?

时间:2013-08-05 13:50:08

标签: java rest servlets constructor jax-rs

我过滤了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?中所述)。这很好,我可以正确访问数据!

我现在要做的是在父类的构造函数中访问此数据,因此我不必在指定资源的每个函数中执行此操作,而是在一个地方

我的尝试:

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没有在那里设置。那么如何在我的父类的构造函数中访问它?

2 个答案:

答案 0 :(得分:3)

在创建实例后注入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 
    }
}

答案 1 :(得分:1)

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