2014-10-31 4 views
2

У меня есть метод в классе, который не получает все, что может быть использовано для получения фактического контекста сервлета. Практически это похоже наКак получить контекст без запроса, сеанса и т. Д.?

public String getSomething() { ... } 

Но для вычисления результата мне нужны фактические структуры сервлетов, специфичные для потоков.

Я думаю, что где-то в глубине контекста приложения должны существовать некоторые, подобные потоковому хранилищу, которые могут быть достигнуты путем вызова статических методов некоторого системного класса.

Я в контейнере сервлетов tomcat6, но Spring также доступен, если это необходимо.

ответ

3

Очевидным решением было бы передать контекст в качестве параметра, поскольку вы, очевидно, используете код, в котором контекст обычно доступен.

Если по какой-то причине вы чувствуете, что это не то, что вы можете сделать (я хотел бы услышать причину этого), другим способом было бы создать фильтр сервлета, который затем создавал бы, например, ThreadLocal<ServletContext>.

+1

действительно ли понадобился «ThreadLocal»?AFAIK, 'ServletContext' определяется только один раз за VM – epoch

+0

@epoch Возможно, у разных веб-приложений есть другой ServletContext? – peterh

+0

Большое спасибо - наконец, я сделал вашу первую идею: я дал servletContext в новом сеттере для bean-компонента. Возможно, это не самое удачное решение, но, безусловно, оно было самым простым и независимым от платформы. – peterh

6

Добавить ServletContextListener на ваш web.xml. Это будет вызываться при загрузке вашего webapp. В методе contextInitialized() вы можете сохранить ServletContext в статической переменной, например, для последующего использования. После этого вы сможете получить доступ к ServletContext в статическом виде:

class MyListener implements ServletContextListener { 

    public static ServletContext context; 

    @Override 
    public void contextInitialized(ServletContextEvent sce) { 
     context = sce.getServletContext(); 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent sce) { 
     context = null; 
    } 

} 

Добавить его в web-xml так:

<web-app> 
    <listener> 
     <listener-class> 
      com.something.MyListener 
     </listener-class> 
    </listener> 
</web-app> 

И вы можете получить к нему доступ из любой точки мира, как это:

public String getSomething() { 
    // Here you have the context: 
    ServletContext c = MyListener.context; 
} 

Примечание:

Возможно, вы захотите сохранить его как private и предоставить метод getter, а также проверить значение null перед его использованием.

1

Вы можете autowire контекст сервлета, как указано ниже

@Autowired 
ServletContext servletContext; 
2

Если у вас нет указателя на что-то полезное, единственный способ, которым я знаю, будет иметь статический атрибут в классе, который содержит текущий ServletContext. Это тривиально с ServletContextListener:

@WebListener 
public class ServletContextHolder implements ServletContextListener { 
    private static ServletContext servletContext; 

    public static ServletContext getServletContext() { 
     return servletContext; 
    } 

    @Override 
    public void contextInitialized(ServletContextEvent sce) { 
     servletContext = sce.getServletContext(); 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent sce) { 
     servletContext = null; 
    }  
} 

Тогда из любой точки мира вы используете

ServletContextHolder.getServletContext(); 

Если вы используете Spring, вы можете также использовать RequestContextHolder, чтобы получить доступ к текущему запросу (оттуда все, что вы потребность)

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder 
           .getRequestAttributes()).getRequest(); 

конечно, если работает таким образом в применении сервлета, а не в портлетных те - вам придется использовать PortletRequestAttributes и, наконец получить порт letRequest