Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Запустить сервлет


Автор: DEER 15.12.2006, 14:49
Привет всем!
Можно ли сделать такой сервлет, метод init которго быдет вызываться при начале работы приложения?
Наподобии ActionServlet из struts, просто ActionServlet мне не подходит, так как он уже есть, и делает много разных дел, и запихивать туда ещё одну большую функциональность не хочется...

Автор: tux 15.12.2006, 14:56
Можно сделать Listener.
web.xml:
Код

<web-app>
  <listener>
    <listener-class>SomeContextListener</listener-class>
  </listener>
</web-app>

SomeContextListener.java:
Код

public class SomeContextListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent event) {
               // do something
    }

    public void contextDestroyed(ServletContextEvent event) {
               // do something
    }

}

Будет запускаться при инициализации приложения.

Автор: DEER 15.12.2006, 15:00
и "жить" всё время пока приложение не выключат?
мне там поток надо запустить

Автор: tux 15.12.2006, 15:09
Цитата(DEER @  15.12.2006,  15:00 Найти цитируемый пост)
и "жить" всё время пока приложение не выключат?
мне там поток надо запустить 

Вроде как. А зачем тебе для потока его постоянное существование?

Автор: DEER 15.12.2006, 15:12
чтобы потом его корректно завершить.
закрыть все конекшены и сказать "пока"  smile 
спасибо tux 

Автор: DEER 15.12.2006, 18:15
попробовал создать простой listener,
запускаю debug чтобы осмотреть как он отработает, и что же я вижу? Он туда заходит ДВА раза!! Первый раз при начале загрузки tomkat'а, а второй раз уже непосредственно когда приложение стартовало.

Скажите, так и должно быть?

Я использовать в сервлет и написать в его описании load-on-startup не решит мою проблему?

Автор: 3x3 15.12.2006, 19:55
Цитата(DEER @ 15.12.2006,  18:15)
попробовал создать простой listener,
запускаю debug чтобы осмотреть как он отработает, и что же я вижу? Он туда заходит ДВА раза!! Первый раз при начале загрузки tomkat'а, а второй раз уже непосредственно когда приложение стартовало.

Скажите, так и должно быть?

Я использовать в сервлет и написать в его описании load-on-startup не решит мою проблему?

Кстати, вы уверены, что два раза он заходит по разным событиям? 
У меня было ощущение/подозрение (на почве эксперимента с одновременной загрузкой 9ти идентичных страничек во фреймсет), что томкат по дефолту стартует два (или три) процесса для обслуживания HTTP-запросов и озадачивает их по очереди.  Не может так быть что листенер инитится для каждого из них персонально?

Автор: y3u 15.12.2006, 20:12
ну есть еще старый добрый вариант, которым мало кто теперь пользуется - это сделать сервелет, сделать ему <load-on-startup>1</load-on-startup> но не мепить его ни на како контекст... можно в нем тогда перекрыть init() и destoy()... уж сервлет то должен заинициалайзиться точно только один раз...

Автор: Stampede 15.12.2006, 21:02
Все-таки иделогически более правильно делать такие вещи через ServletContextListener. То, что он два раза вызывается - это какой-то глюк. Надо просто его отловить и потом спокойно пользоваться.

Как отловить глюк? Ну давай для начала посмотрим, что говорит стек вызовов. Если есть отладчик (какая IDE?), то делается вообще на раз, через брейкпойнт. Если отладчика нету, то можно сделать так:

Код

public void contextInitialized(ServletContextEvent event) {
    Exception e = new Exception();
    e.fillInStackTrace();
    e.printStackTrace(); // если есть какой-нить логгер, лучше вывести в логгер, типа: logger.error(e);
}


И сразу все станет ясно. Должно, по крайней мере. Если что - кидай вывод в форум, попробуем разобраться.

Автор: Greg 15.12.2006, 23:11
Цитата(DEER @ 15.12.2006,  14:49)
Привет всем!
Можно ли сделать такой сервлет, метод init которго быдет вызываться при начале работы приложения?
Наподобии ActionServlet из struts, просто ActionServlet мне не подходит, так как он уже есть, и делает много разных дел, и запихивать туда ещё одну большую функциональность не хочется...

Тебе нужен сервлет который вызывается только в самом начале ?
Смущает сравнение с ActionServlet который отрабатывает на каждом запросе к контейнеру.

Автор: 3x3 17.12.2006, 04:32
Попробовал поэкспериментировать с Томкатом (v.5.5.17) на ту тему, о которой писал выше, но использовал JSP. Похоже он действительно дважды создаёт сервлет.

