Java 在应用程序中获取 ServletContext

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19450202/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 17:16:29  来源:igfitidea点击:

Get ServletContext in Application

javajerseyjax-rs

提问by Industrious

Could you possibly explain how I can get the ServletContextinstance in my Application's sub-class? Is it possible? I have tried to do it like in the following snippet but it does not seem to work - the ctxis not set:

你能解释一下我如何ServletContext在我Application的子类中获取实例吗?是否可以?我试图像在以下代码段中那样做,但它似乎不起作用 -ctx未设置:

import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;

//...

@ApplicationPath("/")
public class MainApplication extends Application {

    @Context ServletContext ctx;

    @Override
    public Set<Class<?>> getClasses() {     
        Set<Class<?>> classes = new HashSet<Class<?>>();
//...
        return classes;
    }
}

web.xml:

网页.xml:

<web-app ...>
 <context-param>
  <param-name>environment</param-name>
  <param-value>development</param-value>
 </context-param>
 <filter>
  <filter-name>jersey-filter</filter-name>
  <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
   <init-param>
   <param-name>javax.ws.rs.Application</param-name>
   <param-value>my.MainApplication</param-value>
  </init-param>
</filter>
...
</web-app>

The problem is that I need to get context parameters from it. If there is another way, I would be grateful if somebody gave a hint.

问题是我需要从中获取上下文参数。如果有另一种方式,如果有人给出提示,我将不胜感激。



I understand that Contextannotation might not be purposed for this. Actually, I do not need ServletContextitself. If only I could get context params from web.xml, I would be absolutely happy.

我知道Context注释可能不是用于此目的。其实,我不需要ServletContext自己。如果我能从 web.xml 获取上下文参数,我会非常高兴。

Here is an example of what I really need:

这是我真正需要的一个例子:

import java.util.HashSet;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;

import org.glassfish.hk2.utilities.binding.AbstractBinder;

public class MainApplication extends Application {

    @Context ServletContext ctx;

    @Override
    public Set<Object> getSingletons() {
        Set<Object> set = new HashSet<Object>();
        final String environment = ctx.getInitParameter("environment");
        //final String environment = ... get context parameter from web xml
        set.add(new AbstractBinder() {

            @Override
            protected void configure() {
                bind(new BaseDataAccess(environment)).to(DataAccess.class);             
            }
        });
        //...
        return set;
    }
}

Thanks.

谢谢。

采纳答案by Laurent Mazuel

Since Jersey 2.5, ServletContext can be injected directly in constructor: https://java.net/jira/browse/JERSEY-2184

从 Jersey 2.5 开始,ServletContext 可以直接注入到构造函数中:https: //java.net/jira/browse/JERSEY-2184

public class MyApplication extends ResourceConfig {
    public MyApplication(@Context ServletContext servletContext) {
       // TODO
    }
}

回答by user987339

Injection happens when you enter service method. Check if this is a problem.

进入服务方法时会发生注入。检查这是否有问题。

回答by user987339

Don't use @Contextin your Applicationbut in a Resource class.

不要@Context在您的Application但在 Resource 类中使用。

@Path("/foos")
public class FooResource {

  @Context
  ServletContext ctx;

  @GET
  public Response getFoos() {
    return Response.ok().build();
  }
}

回答by Sergey Petrunin

There is interesting statement in documentation for Jersey version 1.18 for class com.sun.jersey.spi.container.servlet.ServletContainer

对于类com.sun.jersey.spi.container.servlet.ServletContainer 的Jersey 版本 1.18 的文档中有一个有趣的声明

The servlet or filter may be configured to have an initialization parameter "com.sun.jersey.config.property.resourceConfigClass" or "javax.ws.rs.Application" and whose value is a fully qualified name of a class that implements ResourceConfig or Application. If the concrete class has a constructor that takes a single parameter of the type Map then the class is instantiated with that constructor and an instance of Map that contains all the initialization parameters is passed as the parameter.

