【问题标题】:java.lang.IllegalStateException: ServletConfig has not been initializedjava.lang.IllegalStateException:ServletConfig 尚未初始化
【发布时间】:2016-07-10 01:29:04
【问题描述】:

我正在尝试创建一个允许用户自定义会话超时的 UI 组件。所以我创建了一个如下的servlet:

public class SessionTimeoutServlet extends AbstractBaseServlet {
    private static final long serialVersionUID = 2567293974465204729L;

    public static final String REQUEST_TIMEOUT_PARAMETR_NAME = "timeout";
    private static final String TIMEOUT_TYPE_INIT_PARAMETER_NAME = "timeoutType";
    private static final String WEB_TYPE_TIMEOUT = "web";
    private static final String WEBSERVICE_TYPE_TIMEOUT = "webService";

    @EJB(mappedName = SessionSettingsRemote.BEAN_NAME)
    private SessionSettingsRemote sessionSettingsBean;

    @PostConstruct
    public void initTimeout() {
        try {
            String timeoutType = getServletContext().getInitParameter(TIMEOUT_TYPE_INIT_PARAMETER_NAME);
            if (WEBSERVICE_TYPE_TIMEOUT.equals(timeoutType)) {
                setCustomTimeout(sessionSettingsBean.getSessionSettingsDTO().getWebServiceSessionTimeoutInterval());
            } else if (WEB_TYPE_TIMEOUT.equals(timeoutType)) {
                setCustomTimeout(sessionSettingsBean.getSessionSettingsDTO().getWebSessionTimeoutInterval());
            } else {
                setCustomTimeout(30);
            }
        } catch (ApplicationException e) {
            setCustomTimeout(30);
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int timeout = Integer.parseInt(request.getParameter(REQUEST_TIMEOUT_PARAMETR_NAME));
        setCustomTimeout(timeout);
    }

    public static void setCustomTimeout(int customTimeout) {
        SessionManagerListener.setCustomTimeout(customTimeout);
    }

}

但是,当我在 GlassFish 上部署它时,我遇到了以下异常。

Caused by: java.lang.IllegalStateException: ServletConfig has not been initialized
    at javax.servlet.GenericServlet.getServletContext(GenericServlet.java:199)
    at com.accedian.ems.uiapplication.server.servlets.SessionTimeoutServlet.initTimeout(SessionTimeoutServlet.java:33)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl$3.run(InjectionManagerImpl.java:766)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.invokeLifecycleMethod(InjectionManagerImpl.java:760)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:531)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:141)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:127)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:347)
    at com.sun.enterprise.web.WebContainer.createServletInstance(WebContainer.java:991)
    at com.sun.enterprise.web.WebModule.createServletInstance(WebModule.java:2130)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1404)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1381)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5732)

我在getServletContext() 之前使用过getServletConfig(),但它是null。那么为什么我的配置和上下文没有正确设置呢?

【问题讨论】:

  • 不要使用 @PostConstruct 替代 init 方法。这将在生命周期中过早调用(在构造之后但在容器更改调用 init(ServletConfig) 之前,因此一切仍然是 null

标签: servlets illegalstateexception servletconfig


【解决方案1】:

Servlet 早于托管 bean 和注释以及自 Java EE 6 以来您看到的所有花哨的东西。以前,您必须显式实现预定义的抽象/模板方法才能在生命周期的某个时刻执行任务。

对于 servlet,为了像在“普通”托管 bean 上使用 @PostConstruct 一样挂钩其初始化,您必须覆盖预定义的 GenericServlet#init() 方法。

@Override
public void init() {
    // ...
}

getServletContext() 将在那里可用。

如果您注意GenericServlet javadoc,您会注意到还有一个init(ServletConfig)。但是,强烈建议不要使用该方法,而是使用init()init(ServletConfig) 的默认实现即注意正确设置 ServletContext。您必须介意拨打super.init(config) 以免犯同样的错误。作为历史记录,请注意,您在托管 bean 上看到的 @PostConstruct 方法的规范名称“init”正是从这个 Servlet API 继承的。

如果您想知道,@PreDestroy 等价物是 GenericServlet#destroy() 方法。

@Override
public void destroy() {
    // ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-02
    • 2021-06-21
    • 2020-06-17
    • 2015-07-24
    相关资源
    最近更新 更多