Непосредственно после запуска сервера (или первого обращения к JSP-странице) пользовательские запросы какое-то время выполняет один экземпляр класса, а потом (через секунду-две) в работу включается другой, и остаётся уже навсегда.

Вот вырожденный случай - первый файл это просто фреймсет 3х3 одинаковых фреймов, содержимое которых генерится jsp-шкой, код которой занимается лишь деланием toString() объекта и представлен во втором файле:

test4.html
Код

<HTML>
<HEAD>
<TITLE>Great Recipes</TITLE>
</HEAD>

<FRAMESET ROWS="33%,33%,*">
     <FRAMESET COLS="33%,33%,*">
          <FRAME SRC="test4.jsp">
          <FRAME SRC="test4.jsp">
          <FRAME SRC="test4.jsp">
     </FRAMESET>
     <FRAMESET COLS="33%,33%,*">
          <FRAME SRC="test4.jsp">
          <FRAME SRC="test4.jsp">
          <FRAME SRC="test4.jsp">
     </FRAMESET>
     <FRAMESET COLS="33%,33%,*">
          <FRAME SRC="test4.jsp">
          <FRAME SRC="test4.jsp">
          <FRAME SRC="test4.jsp">
     </FRAMESET>
</FRAMESET>
</HTML>


test4.jsp
Код

<HTML>
<body>
<%
    out.write("this: "+this.toString() +"<br/>");  
    Thread.sleep(500);
%>
</body></HTML>



Так вот что выводится во фреймах (первая цифра - номер фрейма):
1. this: org.apache.jsp.test4_jsp@1493995
2. this: org.apache.jsp.test4_jsp@1493995
3. this: org.apache.jsp.test4_jsp@1493995
4. this: org.apache.jsp.test4_jsp@1493995
5. this: org.apache.jsp.test4_jsp@1493995
6. this: org.apache.jsp.test4_jsp@2c39d2
7. this: org.apache.jsp.test4_jsp@2c39d2
8. this: org.apache.jsp.test4_jsp@2c39d2
9. this: org.apache.jsp.test4_jsp@2c39d2

Если заглушить спячку в JSP-файле, то во все фреймы выводится одинаковый ID объекта, но при самой первой загрузке он один, а при последующих - другой, и при том уже, похоже, больше уже не меняется.


Интересно, что это за первый инстанс, который сначала отрабатывает запросы и потом заменяется другим экземпляром того же объекта и нафига он нужен? 






Автор: tux 17.12.2006, 13:04
Цитата(DEER @  15.12.2006,  18:15 Найти цитируемый пост)
запускаю debug чтобы осмотреть как он отработает, и что же я вижу? Он туда заходит ДВА раза!!

У меня есть версия почему так может происходить. Если war описан с помощью тэга <Context> в server.xml и при этом лежит в каталоге ${CATALINA_HOME}/webapps, для которого включен autoDeploy, то Tomcat инициализирует приложение дважды, как следствие ServletContextListener вызывается два раза.

Насчет JSP действительно интересно. У меня получилось тоже самое. Потом покопался в документации и вот чего обнаружил. В Tomcat 5.5 используется Jasper 2 и одно из его свойств:
Цитата

Background JSP compilation - If you make a change to a JSP page which had already been compiled Jasper 2 can recompile that page in the background. The previously compiled JSP page will still be available to serve requests. Once the new page has been compiled successfully it will replace the old page. This helps improve availablity of your JSP pages on a production server.

То есть JSP может компилироваться (судя по всему делается это когда JSP изменился и при старте приложения) в фоновом режиме и какое-то время пока выполняется компиляция будет использоваться старый экземпляр. А вот когда приложение запустилось первый раз, Tomcat зачем-то первый раз компилит JSP в связи с тем, что он вообще еще не компилировался, а затем второй раз в связи с тем, что приложение запустилось. Зачем не понятно. Видимо Jasper 2 все еще недостаточно интеллектуален. smile

Автор: 3x3 17.12.2006, 15:07
Цитата(tux @ 17.12.2006,  13:04)
То есть JSP может компилироваться (судя по всему делается это когда JSP изменился и при старте приложения) в фоновом режиме и какое-то время пока выполняется компиляция будет использоваться старый экземпляр. А вот когда приложение запустилось первый раз, Tomcat зачем-то первый раз компилит JSP в связи с тем, что он вообще еще не компилировался, а затем второй раз в связи с тем, что приложение запустилось. Зачем не понятно. Видимо Jasper 2 все еще недостаточно интеллектуален. smile