servlet 或过滤器可以配置为具有初始化参数“com.sun.jersey.config.property.resourceConfigClass”或“javax.ws.rs.Application”,其值是实现 ResourceConfig 或应用。如果具体类有一个构造函数,该构造函数采用 Map 类型的单个参数,则使用该构造函数实例化该类,并且包含所有初始化参数的 Map 实例作为参数传递。

If my understanding is correct the following constructor must be invoced with "an instance of Map that contains all the initialization parameters"

如果我的理解是正确的,则必须使用“包含所有初始化参数的 Map 实例”调用以下构造函数

public class ExampleApplication extends Application {
    public ExampleApplication(Map initParams) {
    }
    ...
}

Here is appropriate part of web.xml:

这是 web.xml 的适当部分:

<servlet>
  <servlet-name>Jersey Web Application</servlet-name>
  <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
       <param-name>javax.ws.rs.Application</param-name>
       <param-value>experiment.service.ExampleApplication</param-value>
    </init-param>
</servlet>

But somehow it failed for me with the following message:

但不知何故,我失败了,并显示以下消息:

SEVERE: Missing dependency for constructor public experiment.service.ExampleApplication(java.util.Map) at parameter index 0

严重:在参数索引 0 处缺少构造函数 publicexperiment.service.ExampleApplication(java.util.Map) 的依赖项

And for current version of Jersey (2.5.1) there are no such statement in documentstion: https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/servlet/ServletContainer.html

对于当前版本的 Jersey (2.5.1),文档中没有这样的声明:https: //jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/servlet/ServletContainer.html

回答by zyexal

You can use the ApplicationEventListenerinterface to get the ServletContext. After initialization has finished, you can 'catch' an ApplicationEventand use the injected ServletContextto work with.

您可以使用该ApplicationEventListener接口获取ServletContext. 初始化完成后,您可以“捕获”ApplicationEvent并使用注入的对象ServletContext进行处理。

Works fine with: org.glassfish.jersey : 2.12
For additional versions, pls use comments - i dont know, sry.

适用于:org.glassfish.jersey : 2.12
对于其他版本,请使用注释 - 我不知道,对不起。

Jersey Docs - 20.1.2. Event Listeners

泽西岛文档 - 20.1.2。事件监听器

Your MainApplication:

你的MainApplication

@ApplicationPath("/")
public class MainApplication extends Application {
    @Override
    public Set<Class<?>> getClasses() {     
        Set<Class<?>> set = new HashSet<Class<?>>();
        set.add(MainApplicationListener.class);
        return classes;
    }
}

... or alternative MainResourceConfig(I prefer to use this one):

...或替代方案MainResourceConfig(我更喜欢使用这个):

public class MainResourceConfig extends ResourceConfig {
    public MainResourceConfig() {
        register(MainApplicationListener.class);
    }
}

And the ApplicationEventListener:

ApplicationEventListener

public class MainApplicationListener implements ApplicationEventListener {

    @Context
    private ServletContext ctx; //not null anymore :)

    @Override
    public void onEvent(ApplicationEvent event) {
        switch (event.getType()) {
            case INITIALIZATION_FINISHED:
            // do whatever you want with your ServletContext ctx
            break;
    }

    @Override
    public RequestEventListener onRequest(RequestEvent requestEvent) {
        return null;
    }

}

回答by Haruo Kinoshita

@Contextcan be made available on ResoureConfigby injecting it as a constructor parameter using @Context. Another way to access it is through an event handler.

@Context可以通过使用ResoureConfig将其作为构造函数参数注入来使其可用@Context另一种访问它的方法是通过事件处理程序

Try the below code.

试试下面的代码。

@ApplicationPath("...")
public class MyApplication extends ResourceConfig {
    public MyApplication() {
        register(StartupHandler.class);
    }

    private static class StartupHandler extends  AbstractContainerLifecycleListener {
        @Context
        ServletContext ctx;

        @Override
        public void onStartup(Container container) {
            // You can put code here for initialization. 
        }
    }
// ...