Java сервлеты. Установка и настройка tomcat под WinXP

Наконец я дошел до изучения темы сервлетов на Java, которые, кстати, меня очень порадовали, ибо php и perl изучать времени катастрофически не хватает, а тут и особо переучиваться не надо.

Из учебника вычитал что для сервлетов используется tomcat. ОК. Скачать последнюю версию,
Следующий шаг, для tomcat нужна Java Runtime Environment, которая у меня разумеется уже есть (да и на вряд ли у кого то могут возникнуть проблемы при ее установке).

На этом все, дальше установка, которая не потребовала никаких усилийПервый шаг установки tomcat
Далее принимаем соглашение
Второй шаг установки tomcat. Принимаем соглашениеДалее выбираем тип установки (у себя я выбрал full т.е. со всеми примерами)
Выбираем тип установкиДалее выбираем порты для подключения к серверу. Если порты не зяняты другими приложениями, то можно оставить по умолчанию. Так же в этом окне следует указать логин и пароль для подключения к web-панели. (пароль забыть не страшно, ибо он хранится в открытом виде в конфигурационном файле. Но об этом позже)
Устанавливаем параметры подключенияНа следующем шаге указываем папку куда установлена виртуальная машина Java.
Указываем путь к JVMНу и выберем каталог самого tomcat’а. Я его изменил на свой
Установка домашнего каталога TomcatЖмем Install, и ждем пока закончится копирование файлов.

Теперь можно немного его по конфигурировать.  Начну с переменных окружения операционной системы Tomcat использует CATALINA_HOME для поиска папки, в которую он установлен и CATALINA_BASE для поиска папки где лежат web проекты. Первый должен быть задан обязательно. Если второй не указан, то берется домашняя папка Tomcat.  Так же в переменной JAVA_HOME указан путь к JRE
Главные переменные среды окружения (ОС)

Что касается сброса/восстановления пароля Tomcat, конфигурационный файл пользователей лежит в папке CATALINA_HOME/conf/tomcat-users.xml (в моем случае: C:/WebServer/conf/tomcat-users.xml).
Пожалуй на этом настройка закончена. Конечно, там есть еще куча всяких настроек, но для обучения думаю что этот вариант более чем подойдет.

Что касается проектов. В домашней папке проекта есть папка webaps, которая и служит контейнером для всех web приложений. Для каждого проекта может быть использованы файлы html, jsp, ну и class файлы. Причем class файлы должны располагаться в подпапке WEB-INF/classes, а папка WEB-INF так же должна содержать файл web.xml который описывает все классы. После создания проекта он цепляется автоматически, и например создав папку myprj в каталоге webapps мы можем полюбоваться на пустую страничку по адресу http://localhost:8080/myprj/ а кинув туда заполненный файл index.html мы соответственно увидим результат.

Пожалуй на этом все! Пошел дальше практиковаться в web мастерстве на Java. Для начала попытаюсь скомпилировать hello world голыми руками, ну а дальше можно будет и IDE какую нибудь попытаться использовать. (и скорее всего это будет Eclipse)

P.S.
Если у Вам удалось, так же как и мне :), установить Tomcat, да и еще и в full комплекте, то после запуска оного смотрите вот сюда: http://localhost:8080/docs/appdev/index.html

Неограниченный хостинг

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

  1. Завести аккаунт на любом провайдере DDNS и придумать ЛЮБОЕ имя
  2. Настроить роутер на перенаправление всех входящих подключений в локальную сеть, на конкретный компьютер
  3. Поднять web сервер на машине, куда роутером направляются входящие данные
  4. Добавить в зону оплаченного домена с УДОБНЫМ именем третьего уровня запись CNAME с указанием на домен, созданном на первом шаге.