Да, точно, к сервлету это не относится.


Автор: DEER 18.12.2006, 10:40
ДаДаДа

короче запускается ВСЁ по два раза, но не из за того что это Листенер-ы, потому что и сервлеты, у который прописано <load-on-startup>1</load-on-startup> тоже по два раза отрабатывают

это потому что,
Цитата

У меня есть версия почему так может происходить. Если war описан с помощью тэга <Context> в server.xml и при этом лежит в каталоге ${CATALINA_HOME}/webapps, для которого включен autoDeploy, то Tomcat инициализирует приложение дважды, как следствие ServletContextListener вызывается два раза.

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

На других рабочих станциях всё нормально работает!
Всем спасибо!!!

Добавлено @ 10:48 
Stampede, вот чо пишется в консоли при запуске
Цитата

cmd /c "C:\Tomcat 5.5\bin\catalina.bat" run
c:\Program Files\Java\jre1.5.0_09
gotJdkHome1
gotJdkHome2
gotJdkHome3
gotJdkHome4
Using CATALINA_BASE:   C:\Documents and Settings\OlegM\.IntelliJIdea50\system\tomcat_Unnamed_cc026170
Using CATALINA_HOME:   C:\Tomcat 5.5
Using CATALINA_TMPDIR: C:\Tomcat 5.5\temp
Using JRE_HOME:        c:\Program Files\Java\jre1.5.0_09
Connected to the target VM, address: '127.0.0.1:1256', transport: 'socket'
18.12.2006 10:36:01 org.apache.catalina.core.AprLifecycleListener lifecycleEvent
INFO: The Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: c:\Program Files\Java\jre1.5.0_09\bin;.;C:\WINDOWS\system32;C:\WINDOWS;C:\Perl\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;c:\Java\ant\bin\;C:\Program Files\Subversion\bin;c:\Java\libs\;c:\Java\lib\;C:\Program Files\Apache Software Foundation\Maven 1.0.2\bin
18.12.2006 10:36:01 org.apache.coyote.http11.Http11BaseProtocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
18.12.2006 10:36:01 org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 1141 ms
18.12.2006 10:36:01 org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
18.12.2006 10:36:01 org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/5.5.17
18.12.2006 10:36:01 org.apache.catalina.core.StandardHost start
INFO: XML validation disabled
AbandonedObjectPool is used (org.apache.tomcat.dbcp.dbcp.AbandonedObjectPool@15e3dc4)
   LogAbandoned: true
   RemoveAbandoned: true
   RemoveAbandonedTimeout: 60
18.12.2006 10:37:55 org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(C:\Tomcat 5.5\webapps\sale\WEB-INF\lib\servlet-api.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester.sax).
log4j:WARN Please initialize the log4j system properly.
AbandonedObjectPool is used (org.apache.tomcat.dbcp.dbcp.AbandonedObjectPool@627b5c)
   LogAbandoned: true
   RemoveAbandoned: true
   RemoveAbandonedTimeout: 60
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:22 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Class-Path
18.12.2006 10:38:23 org.apache.coyote.http11.Http11BaseProtocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
18.12.2006 10:38:24 org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
18.12.2006 10:38:24 org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/47  config=null
18.12.2006 10:38:24 org.apache.catalina.storeconfig.StoreLoader load
INFO: Find registry server-registry.xml at classpath resource
Connected to server
18.12.2006 10:38:24 org.apache.catalina.startup.Catalina start
INFO: Server startup in 142803 ms


некоторые строки помечены Duplicate

Автор: Катена 8.1.2007, 04:06
Помогите пожалуйста!!!!!!!
.java  не компилируется в .class
Установила j2se, j2ee, прописала все переменные окружения ошибку выдает на import javax.servlet.*; и import javax.servlet.http.*;

Автор: 3x3 8.1.2007, 04:46
Цитата(Катена @ 8.1.2007,  04:06)
Помогите пожалуйста!!!!!!!
.java  не компилируется в .class
Установила j2se, j2ee, прописала все переменные окружения ошибку выдает на import javax.servlet.*; и import javax.servlet.http.*;

Оно ещё должно знать где сидит jar-файл с этими классами. Например у меня под томкатом эти классы сидят в T:/Tomcat.5.5.17/common/lib/servlet-api.jar и если я хочу что-нибудь скомпилировать с их участием, могу вставить эту строчку в CLASSPATH (целиком, вместе с именем класса) или иначе указать компилятору где брать этот архив. При запуске из-под томката, контейнер уже сам позаботится что бы АПИ был доступен.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)