Метод init()
И еще пара полезных мелочей. Конечно, я про инициализацию сервлета. Как ты уже знаешь, после того, как веб-сервер создал объект сервлета и поместил его в контейнер, он вызывает у сервлета метод init(). Ты можешь переопределить этот метод и инициализировать в нем все, что тебе нужно.
А почему бы не использовать конструктор?
Потому что процесс создания сервлета происходит примерно так:
- Создаем объект, унаследованный от HttpServlet
- Создаем объект ServletContext, добавляем его переменную сервлета
- Создаем объект ServletConfig, добавляем его переменную сервлета
- …
- Веб-сервер присоединяет сервлет к контейнеру
- Вызываем метод init()
В конструкторе твоего сервлета еще очень много его внутренних переменных не инициализировано. Контейнер ничего не знает о твоем сервлете, твой сервлет ничего не знает о его контексте. Думаю, тут и так все понятно.
Давай напишем сервлет, который при инициализации находит properties-файл с настройками:
public class PropertiesServlet extends HttpServlet {
public init() {
try (InputStream input = new FileInputStream("c:/path/to/config.properties")) {
Properties prop = new Properties();
prop.load(input);
String databaseURL = prop.getProperty("db.url");
String databaseUser = prop.getProperty("db.user ");
String databasePassword = prop.getProperty("db.password");
}
}
}
Тут мы создаем объект Properties и загружаем в него данные из файла config.properties. Ну и в дальнейшем можно доставать из объекта Properties различные параметры, такие как данные для доступа к базе данных, например.
Как правильно загрузить properties-файл
Кстати, а что делать, если твой сервлет выполняется не на твоем компьютере?
Скажем, написали его тут, а он выполняется на сервере где-то в другой части света. Или на нескольких серверах. Как правильно загрузить properties-файл в этом случае?
Хороший вопрос. Обычно в процессе работы сервлет знает только относительный путь своих properties-файлов, но не знает их абсолютного пути, так как war-файлы с сервлетами могут храниться где угодно.
Значит, нам нужно узнать путь, где храниться наш сервлет (сервлет-то уже проинициализирован) и добавить к нему относительный путь :)
Выглядит это примерно так:
String path = absoluteServletParh + "относительный путь";
И, как всегда, у такой элементарной задачи часто есть свое маленькое “но”. Твой сервлет и его properties-файл хранятся внутри архива :) Не обязательно, конечно, но и такое бывает. properties-файл частенько хранится внутри jar- или war-файлов.
То есть физического пути на диске у твоего файла может не быть. Но так как контейнер сумел загрузить твой сервлет, он скорее всего сможет загрузить и твой properties-файл.
Для этого тебе нужно получить объект загрузчика класса (ClassLoader) и попросить его загрузить твой файл. Вот как это будет выглядеть:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream stream = loader.getResourceAsStream("/config.properties");
Properties prop = new Properties();
prop.load(stream);
Метод getConfig()
Кстати, не все параметры можно передавать в сервлет в properties-файлах. Например, твой сервлет взаимодействует с другими сервлетами в распределенном веб-приложении.
Тогда нужно сделать так, чтобы контейнер передал твоему сервлету всю необходимую информацию, когда он будет вызвать его метод init(). Более того, он так и делает.
У твоего сервлета (ты ведь помнишь, что он унаследован от класса HttpServlet) есть метод getServletConfig(). Который возвращает объект ServletConfig, созданный и инициализированный контейнером. У этого объекта есть такие методы:
getInitParameterNames() | Возвращает список имен параметров сервлета |
getInitParameter(String name) | Возвращает параметр сервлета по его имени |
getServletName() | Возвращает собственное имя сервлета |
getServletContext() | Возвращает объект ServletContext |
Давай напишем сервлет, который возвращает список своих параметров из ServletConfig’а. Класть их туда будет через файл web.xml:
<web-app>
<servlet>
<servlet-name>Print-Servlet</servlet-name>
<servlet-class>PrintServlet</servlet-class>
<init-param>
<param-name>jdbc-driver</param-name>
<param-value>sun.jdbc.odbc.JdbcOdbcDriver</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Print-Servlet</servlet-name>
<url-pattern>/print</url-pattern>
</servlet-mapping>
</web-app>
Получить свои параметры сервлет может с помощью кода:
public class PrintServlet extends HttpServlet {
public void init() {
ServletConfig config = this.getServletConfig();
Enumeration<String> initParameterNames = config.getInitParameterNames();
while (initParameterNames.hasMoreElements()){
String key = initParameterNames.nextElement();
System.out.println("%s: %s\n", key, config.getInitParameter(key));
}
}
}
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