2

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

4

2 回答 2

4

的字段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 
    }
}
于 2013-08-05T14:09:56.293 回答
1

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

于 2013-08-05T14:11:21.837 回答