Получение двух сервлетов для использования одного и того же объекта с использованием контекста сервлета - PullRequest
1 голос
/ 25 февраля 2012

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

Сервлет 1

public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException{
        PrintWriter out = response.getWriter();

        HashMap<String ,String> hm = new HashMap<String, String>();
        hm.put("1", "1");

        this.getServletContext().setAttribute("usermanager", hm);
        this.getServletConfig().getServletContext().setAttribute("usermanager2", hm);   
    }

Сервлет 2

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException{

    HashMap newMap2 = (HashMap) this.getServletConfig().getServletContext().getAttribute("usermanager"); 
    HashMap newMap3 = (HashMap) this.getServletContext().getAttribute("usermanager2"); 

    System.out.println("newmap2 size " + newMap2.size());
    System.out.println("newmap3 size " + newMap3.size());   
}

Чтобы проверить это, я перезапустил Tomcat 6, затем сначала запустил сервлет доступа 1, чтобы он инициализировал объект Hashmap. Когда я впоследствии получаю доступ к сервлету 2, я получаю ошибку NULL-POINTER, которая указывает на номер строки, где я пытался вызвать newMap2.size ()

Что я делаю не так?

java.lang.NullPointerException
    at com.TestServlet.doGet(TestServlet.java:24)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:291)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:619)

Ответы [ 2 ]

7 голосов
/ 26 февраля 2012

Как уже упоминал @Peter Cetinski, контекст сервлета всегда относится только к одному веб-приложению (WAR-файл).Тем не менее, Servlet API предоставляет способ доступа к «чужим» контекстам сервлетов, вызывая javax.servlet.ServletContext.getContext(uriPath).

Так что если вы действительно хотите / хотите распределить свои сервлеты по разным WAR и взаимодействию междуони необходимы, вы можете сделать это.

Предполагая, что Сервлет 1 находится в веб-приложении warA , Сервлет 2 находится в веб-приложении warB , а путь к контексту приложения совпадает с именем веб-приложения (например, http://myserver/warA и http://myserver/warB), код для сервлета 2 может выглядеть следующим образом:

/* retrieve foreign context */
ServletContext ctxWarA = this.getServletContext().getContext("warA");

/* ... and work with it */
Map<String, String> map = (Map<String, String>) ctxWarA.getAttribute("usermanager");

Существуют некоторые ограничения:

  • Вы должны явно разрешить warB доступ к внешнему контексту, указав это в приложениях context.xml: <Context crossContext="true"/>

  • эта установка является проприетарной (я не могу рассказать вам, как это работает на других серверах приложений / сервлетах)

  • если вы хотите поделиться пользовательскими классами, они должныбыть разделенным между приложениями (plВ стандартных настройках <tomcat>/lib

  • вы работаете с различными загрузчиками классов для warA и warB, вы должны знать, что

  • Tomcat не гарантирует определенную последовательность запуска (нет способа настроить это).В вашем случае warB должен быть в состоянии справиться с этим и ожидать, что warA еще не запущен

Если вам нужно обмениваться объектами / информацией между веб-приложениями, я бы подумалэти альтернативные подходы:

  • общий синглтон, расположенный в Tomcat / lib (я знаю синглтон, но он работает)

  • объект, расположенный вдерево JNDI ( документация Tomcat )

  • информация, необходимая для построения кэша в общем хранилище данных (файл, база данных и т. д.), и каждое приложение загружает данныепри запуске

1 голос
/ 25 февраля 2012

ServletContext доступен только в веб-приложении. Если вы развертываете в двух разных WAR, то у вас есть 2 веб-приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...