В принципе, этого достаточно. Что из этого всего получилось у меня вы можете посмотреть по ссылке. Разумеется, что web сервер настроен не идеально. Я бы даже сказал, что настройки произведены минимальные. Нет поддержки никаких скриптов и баз данных, но это тоже дело техники, и все зависит от прямоты рук (признаться, при подключении php у меня apache люто матюкался, но я не теряю надежды 🙂

Заметка. Добавление обработчика к элементам формы

В программно добавляемые реквизиты можно добавить обработчики событий. Это делается для элементов формы. Используется метод УстановитьДействие в параметры которого передается имя события и действие. Например для колонки таб. части:

Процедура ПриОткрытии()
	УстановитьОбработчики();
КонецПроцедуры
Процедура СтатьяДвиженияДенежныхСредствНачалоВыбора(Элемент, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;
	Запрос = Новый Запрос;
//--------------------------
	МассивСтатей = Новый СписокЗначений;
	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		МассивСтатей.Добавить(Выборка.СтатьяДвиженияДенежныхСредств);
	КонецЦикла;

	ФормаВыбора = Справочники.СтатьиДвиженияДенежныхСредств.ПолучитьФормуВыбора("ФормаВыбора",Элемент);
	
	ФормаВыбора.СправочникСписок.Отбор.Ссылка.ВидСравнения = ВидСравнения.ВСписке;
	ФормаВыбора.СправочникСписок.Отбор.Ссылка.Использование = Истина;
	ФормаВыбора.СправочникСписок.Отбор.Ссылка.Значение = МассивСтатей;
	
	ФормаВыбора.ЭлементыФормы.СправочникСписок.НастройкаОтбора.Ссылка.Доступность = Ложь;
	ФормаВыбора.ТолькоПросмотр = Истина;
	ФормаВыбора.ПараметрТекущаяСтрока = Элемент.Значение;

	ФормаВыбора.Открыть();
КонецПроцедуры

Процедура УстановитьОбработчики()
	Действие = Новый Действие("СтатьяДвиженияДенежныхСредствНачалоВыбора");
	МассивРеквизитов = Новый Массив();
	МассивРеквизитов.Добавить("СтатьяДвиженияДенежныхСредств");
	МассивРеквизитов.Добавить("СтатьяДвиженияДенежныхСредствПрочее");
	МассивРеквизитов.Добавить("СтатьяДвиженияДенежныхСредствВыплатаЗП");
	МассивРеквизитов.Добавить("СтатьяДвиженияДенежныхСредствБанк");
	МассивРеквизитов.Добавить("СтатьяДвиженияДенежныхСредствБанк1");
	МассивРеквизитов.Добавить("СтатьяДвиженияДенежныхСредствИнк");
	МассивРеквизитов.Добавить("СтатьяДвиженияДенежныхСредствИсполнительныеЛисты");
	МассивРеквизитов.Добавить("СтатьяДвиженияДенежныхСредствВыплатаЗарплатыРаботнику");

	ЭлементыФормы.ВыдачаВПодотчет.Колонки["СтатьяДвиженияДенежныхСредств"].ЭлементУправления.УстановитьДействие("НачалоВыбора",Действие);
	ЭлементыФормы.РасшифровкаПлатежа.Колонки["СтатьяДвиженияДенежныхСредств"].ЭлементУправления.УстановитьДействие("НачалоВыбора",Действие);

	Для Каждого ИмяПоля ИЗ МассивРеквизитов Цикл
		ЭлементыФормы[ИмяПоля].УстановитьДействие("НачалоВыбора",Действие); 
	КонецЦикла;
КонецПроцедуры

Java. Подключение к БД. Использование в eclipse внешних jar файлов

Имеется следующий код

package kz.ranter.ytzh;
import java.sql.*;
public class DBConnectTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
Connection mdbh = DriverManager.getConnection("jdbc:postgresql://127.0.0.1/tests","postgres","1");
Statement st = mdbh.createStatement();
ResultSet rs = st.executeQuery("SELECT tablename FROM pg_tables;");
while(rs.next())
System.out.println(rs.getString(1));
rs.close();
st.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Colored with dumpz.org

При его компиляции в эклипсе «как есть» система выдает ошибку

java.sql.SQLException: No suitable driver found for jdbc:postgresql://127.0.0.1/tests
        at java.sql.DriverManager.getConnection(Unknown Source)
        at java.sql.DriverManager.getConnection(Unknown Source)
        at kz.ranter.ytzh.DBConnectTest.main(DBConnectTest.java:12)

Это происходит потому что Java не видит jar файл для подключения к БД (JDBC драйвер)
После сборки .class файл можно запустить из командной строки с указанием пути к соответствующему .class файлу

java -cp C:\Develop\JAVA\DBTests\bin;"C:\Program Files\PostgreSQL\pgJDBC\postgresql-9.1-901.jdbc4.jar" kz.ranter.ytzh.DBConnectTest

В параметре -cp указан путь к «корневой» папке для приложения а так же путь к .jar файлу с драйвером для БД

В эклипсе все делается гараздо проще:
В ProjectExplorer -> Выбрать нужный проект, -> alt+enter -> Run/Debug Settings-> выбрать конфигурацию -> Edit… -> Закладка classpath -> Add External JARs… -> Выбрать нужный jar файл
После этого выполнение идет без проблем

Java. Преобразование InputStream в различные кодировки

Пытался прочитать данные из потока, однако кириллические символы никак ни хотел корректно отображаться. Оказалось, что InputStreamReader работает только с типом byte, и для поддержки кодировок используются классы Reader’ы в конструкторе которых можно указать кодировку

package ShildtSpr.Chapter20;
import java.net.*;
import java.io.*;
import java.util.*;
public class HttpURLDemo {
public static void p(){
p("");
}
public static void p(Object s){
System.out.println(s);
}
/**
* @param args
* @throws MalformedURLException
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
URL hp = new URL("http://ranter.kz");
HttpURLConnection hpCon = (HttpURLConnection)hp.openConnection();
p("Метод запроса: "+hpCon.getRequestMethod());
p("Код ответа: "+hpCon.getResponseCode());
p("Сообщение ответа: "+hpCon.getResponseMessage());
Map<String, List<String>> hdrMap = hpCon.getHeaderFields();
Set<String> hdrFields = hdrMap.keySet();
p("\nЗдесь следует заголовок");
for(String k:hdrFields)
p(""+k+": "+hdrMap.get(k));
//Создаем класс BufferedReader из InputStreamReader для которого указываем кодировку
BufferedReader f = new BufferedReader(new InputStreamReader(hpCon.getInputStream(), "UTF-8"));
String line;
while((line=f.readLine())!=null){
System.out.println(line);
}
f.close();
}
}

Colored with dumpz.org

Java. Параметры по умолчанию

Оказалось, что в Java нет параметров по умолчанию, и для этого нужно использовать перегрузку. Таким образом получается следующее:

public static void pl(){
pl(«»);
}
public static void pl(String s){
System.out.println(s);
}

Colored with dumpz.org

Ну и соответственно, если параметров много, и для них можно установить значение по умолчанию, то нужно так же путем перегрузок предусмотреть ВСЕ возможные варианты 🙂
Например:

/**
* Вывод несколько раз одной строки
* @param s Выводимая строка
* @param count Количество выводов
*/
public static void pl(String s, int count){
for(int i=0;i<count;i++)
System.out.println(s);
}
/**
* Вывод пустой строки (перевод на новую строку)
*/
public static void pl(){
pl(«»,1);
}
/**
* Вывод одной строки на печать
* @param s Выводимая строка
*/
public static void pl(String s){
pl(s,1);
}
/**
* Пропуск нескольких строк
* @param count Количество переходов
*/
public static void pl(int count){
pl(«»,count);
}

Colored with dumpz.org

Вот такие вот выкрутасы вместо

public static void pl(String s="", int count=1)

Открытие управляемой формы объекта. Эмуляция события «Обработка интерактивной активации»

При работе в управляемом интерфейсе в карте маршрута не срабатывает обработчик события «ОбработкаИнтерактивнойАктивации», которая в обычном, не управляемом режиме может быть использована для открытия форм документов и справочников привязанных к задаче. Я эту проблему решил следующим способом:

  1. Для задач создал форму списка
  2. Для списка подписался на событие «ПередНачаломИзменения»
  3. Реализовал следующий модуль для формы
&НаКлиенте
Процедура СписокПередНачаломИзменения(Элемент, Отказ)
	Структура = Новый Структура("БизнесПроцесс",Элемент.ТекущиеДанные.БизнесПроцесс);
	СтруктураПараметров = Вспомогательная(Структура);
	СтруктураПараметров.Вставить("ТочкаМаршрута",Элемент.ТекущиеДанные.ТочкаМаршрута);
	Форма = ПолучитьФорму("Документ.ОформлениеЗаявкиНаСотрудника.ФормаОбъекта",СтруктураПараметров,ЭтаФорма, Истина);
	Форма.Открыть();
	Отказ = Истина;
КонецПроцедуры

&НаСервере
Функция Вспомогательная(Структура)
	Заявка = Структура.БизнесПроцесс.Заявка;
	Адрес = ПоместитьВоВременноеХранилище(Заявка, Новый УникальныйИдентификатор);

	Возврат Новый Структура("Адрес, Ключ",Адрес,Заявка);

КонецФункции

Для метода «Получит форму» вторым параметром передается структура. Если в нее установить поле «Ключ» которое является ссылкой на объект открытия, то он откроется. Если же нужно создать новый объект, то поле «Ключ» не передается

Далее в модуле документа можно реализовать поведение документа.

Источники: http://devtrainingforum.v8.1c.ru/forum/thread.jsp?id=568630
http://www.forum.mista.ru/topic.php?id=619704

Открытие формы записи регистра сведений

На сайте мисты (http://www.forum.mista.ru/topic.php?id=415772) имеется меседж в котором описывается каким образом можно открыть запись регистра сведений. Приведу его:

Ключ = Новый Структура();
Ключ.Вставить("ТипАвтомобиля", ВыбраннаяСтрока.ТипАвтомобиля);
Ключ.Вставить("Водитель",?(ВыбраннаяСтрока.Водитель = "Водитель", Истина, Ложь));

м = РегистрыСведений.КоэффициентыЗаработка.Получить(ВыбраннаяСтрока.Период, Ключ);
ФормаЗаписи=РегистрыСведений.КоэффициентыЗаработка.ПолучитьФормуРедактированияЗаписи("ФормаЗаписи");
ФормаЗаписи.Период = ВыбраннаяСтрока.Период;
ЗаполнитьЗначенияСвойств(ФормаЗаписи,Ключ);
ЗаполнитьЗначенияСвойств(ФормаЗаписи,м);
ФормаЗаписи.ОткрытьМодально();

Автоматический подбор по строке

В стандартные элементы формы, содержащие ссылки на объект могут быть подставлены данные подобранные по первым символам наименования или кода для справочников или же по номеру для документов. В качестве расширения указанное поле можно использовать для поиска по любому строковому содержанию в любом реквизите искомого объекта. Для этого необходимо подписаться на событие элемента формы «Окончание ввода текста» внутри обработчика которого установить передаваемому параметру «Значение» либо ссылку на соответствующий объект, либо внести в него список этих объектов. Во втором случае система предложит выбрать один вариант из заполненного списка. Если же в списке только один элемент, то система просто подставит его в указанный элемент формы.
В примере ниже я реализовал подбор контрагента. Поиск осуществляется по строке в любой части наименования. Кроме того, в случае, если контрагент не найден, то будет выдан запрос на его создание, и открыто модальное окно для заполнения реквизитов. В случае если элемент записан, он будет подставлен в элемент формы.

Процедура КонтрагентОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
	Значение = Новый СписокЗначений;
	СтандартнаяОбработка = Ложь;
	ТекстЗапроса = "ВЫБРАТЬ
	               |	Контрагенты.Ссылка,
	               |	Контрагенты.Наименование,
	               |	Контрагенты.РНН
	               |ИЗ
	               |	Справочник.Контрагенты КАК Контрагенты
	               |ГДЕ
	               |	Контрагенты.ЭтоГруппа = ЛОЖЬ";
	ПостроительЗапроса = Новый ПостроительЗапроса;
	ПостроительЗапроса.Текст = ТекстЗапроса;
	ПостроительЗапроса.ЗаполнитьНастройки();
	ЭлементОтбора = ПостроительЗапроса.Отбор.Добавить("Наименование");
	ЭлементОтбора.ВидСравнения = ВидСравнения.Содержит;
	ЭлементОтбора.Использование = Истина;
	ЭлементОтбора.Значение = Текст;
	ПостроительЗапроса.Выполнить();

	Выборка = ПостроительЗапроса.Результат.Выбрать();
	Пока Выборка.Следующий() Цикл
		Значение.Добавить(Выборка.Ссылка,Выборка.Наименование+?(СокрЛП(Выборка.РНН)="",""," ("+Выборка.РНН+")"));
		Если Значение.Количество() >= 50 Тогда
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Если Значение.Количество() = 0 Тогда
		Ответ = Вопрос("Контрагент с наименованием "+Текст+" не найден. 
		|Создать?",РежимДиалогаВопрос.ДаНет);
		Если Ответ = КодВозвратаДиалога.Да Тогда
			Элемент = Справочники.Контрагенты.СоздатьЭлемент();
			Элемент.Наименование = Текст;
			Форма = Элемент.ПолучитьФорму("ФормаЭлемента");
			Форма.ОткрытьМодально();
			Если НЕ Элемент.ЭтоНовый() Тогда
				Значение = Элемент.Ссылка;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
КонецПроцедуры

Получение времени из даты

Сегодня появилась необходимость получить время из даты. Для вывода информации на экран достаточно использовать форматную строку 

"ДФ=HH:mm"

однако, мне захотелось получить «чистое» время без информации о дате. Для этого в тексте запроса я использовал следующую конструкцию:

ДОБАВИТЬКДАТЕ(ДатаВремя(1,1,1),МИНУТА,РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(График.Дата, ДЕНЬ),График.Дата,Минута)) КАК Время