Создан небольшой пример, который позволит новичкам познакомится с технологиями написания web приложений на java.
Скачать можно тут.
Для работы с примером нам потребуется веб контейнер, например Tomcat6, который можно скачать с официального сайта Apache Tomcat.
После инсталяции Веб контейнера, установите war файл примера на сервер (deploy).
Данный пример состоит из трёх jsp файлов, а также двух вспомогательных классов:
index.jsp - главная страница, проводит авторизацию пользователей, только авторизованные пользователи получают доступ к нашей админке.
users.jsp - список пользователей, которые имеют доступ к админке, лишних пользователей можно удалить.
adduser.jsp - форма, где можно создать нового пользователя.
Список пользователей хранится в хмл файле users.xml. Каждый пользователь имеет свой логин и пароль.
По умолчанию существует пользователь с логином: "admin", пароль: "admin";
замечание! Это учебный пример, поэтому для наглядности реализована минимальная функциональность для корректной работы.
Знакомимся с примером и задаём вопросы, указываем на замечания.
29 января 2008
25 января 2008
java.util LinkedList
Решил познакомится поближе с возможностями данного класса.
LinkedList - это реализация интерфейса List, которая реализует все операции списка и позволяет добавлять любые элементы (включая null). Кроме реализации интерфейса List , LinkedList реализует методы получения, удаления и вставки в начало и конец списка. Такие операции позволяют использовать рассматриваемый класс как стек, очередь и двухсторонняя очередь.
Единственный негативный момент в том, что LinkedList является не синхронизированной. Тоесть при доступе к одному объекту LinkedList из нескольких потоков, необходимо, внешними средствами синхронизовать этот объект. Например создать объект, который будет инкапсулировать наш объект и отвечает за синхронизацию синхронизацию:
List list = Collections.synchronizedList(new LinkedList(...));
Так теперь перейдём к примерам.
1. Создание стека с помощью LinkedList :
import java.util.LinkedList;
public class MainClass {
public static void main(String[] args) {
StackL stack = new StackL();
stack.push("First In");
stack.push("Second In");
System.out.println(stack.pop());
System.out.println(stack.pop());
}
}
class StackL {
private LinkedList list = new LinkedList();
public void push(Object v) {
list.addFirst(v);
} public Object pop() {
return list.removeFirst();
}
}
Как известно стек работает по принципу FILO (first in last out), так что результат работы нашего примера:
>Second In
>First In
2. Создание очереди с помощью LinkedList:
import java.util.LinkedList ;
public class Queue {
private LinkedList list = new LinkedList();
public void put(Object v) {
list.addFirst(v);
}
public Object get() {
return list.removeLast();
}
public boolean isEmpty() {
return list.isEmpty();
}
public static void main(String[] args) {
Queue queue = new Queue();
for(int i = 0; i < 10; i++)
queue.put(Integer.toString(i));
while(!queue.isEmpty())
System.out.println(queue.get());
}
}
В данном примере реализован принцип очереди: FIFO (first in first out).
Как вы заметили в этих примерах были ограничены возможности класса LinkedList, потому что он (LinkedList) имеет в своём арсенале методы реализующие и стек и очередь и двухсторонню очередь.
LinkedList - это реализация интерфейса List, которая реализует все операции списка и позволяет добавлять любые элементы (включая null). Кроме реализации интерфейса List , LinkedList реализует методы получения, удаления и вставки в начало и конец списка. Такие операции позволяют использовать рассматриваемый класс как стек, очередь и двухсторонняя очередь.
Единственный негативный момент в том, что LinkedList является не синхронизированной. Тоесть при доступе к одному объекту LinkedList из нескольких потоков, необходимо, внешними средствами синхронизовать этот объект. Например создать объект, который будет инкапсулировать наш объект и отвечает за синхронизацию синхронизацию:
List list = Collections.synchronizedList(new LinkedList(...));
Так теперь перейдём к примерам.
1. Создание стека с помощью LinkedList :
import java.util.LinkedList;
public class MainClass {
public static void main(String[] args) {
StackL stack = new StackL();
stack.push("First In");
stack.push("Second In");
System.out.println(stack.pop());
System.out.println(stack.pop());
}
}
class StackL {
private LinkedList list = new LinkedList();
public void push(Object v) {
list.addFirst(v);
} public Object pop() {
return list.removeFirst();
}
}
Как известно стек работает по принципу FILO (first in last out), так что результат работы нашего примера:
>Second In
>First In
2. Создание очереди с помощью LinkedList:
import java.util.LinkedList ;
public class Queue {
private LinkedList list = new LinkedList();
public void put(Object v) {
list.addFirst(v);
}
public Object get() {
return list.removeLast();
}
public boolean isEmpty() {
return list.isEmpty();
}
public static void main(String[] args) {
Queue queue = new Queue();
for(int i = 0; i < 10; i++)
queue.put(Integer.toString(i));
while(!queue.isEmpty())
System.out.println(queue.get());
}
}
В данном примере реализован принцип очереди: FIFO (first in first out).
Как вы заметили в этих примерах были ограничены возможности класса LinkedList, потому что он (LinkedList) имеет в своём арсенале методы реализующие и стек и очередь и двухсторонню очередь.
24 января 2008
Что выбрать в качестве базы данных PostgreSQL или MySQL
В следующей таблице приведены основные характеристики и возможности каждой из указанных бд.
Как видно из таблицы за счёт своей простоты, MySQL работает быстрее чем PostgreSQL. В большинстве случаев этой базовой функциональность MySQL вполне достаточно для разработки не слишком сложных Web приложений. Но всё же, PostgreSQL предоставляет много преимуществ для построение мощного хранилища и есть хорошей бесплатной альтернативой для Oracle, DB2 или MSSQL.
Так что при выборе базы данных для своего приложения необходимо внимательно оценить свои потребности и сделать правильный выбор.
ресурсы: 1 & 2
| POSTGRESQL | MYSQL |
Совместимость с ANSI SQL стандартом | Очень близка к ANSI SQL стандарту | В некоторой мере совместима с ANSI SQL |
Сравнительная производительность | Работает медленней | Работает быстрее |
Под запросы | + | - |
Транзакции | + | + |
Репликация баз данных | + | + |
Поддержка внешних ключей | + | - |
Представления | + | - |
Хранимые процедуры | + | - |
Триггеры | + | - |
Объеденения | + | - |
Поддержка Windows | + | + |
Очистка | + | - |
Поддержка ODBC | + | + |
Поддержка JDBC | + | + |
Разные типы таблиц | - | + |
Как видно из таблицы за счёт своей простоты, MySQL работает быстрее чем PostgreSQL. В большинстве случаев этой базовой функциональность MySQL вполне достаточно для разработки не слишком сложных Web приложений. Но всё же, PostgreSQL предоставляет много преимуществ для построение мощного хранилища и есть хорошей бесплатной альтернативой для Oracle, DB2 или MSSQL.
Так что при выборе базы данных для своего приложения необходимо внимательно оценить свои потребности и сделать правильный выбор.
ресурсы: 1 & 2
23 января 2008
22 января 2008
Рекомендуемая литература по Java
Thinking in Java, 2nd Edition Russian version
Thinking in Patterns Russian version
Thinking in Enterprise Java Russian version
В оригинале эти книги можно найти на сайте http://www.mindview.net/Books
Thinking in Patterns Russian version
Thinking in Enterprise Java Russian version
В оригинале эти книги можно найти на сайте http://www.mindview.net/Books
20 января 2008
16 января 2008
Отправка почты с помощью Java Mail через протокол SSL/TLS
Как использовать базовые функции Java Mail уже было расмотрено в одном из предыдущих обзоров. Теперь
рассмотрим, как отправлять почту через защищённое соеденение с smtp сервером.
для того, что-бы установить такое соеденение необходимо:
- принять сертификаты подлинности сервера;
- пройти аутентификацию на сервере.
Для начала мы должны зареестрировать провайдера алгоритма SSL :
Security.addProvider( new com.sun.net.ssl.internal.ssl.Provider());
Далее следует создать класс, который является наследником: SSLSocketFactory, и добавить имя этого класс в
свойства:
Security.setProperty( "ssl.SocketFactory.provider",SimpleSSLSocketFactory.class.getCanonicalName());
Для того что-бы выполнить соеденение по SSL/TLS нам надо принять все сертификаты сервера. Для этого мы
перегрузим свой TrustManager(класс проверяющий подлинность сертификатов) и при инициализации SSL сессии в
нашем SimpleSSLSocketFactory , TrustManager будет без проверки принимать все сертификаты предоставленные
сервером. Благодаря этому нам удастся установить соеденение с сервером.
Теперь нам осталось установить ещё несколько дополнительных свойств для использования SSL/TLS :
final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
props.setProperty( "mail.smtp.socketFactory.class", SSL_FACTORY);
// использовать только ssl соеденения в любом из направлений
props.setProperty( "mail.smtp.socketFactory.fallback", "false");
// smtp требует автентификации
props.setProperty("mail.smtp.auth","true");
После этого мы собираем письмо, как показано в предыдущей статье и отсылаем его следующим образом:
Transport tr = session.getTransport("smtp");
tr.connect(smtpHost, username, password);
msg.saveChanges();
tr.sendMessage(msg, msg.getAllRecipients());
tr.close();
Где в полях username, password надо указать соответствующие данные учётной записи на smtp сервере.
На этом всё. Если у вам не удалось самому собрать такое приложение, вы можете скачать мои исходники.
Ресурсы:
исходники : http://depositfiles.com/files/3109865
java.sun.com/products/javamail
рассмотрим, как отправлять почту через защищённое соеденение с smtp сервером.
для того, что-бы установить такое соеденение необходимо:
- принять сертификаты подлинности сервера;
- пройти аутентификацию на сервере.
Для начала мы должны зареестрировать провайдера алгоритма SSL :
Security.addProvider( new com.sun.net.ssl.internal.ssl.Provider());
Далее следует создать класс, который является наследником: SSLSocketFactory, и добавить имя этого класс в
свойства:
Security.setProperty( "ssl.SocketFactory.provider",SimpleSSLSocketFactory.class.getCanonicalName());
Для того что-бы выполнить соеденение по SSL/TLS нам надо принять все сертификаты сервера. Для этого мы
перегрузим свой TrustManager(класс проверяющий подлинность сертификатов) и при инициализации SSL сессии в
нашем SimpleSSLSocketFactory , TrustManager будет без проверки принимать все сертификаты предоставленные
сервером. Благодаря этому нам удастся установить соеденение с сервером.
Теперь нам осталось установить ещё несколько дополнительных свойств для использования SSL/TLS :
final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
props.setProperty( "mail.smtp.socketFactory.class", SSL_FACTORY);
// использовать только ssl соеденения в любом из направлений
props.setProperty( "mail.smtp.socketFactory.fallback", "false");
// smtp требует автентификации
props.setProperty("mail.smtp.auth","true");
После этого мы собираем письмо, как показано в предыдущей статье и отсылаем его следующим образом:
Transport tr = session.getTransport("smtp");
tr.connect(smtpHost, username, password);
msg.saveChanges();
tr.sendMessage(msg, msg.getAllRecipients());
tr.close();
Где в полях username, password надо указать соответствующие данные учётной записи на smtp сервере.
На этом всё. Если у вам не удалось самому собрать такое приложение, вы можете скачать мои исходники.
Ресурсы:
исходники : http://depositfiles.com/files/3109865
java.sun.com/products/javamail
15 января 2008
Отправка почты с помощью Java Mail
JavaMail API представляtn собой платформонизависимый фреймворк для создания приложений способных работать с почтовыми серверами.
JavaMail распостраняется как дополнительный пакет для J2se, а также он входит в J2ee sdk.
Если у вас не установлено J2ee sdk, то вы можете скачать java mail API из сайта Sun Microsistems : java.sun.com/products/javamail .
В данном примере мы разберём как отправлять простые письма с помощью Mail API, поетому из скачаного архива нам понадобится библиотека mail.jar.
Для отправки сообщений написали функцию, которая получает все необходимые параметры (адрес smtp , smtp порт, e-mail адресс с которого отправляю, e-mail адресс на который отправляют, тема письм и содержание).
public void send(String smtpHost, int smtpPort, String from,String to, String subject, String content) throws AddressException, MessagingException {
java.util.Properties props = System.getProperties();
props.setProperty("mail.smtp.host", smtpHost); props.setProperty("mail.smtp.port", ""+smtpPort);
Session session = Session.getDefaultInstance (props, null);
// Construct the message
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
msg.setSubject(subject);
msg.setText(content);
Transport.send(msg);
}
Вызов функции будет иметь приблизительно такой вид.
send("smtp_server.com", 25, " from@email.com","to@email.com", "title","Hello from app!");
Замечание. необходимо указывать рабочий smtp иначе будет генерироватся исключение.
В следующей части рассмотрим отправку сообщений с аутентификацией через защищённый протокол ssl.
JavaMail распостраняется как дополнительный пакет для J2se, а также он входит в J2ee sdk.
Если у вас не установлено J2ee sdk, то вы можете скачать java mail API из сайта Sun Microsistems : java.sun.com/products/javamail .
В данном примере мы разберём как отправлять простые письма с помощью Mail API, поетому из скачаного архива нам понадобится библиотека mail.jar.
Для отправки сообщений написали функцию, которая получает все необходимые параметры (адрес smtp , smtp порт, e-mail адресс с которого отправляю, e-mail адресс на который отправляют, тема письм и содержание).
public void send(String smtpHost, int smtpPort, String from,String to, String subject, String content) throws AddressException, MessagingException {
java.util.Properties props = System.getProperties();
props.setProperty("mail.smtp.host", smtpHost); props.setProperty("mail.smtp.port", ""+smtpPort);
Session session = Session.getDefaultInstance (props, null);
// Construct the message
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
msg.setSubject(subject);
msg.setText(content);
Transport.send(msg);
}
Вызов функции будет иметь приблизительно такой вид.
send("smtp_server.com", 25, " from@email.com","to@email.com", "title","Hello from app!");
Замечание. необходимо указывать рабочий smtp иначе будет генерироватся исключение.
В следующей части рассмотрим отправку сообщений с аутентификацией через защищённый протокол ssl.
12 января 2008
String в вопросах и ответах
1
Какая разница между:
String s1="string";
и
String s2=new String("string");
В первом примере создаётся только один объект строка: "string" , а затем создаётся указатель s1 на эту строку. Во втором примере сначала создаётся первый объект "string", а затем второй объект строка оператором new. В итоге получается второй способ менее эффективным.
2
Когда следует использовать String, а когда StringBuffer ?
Оба класса String и StringBuffer предназначены для работы со строковыми переменными, которые содержат более одного символа. Класс String следует использовать для работы со строками, значение которых не будет меняться. Например, если вы передаёте в метод строковый параметр, который точно не будет изменятся внутри метода, то лучше передавать строку с помощью класса String.
Класс StringBuffer следует использовать для строковых переменных, которые будут изменяться. Например когда считіваются данные из файла и динамически создаётся строковая переменная. Это связано с тем, что String - константа, и при каждом изменении будет создаватся новая строка и переприсваиватся указатель на неё.
3
Как преобразовать 16ричной число в виде строки "FFFA" в 10чную форму.
Можно использовать функцию: Integer.parseInt(String s,Int r);
r- базис (radix) в десятичной системе для 16чных чисел равен 16ти.
4
Есть String, которая состоит из нескольких строчек разделённых символом '\n' , как их объеденить ?
Можно использовать класс java.util.StringTokenizer. Например следующим образом:
StringTokenizer t=new StringTokenizer(" 1 \n 2 \n 3 \n 4 ","\n");
while (t.hasMoreTokens()){
System.out.println(t.nextToken());
}
5
Как проверить что введённая строка состоит ТОЛЬКО из заглавных символов?
String onlyLowerCase="SOME STRiNG";
if ( onlyLowerCase.equals(onlyLowerCase.toUpperCase())){
// в строке только заглавные символы ...
}
Какая разница между:
String s1="string";
и
String s2=new String("string");
В первом примере создаётся только один объект строка: "string" , а затем создаётся указатель s1 на эту строку. Во втором примере сначала создаётся первый объект "string", а затем второй объект строка оператором new. В итоге получается второй способ менее эффективным.
2
Когда следует использовать String, а когда StringBuffer ?
Оба класса String и StringBuffer предназначены для работы со строковыми переменными, которые содержат более одного символа. Класс String следует использовать для работы со строками, значение которых не будет меняться. Например, если вы передаёте в метод строковый параметр, который точно не будет изменятся внутри метода, то лучше передавать строку с помощью класса String.
Класс StringBuffer следует использовать для строковых переменных, которые будут изменяться. Например когда считіваются данные из файла и динамически создаётся строковая переменная. Это связано с тем, что String - константа, и при каждом изменении будет создаватся новая строка и переприсваиватся указатель на неё.
3
Как преобразовать 16ричной число в виде строки "FFFA" в 10чную форму.
Можно использовать функцию: Integer.parseInt(String s,Int r);
r- базис (radix) в десятичной системе для 16чных чисел равен 16ти.
4
Есть String, которая состоит из нескольких строчек разделённых символом '\n' , как их объеденить ?
Можно использовать класс java.util.StringTokenizer. Например следующим образом:
StringTokenizer t=new StringTokenizer(" 1 \n 2 \n 3 \n 4 ","\n");
while (t.hasMoreTokens()){
System.out.println(t.nextToken());
}
5
Как проверить что введённая строка состоит ТОЛЬКО из заглавных символов?
String onlyLowerCase="SOME STRiNG";
if ( onlyLowerCase.equals(onlyLowerCase.toUpperCase())){
// в строке только заглавные символы ...
}
11 января 2008
Создание Web Сервиса на Java с помощью Tomcat и Jwsdp
Написание Веб сервиса - серверной и клиентской части будет состоять из 20 простых шагов. Но для начала необходимо выполнить кое - какую предварительную работу.
Первым делом устанавливаем Web Container, например: Tomcat6.
В переменных окружения создаём: CATALINA_HOME и TOMCAT_HOME, в обеих указываем пути к установленному каталогу.
Устанавливаем JWSDP (Java Web Service Developer Pack) и создаём переменную окружения: JWSDP_HOME.
Замечание! при написании web сервиса использовалось: jdk 1.5, tomcat 6.0, jwsdp 2.0 и дополнительно были обновлены библиотеки: saaj до версии 1.3 ( saaj.dev.java.net) при других версиях программ могут возникать ошибки работы ( о которых вы можете написать в коментариях).
Создаём приложение
В данном примере не будут использоватся никакие среды разработки (IDE), поетому создаём в нашей рабочей папке следующие кататлоги:
WS
- build
- config
- dist
- doc
- src
- web
Написание Серверной части
1. Создаём интерфейс веб сервиса, где объявляем методы, к которым может обращатся клиент
// сохраняем в src/server/wstest.java
package server;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.lang.*;
public interface wstest extends Remote {
public String getEchoString(String strv) throws RemoteException;
public int getEchoInt(int intv) throws RemoteException;
public int add (int i, int j) throws RemoteException;
public double divide (int i, int j) throws RemoteException;
}
2. Создаём класс где реализуем методы, описанные в интерфейсе
// сохраняем в src/server/wstestImpl.java
package server;
import java.lang.*;
public class wstestImpl implements wstest {
public String getEchoString(String strv) {
return strv;
}
public int getEchoInt(int intv) {
return intv;
}
public int add (int i, int j) {
return i+j;
}
public double divide (int i, int j) {
return (double)i/(double)j;
} public static void main (String[] args){
wstestImpl wstest = new wstestImpl();
System.out.println(" 5+2 = "+wstest.add(5,2));
System.out.println (" 5/2 = "+wstest.divide(5,2));
}
}
3. Создаём конфигурационный файл веб сервиса
<?xml version="1.0" encoding="UTF-8"?>
<!-- configuration file for JWSDP wsdeploy tool -->
<webServices xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd" version="1.0" targetNamespaceBase="http://peteryeung.homeip.net/targetNamespaceBase/operation/message " typeNamespaceBase="http://peteryeung.homeip.net/typeNamespaceBase/type "> <!-- the endpoint name becomes the service name in the WSDL --> <endpoint name="wstestService" interface="server.wstest" implementation="server.wstestImpl"/> <endpointMapping endpointName="wstestService" urlPattern="/wstestService"/> </webServices>
сохраняем в : config/ jaxrpc-ri.xml
4. Создаем web.xml файл
<?xml version="1.0" encoding="UTF-8"?>
<web-app> <display-name>SimpleWebService</display-name> <description>First web service by me</description> <session-config> <session-timeout>60</session-timeout> </session-config> </web-app>
сохраняем в config/web.xml
5. Копируем библиотеки в каталог библиотек Tomcat (CATALINA_HOME\Lib) :
%JWSDP_HOME%\jaxrpc\lib
%JWSDP_HOME%\saaj\lib
%JWSDP_HOME%\jwsdp-shared\lib
%JWSDP_HOME%\jaxp\lib\endorsed
%JWSDP_HOME%\sjsxp\lib\
%JWSDP_HOME%\fastinfoset\lib\
Для пунктов 6 - 10 были созданы отдельные bat файлы, которые по очереди запускались
6. Компилируем исходники серверной части
javac -d build src/server/*.java
7. Создаём правильную структуру WAR архива
md web\WEB-INF
md web\WEB-INF\classes
xcopy/S build\server\* web\WEB-INF\classes\server\
copy config\jaxrpc-ri.xml web/WEB-INF
copy config\web.xml web/WEB-INF
8. Создаём WAR файл
jar -cvf build/myWEB-INF.war -C web\ .
9. Переделываем WAR архив специально для Web сервиса
md dist
md build\tmpdir
%JWSDP_HOME%\jaxrpc\bin\wsdeploy.bat -verbose -o dist/myWStest.war build/myWEB-INF.war
10. Загружаем на Tomcat
copy dist\myWStest.war %TOMCAT_HOME%\webapps
11. Перезагружаем Tomcat
12. Проверяем wsdl файл
http://localhost:8080/myWStest/wstestService?WSDL
Если всё ранее выполнено правильно , то откроется настроечный XML файл.
Создание клиенсткой части
13. Определяем для клиента, где находится сервис ( WSDL )
config/wscompile_config.xml
<?xml version="1.0"?>
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<!-- WSDL URL and generated package name --> <wsdl location=" http://localhost:8080/myWStest/wstestService?WSDL" packageName="clientStub"></wsdl> </configuration>
14. Генерируем код заглушки (stub code)
%JWSDP_HOME%\jaxrpc\bin\wscompile -d build -gen:client -keep config/wscompile_config.xml
15. Генерируем документацию (java docs)
javadoc -d doc\clientStub build\clientStub\*.java
16. Создаём Jar
md lib jar -cvf lib/wsstub.jar -C build clientStub/
17. Создаём тестовое клиент приложение
// сохраняем в src/client/wstestclient.java
import clientStub.*;
public class wstestclient {
public static void main (String[] args)
{
WstestService wstestService = new WstestService_Impl();
Wstest wstest=null; try { wstest = wstestService.getWstestPort();
} catch(javax.xml.rpc.ServiceException e) { e.printStackTrace(System.err);
} // Invoke the webservices
try {
System.out.println(" wstest.getEchoInt(1) -> "+wstest.getEchoInt(1));
System.out.println(" wstest।getEchoString(\"test\")->"+wstest.getEchoString("test"));
System.out.println(" 5+2 = "+wstest.add(5,2)); System.out.println(" 5/2 = "+wstest.divide(5,2));
} catch (java.rmi.RemoteException e) {
e.printStackTrace (System.err);
}
}
}
18. Компилируем тестовый пример
javac -g -d build -classpath lib/wsstub.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc-api.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc- spi.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc-impl.jar;
src/client/*.java
19. Запускаем клиент
java -cp lib/wsstub.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc-api.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc- spi.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc-impl.jar;
%JWSDP_HOME%\jwsdp-shared\lib\jax-qname.jar; %JWSDP_HOME%\jwsdp-shared\lib\activation.jar;
%JWSDP_HOME%\jwsdp-shared\lib\mail.jar;
%JWSDP_HOME%\saaj\lib\saaj- impl.jar; %JWSDP_HOME%\saaj\lib\saaj-api.jar;
%JWSDP_HOME%\jaxp\lib\endorsed\xercesImpl.jar; %JWSDP_HOME%\fastinfoset\lib\FastInfoset.jar;
%JWSDP_HOME%\sjsxp\lib\jsr173_api.jar;
%JWSDP_HOME%\jaxp\lib\endorsed\dom.jar;
build client.wstestclient pause
20. Результат работы появится в консоли
wstest।getEchoInt(1) -> 1
wstest।getEchoString("test") -> test
5+2 = 7
5/2 = 2.5
создание Web сервиса успешно завершено
Первым делом устанавливаем Web Container, например: Tomcat6.
В переменных окружения создаём: CATALINA_HOME и TOMCAT_HOME, в обеих указываем пути к установленному каталогу.
Устанавливаем JWSDP (Java Web Service Developer Pack) и создаём переменную окружения: JWSDP_HOME.
Замечание! при написании web сервиса использовалось: jdk 1.5, tomcat 6.0, jwsdp 2.0 и дополнительно были обновлены библиотеки: saaj до версии 1.3 ( saaj.dev.java.net) при других версиях программ могут возникать ошибки работы ( о которых вы можете написать в коментариях).
Создаём приложение
В данном примере не будут использоватся никакие среды разработки (IDE), поетому создаём в нашей рабочей папке следующие кататлоги:
WS
- build
- config
- dist
- doc
- src
- web
Написание Серверной части
1. Создаём интерфейс веб сервиса, где объявляем методы, к которым может обращатся клиент
// сохраняем в src/server/wstest.java
package server;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.lang.*;
public interface wstest extends Remote {
public String getEchoString(String strv) throws RemoteException;
public int getEchoInt(int intv) throws RemoteException;
public int add (int i, int j) throws RemoteException;
public double divide (int i, int j) throws RemoteException;
}
2. Создаём класс где реализуем методы, описанные в интерфейсе
// сохраняем в src/server/wstestImpl.java
package server;
import java.lang.*;
public class wstestImpl implements wstest {
public String getEchoString(String strv) {
return strv;
}
public int getEchoInt(int intv) {
return intv;
}
public int add (int i, int j) {
return i+j;
}
public double divide (int i, int j) {
return (double)i/(double)j;
} public static void main (String[] args){
wstestImpl wstest = new wstestImpl();
System.out.println(" 5+2 = "+wstest.add(5,2));
System.out.println (" 5/2 = "+wstest.divide(5,2));
}
}
3. Создаём конфигурационный файл веб сервиса
<?xml version="1.0" encoding="UTF-8"?>
<!-- configuration file for JWSDP wsdeploy tool -->
<webServices xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd" version="1.0" targetNamespaceBase="http://peteryeung.homeip.net/targetNamespaceBase/operation/message " typeNamespaceBase="http://peteryeung.homeip.net/typeNamespaceBase/type "> <!-- the endpoint name becomes the service name in the WSDL --> <endpoint name="wstestService" interface="server.wstest" implementation="server.wstestImpl"/> <endpointMapping endpointName="wstestService" urlPattern="/wstestService"/> </webServices>
сохраняем в : config/ jaxrpc-ri.xml
4. Создаем web.xml файл
<?xml version="1.0" encoding="UTF-8"?>
<web-app> <display-name>SimpleWebService</display-name> <description>First web service by me</description> <session-config> <session-timeout>60</session-timeout> </session-config> </web-app>
сохраняем в config/web.xml
5. Копируем библиотеки в каталог библиотек Tomcat (CATALINA_HOME\Lib) :
%JWSDP_HOME%\jaxrpc\lib
%JWSDP_HOME%\saaj\lib
%JWSDP_HOME%\jwsdp-shared\lib
%JWSDP_HOME%\jaxp\lib\endorsed
%JWSDP_HOME%\sjsxp\lib\
%JWSDP_HOME%\fastinfoset\lib\
Для пунктов 6 - 10 были созданы отдельные bat файлы, которые по очереди запускались
6. Компилируем исходники серверной части
javac -d build src/server/*.java
7. Создаём правильную структуру WAR архива
md web\WEB-INF
md web\WEB-INF\classes
xcopy/S build\server\* web\WEB-INF\classes\server\
copy config\jaxrpc-ri.xml web/WEB-INF
copy config\web.xml web/WEB-INF
8. Создаём WAR файл
jar -cvf build/myWEB-INF.war -C web\ .
9. Переделываем WAR архив специально для Web сервиса
md dist
md build\tmpdir
%JWSDP_HOME%\jaxrpc\bin\wsdeploy.bat -verbose -o dist/myWStest.war build/myWEB-INF.war
10. Загружаем на Tomcat
copy dist\myWStest.war %TOMCAT_HOME%\webapps
11. Перезагружаем Tomcat
12. Проверяем wsdl файл
http://localhost:8080/myWStest/wstestService?WSDL
Если всё ранее выполнено правильно , то откроется настроечный XML файл.
Создание клиенсткой части
13. Определяем для клиента, где находится сервис ( WSDL )
config/wscompile_config.xml
<?xml version="1.0"?>
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<!-- WSDL URL and generated package name --> <wsdl location=" http://localhost:8080/myWStest/wstestService?WSDL" packageName="clientStub"></wsdl> </configuration>
14. Генерируем код заглушки (stub code)
%JWSDP_HOME%\jaxrpc\bin\wscompile -d build -gen:client -keep config/wscompile_config.xml
15. Генерируем документацию (java docs)
javadoc -d doc\clientStub build\clientStub\*.java
16. Создаём Jar
md lib jar -cvf lib/wsstub.jar -C build clientStub/
17. Создаём тестовое клиент приложение
// сохраняем в src/client/wstestclient.java
import clientStub.*;
public class wstestclient {
public static void main (String[] args)
{
WstestService wstestService = new WstestService_Impl();
Wstest wstest=null; try { wstest = wstestService.getWstestPort();
} catch(javax.xml.rpc.ServiceException e) { e.printStackTrace(System.err);
} // Invoke the webservices
try {
System.out.println(" wstest.getEchoInt(1) -> "+wstest.getEchoInt(1));
System.out.println(" wstest।getEchoString(\"test\")->"+wstest.getEchoString("test"));
System.out.println(" 5+2 = "+wstest.add(5,2)); System.out.println(" 5/2 = "+wstest.divide(5,2));
} catch (java.rmi.RemoteException e) {
e.printStackTrace (System.err);
}
}
}
18. Компилируем тестовый пример
javac -g -d build -classpath lib/wsstub.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc-api.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc- spi.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc-impl.jar;
src/client/*.java
19. Запускаем клиент
java -cp lib/wsstub.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc-api.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc- spi.jar;
%JWSDP_HOME%\jaxrpc\lib\jaxrpc-impl.jar;
%JWSDP_HOME%\jwsdp-shared\lib\jax-qname.jar; %JWSDP_HOME%\jwsdp-shared\lib\activation.jar;
%JWSDP_HOME%\jwsdp-shared\lib\mail.jar;
%JWSDP_HOME%\saaj\lib\saaj- impl.jar; %JWSDP_HOME%\saaj\lib\saaj-api.jar;
%JWSDP_HOME%\jaxp\lib\endorsed\xercesImpl.jar; %JWSDP_HOME%\fastinfoset\lib\FastInfoset.jar;
%JWSDP_HOME%\sjsxp\lib\jsr173_api.jar;
%JWSDP_HOME%\jaxp\lib\endorsed\dom.jar;
build client.wstestclient pause
20. Результат работы появится в консоли
wstest।getEchoInt(1) -> 1
wstest।getEchoString("test") -> test
5+2 = 7
5/2 = 2.5
создание Web сервиса успешно завершено
Настройка Apache Tomcat для работы с протоколом SSL
SSL (Secure Socket Layer) - это технология, которая позволяет устанавливать бзопасное соеденение между веб броузером и веб сервером. Это значит что каждая из сторон будет отправлять данные в зашифрованном виде, а другая сторона будет их расшифровывать перед обработкой. Второй важный аспект в работе протокола SSL - это аутентификация. Прежде чем расказать серверу свои секретные данные (логин, пароль) сервер предоставит униальный "Сертификат" - доказательства того, что этот сервер действительно тот за кого себя выдаёт . Так же возможны случаи, когда сервер запрашивает "сертификат" у броузера клиента - "Клиентская аутентификация".
От теории к практики. Для начала нам необходимо сгенерировать сертификат для Apach Tomcat. В этой задаче нам поможет утилита keytool. В более ранние версии J2se она невходила и приходилось качать дополнительный пакет JSSE (java SE security) , но начиная с j2se 1.4 такой необходимости нету.
Итак, для генерации сертификатов, необходимо запустить утилиту keytool.
В Windows:
%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA
в Unix: $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
После запуска вам будет предложен ряд вопросов, ответив на которые вы сгенерируете сертификат.
Внимание. Это всего лишь тестовый сертификат, который может использоватся для разработки и тестирования приложений, в реальных бизнес приложениях сертифиаты должны быть выданы специальными ЦСК (центр сертификации ключей), которые несут ответственность за их автентичность.
Сертификат сгенерирован, осталось разрешить томкату принимать SSL соеденения. Для этого в файле $CATALINA_HOME/conf/server.xml неоходимо раскоментировать запись:"SSL HTTP/1.1 Connector", где указывается параметры соеденения, у меня она выглядит следующим образом:
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" />
Протестировать SSL можно:
https://localhost:8443
Броузер проинформирует о наличии на сервере сертификата от неизвестной организации и предложит принять его, что и надо сделать для загрузки страници.
От теории к практики. Для начала нам необходимо сгенерировать сертификат для Apach Tomcat. В этой задаче нам поможет утилита keytool. В более ранние версии J2se она невходила и приходилось качать дополнительный пакет JSSE (java SE security) , но начиная с j2se 1.4 такой необходимости нету.
Итак, для генерации сертификатов, необходимо запустить утилиту keytool.
В Windows:
%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA
в Unix: $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
После запуска вам будет предложен ряд вопросов, ответив на которые вы сгенерируете сертификат.
Внимание. Это всего лишь тестовый сертификат, который может использоватся для разработки и тестирования приложений, в реальных бизнес приложениях сертифиаты должны быть выданы специальными ЦСК (центр сертификации ключей), которые несут ответственность за их автентичность.
Сертификат сгенерирован, осталось разрешить томкату принимать SSL соеденения. Для этого в файле $CATALINA_HOME/conf/server.xml неоходимо раскоментировать запись:"SSL HTTP/1.1 Connector", где указывается параметры соеденения, у меня она выглядит следующим образом:
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" />
Протестировать SSL можно:
https://localhost:8443
Броузер проинформирует о наличии на сервере сертификата от неизвестной организации и предложит принять его, что и надо сделать для загрузки страници.
Парсинг XML с помощью DOM
Пусть у нас имеется xml файл в котором хранится список студентов.
<students>
<student>
<name>Nikolaj</name>
<surname>Ivanov</surname>
<age>23</age>
<group>PF-11</group>
</student>
<student>
<name>Petr</name>
<surname>Kilkin</surname>
<age>22</age>
<group>FP-22</group>
</student>
</students>
перед нами стоит задача извлечь данные о студентах в список (например ArrayList) для дальнейшей обработки.
Первое что сделаем - напишем класс, который будет описывать студента:
class Student{
private String name="";
private String surname="";
private int age="";
private String group="";
// самостоятельно добавьте конструктор, а также
// getXXX() и setXXX() методы для каждого параметра
}
Теперь переходим к написанию парсера. Основной идеей Dom парсера есть перебор по дереву всех элементов хмл файла. Наш класс - парсер будет читать хмл файл и выбирать все необходимые данные оттуда. Сразу приведу пример такого класса:
//Dom Parser
import java.util.*;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
public class DomStudParser
{
private Document doc = null;
private String txt = "";
private Student tmpS = null;
private List stds = null;
// fName - имя хмл файла
public DomHostsParser(String fName)
{
try
{
doc = parserXML(new File(fName));
stds = new ArrayList();
visit(doc, 0);
Host tmp=null;
}
catch(Exception error)
{
error.printStackTrace();
}
}
public void visit(Node node, int level)
{
NodeList nl = node.getChildNodes();
String parent="";
for(int i=0, cnt=nl.getLength(); i<cnt; i++)
{
if (nl.item(i).getNodeType()==Node.TEXT_NODE){ // if1
parent=nl.item(i).getParentNode().getNodeName();
txt=nl.item(i).getNodeValue();
if (parent=="name"){ // if1.1
tmpS.setName(txt);
}
if (parent=="surname"){ // if1.2
tmpS.setSurname(txt);
}
if (parent=="age"){ // if1.3
tmpS.setAge(Integer.valueOf(txt));
}
if (parent=="group"){
tmpS.setGroup(txt);
}
} else {
if (nl.item(i).getNodeName().equals("student")){
tmpS=new Student();
stds.add(tmpS);
}
}
System.out.println(nl.item(i).getNodeName() + " = " + nl.item(i).getNodeValue());
visit(nl.item(i), level+1);
}
}
public Document parserXML(File file) throws SAXException, IOException, ParserConfigurationException
{
return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
}
public List getStds() {
return stds;
}
public void setStds(List stds) {
this.stds = stds;
}
}
Итак немного объяснений.
Функция parserXML преобразовывает наш хмл файл в хмл документ, над которым может проводить работу.
Основной в данном классе - рекурсивно вызываемый метод visit, который по дереву (поиск в глубину) перебирает все узлы нашего хмл елемента.
Узлы бывают нескольких типов: название атрибута, название элемента, значение элемента, коментарий и т.д.
В нашем случае узлы только 2х типов - это TEXT_NODE (значение элемента) и ELEMENT_NODE (название элемента). Парсер начинает просмотр с элемента "<students>" , далее обработке подвергнется "текст", который находится между тегами <students> и <student> , далее элемент <student> , при достижении которого сработает условие "else if" и будет создан новый экземпляр класса Student, который мы начнём заполнять. Когда дойдём до текста после элемента <name> - "Nikolaj" , сработает условие if1.1.Это произойдт потому что родителем для данного текста есть элемент name и т.д. мы переберём все элементы и в итоге получим List с двумя объектами Student внутри, получить этот список можна с помощью функции getStds().
подробнее:
http://java.sun.com/j2se/1.4.2/docs/api/org/w3c/dom/package-summary.html
<students>
<student>
<name>Nikolaj</name>
<surname>Ivanov</surname>
<age>23</age>
<group>PF-11</group>
</student>
<student>
<name>Petr</name>
<surname>Kilkin</surname>
<age>22</age>
<group>FP-22</group>
</student>
</students>
перед нами стоит задача извлечь данные о студентах в список (например ArrayList) для дальнейшей обработки.
Первое что сделаем - напишем класс, который будет описывать студента:
class Student{
private String name="";
private String surname="";
private int age="";
private String group="";
// самостоятельно добавьте конструктор, а также
// getXXX() и setXXX() методы для каждого параметра
}
Теперь переходим к написанию парсера. Основной идеей Dom парсера есть перебор по дереву всех элементов хмл файла. Наш класс - парсер будет читать хмл файл и выбирать все необходимые данные оттуда. Сразу приведу пример такого класса:
//Dom Parser
import java.util.*;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
public class DomStudParser
{
private Document doc = null;
private String txt = "";
private Student tmpS = null;
private List stds = null;
// fName - имя хмл файла
public DomHostsParser(String fName)
{
try
{
doc = parserXML(new File(fName));
stds = new ArrayList();
visit(doc, 0);
Host tmp=null;
}
catch(Exception error)
{
error.printStackTrace();
}
}
public void visit(Node node, int level)
{
NodeList nl = node.getChildNodes();
String parent="";
for(int i=0, cnt=nl.getLength(); i<cnt; i++)
{
if (nl.item(i).getNodeType()==Node.TEXT_NODE){ // if1
parent=nl.item(i).getParentNode().getNodeName();
txt=nl.item(i).getNodeValue();
if (parent=="name"){ // if1.1
tmpS.setName(txt);
}
if (parent=="surname"){ // if1.2
tmpS.setSurname(txt);
}
if (parent=="age"){ // if1.3
tmpS.setAge(Integer.valueOf(txt));
}
if (parent=="group"){
tmpS.setGroup(txt);
}
} else {
if (nl.item(i).getNodeName().equals("student")){
tmpS=new Student();
stds.add(tmpS);
}
}
System.out.println(nl.item(i).getNodeName() + " = " + nl.item(i).getNodeValue());
visit(nl.item(i), level+1);
}
}
public Document parserXML(File file) throws SAXException, IOException, ParserConfigurationException
{
return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
}
public List getStds() {
return stds;
}
public void setStds(List stds) {
this.stds = stds;
}
}
Итак немного объяснений.
Функция parserXML преобразовывает наш хмл файл в хмл документ, над которым может проводить работу.
Основной в данном классе - рекурсивно вызываемый метод visit, который по дереву (поиск в глубину) перебирает все узлы нашего хмл елемента.
Узлы бывают нескольких типов: название атрибута, название элемента, значение элемента, коментарий и т.д.
В нашем случае узлы только 2х типов - это TEXT_NODE (значение элемента) и ELEMENT_NODE (название элемента). Парсер начинает просмотр с элемента "<students>" , далее обработке подвергнется "текст", который находится между тегами <students> и <student> , далее элемент <student> , при достижении которого сработает условие "else if" и будет создан новый экземпляр класса Student, который мы начнём заполнять. Когда дойдём до текста после элемента <name> - "Nikolaj" , сработает условие if1.1.Это произойдт потому что родителем для данного текста есть элемент name и т.д. мы переберём все элементы и в итоге получим List с двумя объектами Student внутри, получить этот список можна с помощью функции getStds().
подробнее:
http://java.sun.com/j2se/1.4.2/docs/api/org/w3c/dom/package-summary.html
10 января 2008
Как получить текущее время/дату
Существует множество способов для получение текущих времени/даты, всё зависит от того, для каких целей это нам нужно.
1. Мы хотим подсчитать время выполнения какого то метода. Для этого достаточно вызвать: System.currentTimeMillis () до и после выполнения метода.
Каждый вызов даст нам число - текущее время в милисекундах. Отняв второе от первого получим время работы метода в милисекундах.
2. Нам надо в правильно отформатированном виде вывести дату время.
В пакете java.util есть класс Calendar, которым мы и воспользуемся:
java.util.Calendar.getInstance().getTime()
результат стандартно сформированная строка, например:
Thu Jan 10 16:08:49 EET 2008
Если данный вид нас не устраивает, можно использовать класс SimpleDateFormat из пакета java.text , он предоставляет гораздо более широкие возможности в отображении даты / времени.
Например
String dt=new java.text.SimpleDateFormat("dd-MMM-yy G hh:mm aaa")).format(java.util.Calendar.getInstance ().getTime();
даст нам результат в виде :
10-янв-08 н.э. 04:08 PM
Полный перечень ключевых слов, которые могут быть использованны при формирования вида отображения даты/времени можно узреть в документации Sun : SimpleDateFormat
1. Мы хотим подсчитать время выполнения какого то метода. Для этого достаточно вызвать: System.currentTimeMillis () до и после выполнения метода.
Каждый вызов даст нам число - текущее время в милисекундах. Отняв второе от первого получим время работы метода в милисекундах.
2. Нам надо в правильно отформатированном виде вывести дату время.
В пакете java.util есть класс Calendar, которым мы и воспользуемся:
java.util.Calendar.getInstance().getTime()
результат стандартно сформированная строка, например:
Thu Jan 10 16:08:49 EET 2008
Если данный вид нас не устраивает, можно использовать класс SimpleDateFormat из пакета java.text , он предоставляет гораздо более широкие возможности в отображении даты / времени.
Например
String dt=new java.text.SimpleDateFormat("dd-MMM-yy G hh:mm aaa")).format(java.util.Calendar.getInstance ().getTime();
даст нам результат в виде :
10-янв-08 н.э. 04:08 PM
Полный перечень ключевых слов, которые могут быть использованны при формирования вида отображения даты/времени можно узреть в документации Sun : SimpleDateFormat
05 января 2008
Пределы примитивных типов данных
Небольшая програмка, которая выводит пределы для примитивных типов данных.
class PrimitivLimits{
public static void main(String []s){
System.out.println("Byte: [" + Byte.MIN_VALUE + "," + Byte.MAX_VALUE +"]");
System.out.println("Short: ["+Short.MIN_VALUE+" , " + Short.MAX_VALUE+"]");
System.out.println("Int: ["+Integer.MIN_VALUE+" , " + Integer.MAX_VALUE+"]");
System.out.println("Long: ["+Long.MIN_VALUE+" , " + Long.MAX_VALUE+"]");
System.out.println("Float: ["+Float.MIN_VALUE+" , " + Float.MAX_VALUE+"]");
System.out.println("Double: ["+Double.MIN_VALUE+" , " + Double.MAX_VALUE+"]");
}
}
class PrimitivLimits{
public static void main(String []s){
System.out.println("Byte: [" + Byte.MIN_VALUE + "," + Byte.MAX_VALUE +"]");
System.out.println("Short: ["+Short.MIN_VALUE+" , " + Short.MAX_VALUE+"]");
System.out.println("Int: ["+Integer.MIN_VALUE+" , " + Integer.MAX_VALUE+"]");
System.out.println("Long: ["+Long.MIN_VALUE+" , " + Long.MAX_VALUE+"]");
System.out.println("Float: ["+Float.MIN_VALUE+" , " + Float.MAX_VALUE+"]");
System.out.println("Double: ["+Double.MIN_VALUE+" , " + Double.MAX_VALUE+"]");
}
}
02 января 2008
01 января 2008
Алгоритм Des. Симметрическое шифрование в java
Симметрическое шифрование - способ шифрования, в котором для (за)шифрования и расшифрования применяется один и тот же криптографический ключ.
Рассмотрим реализацию симметрического шифрования в java на примере алгоритма DES. В первую очередь нам понадобится класс javax.crypto.Cipher , который реализует базовые функции популярных криптографических алгоритомов шифрования. Для создания экземпляра такого класса используется статистический метод Cipher.getInstance , который в качестве параметра получает имя криптографического алгоритма шифрования. В нашем случае:
Cipher chr = Cipher.getInstance("DES");
Следующим шагом будет инициализация экземпляра класса и указание каком режиме он будет работать:
в режиме шифрования chr.init(Cipher.ENCRYPT_MODE, key); - , или расщифрования -
chr.init(Cipher.DECRYPT_MODE, key); .
Как видно, появился новый неизвесный параметр: key - это 56 битный ключ алгоритма DES. Данный параметр имеет тип javax.crypto.SecretKey и может быть создан с помощью класса
javax.crypto.KeyGenerator.
SecretKey key = KeyGenerator.getInstance("DES").generateKey();
Шифрование или расшифрование выполняет функция doFinal класса Cipher, которая на входе получает масив байт и возвращает также масив байт, но уже соответственно преобразованных. Что именно (шифрование или расшифрование) будет выполнять функция зависит от того что было указанно в первом параметре функции инициализации init().
Итак из всего выше сказанного можно скомпоновать небольшой класс. Класс по работе скриптографическим алгоритмом шифрования DES. К классу прилагается функция main, для того что-бы проверить правильностб работы созданных функций.
Рассмотрим реализацию симметрического шифрования в java на примере алгоритма DES. В первую очередь нам понадобится класс javax.crypto.Cipher , который реализует базовые функции популярных криптографических алгоритомов шифрования. Для создания экземпляра такого класса используется статистический метод Cipher.getInstance , который в качестве параметра получает имя криптографического алгоритма шифрования. В нашем случае:
Cipher chr = Cipher.getInstance("DES");
Следующим шагом будет инициализация экземпляра класса и указание каком режиме он будет работать:
в режиме шифрования chr.init(Cipher.ENCRYPT_MODE, key); - , или расщифрования -
chr.init(Cipher.DECRYPT_MODE, key); .
Как видно, появился новый неизвесный параметр: key - это 56 битный ключ алгоритма DES. Данный параметр имеет тип javax.crypto.SecretKey и может быть создан с помощью класса
javax.crypto.KeyGenerator.
SecretKey key = KeyGenerator.getInstance("DES").generateKey();
Шифрование или расшифрование выполняет функция doFinal класса Cipher, которая на входе получает масив байт и возвращает также масив байт, но уже соответственно преобразованных. Что именно (шифрование или расшифрование) будет выполнять функция зависит от того что было указанно в первом параметре функции инициализации init().
Итак из всего выше сказанного можно скомпоновать небольшой класс. Класс по работе скриптографическим алгоритмом шифрования DES. К классу прилагается функция main, для того что-бы проверить правильностб работы созданных функций.
import javax.crypto.*;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/**
* Класс реализующий работу с алгоритмом шифрования DES
* @author Rumoku
*/
class DesEncrypter {
Cipher ecipher;
Cipher dcipher;
/**
* Конструктор
* @param key секретный ключ алгоритма DES. Экземпляр класса SecretKey
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
*/
public DesEncrypter(SecretKey key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
ecipher = Cipher.getInstance("DES");
dcipher = Cipher.getInstance("DES");
ecipher.init(Cipher.ENCRYPT_MODE, key);
dcipher.init(Cipher.DECRYPT_MODE, key);
}
/**
* Функция шифровнаия
* @param str строка открытого текста
* @return зашифрованная строка в формате Base64
*/
public String encrypt(String str) throws UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {
byte[] utf8 = str.getBytes("UTF8");
byte[] enc = ecipher.doFinal(utf8);
return new sun.misc.BASE64Encoder().encode(enc);
}
/**
* Функция расшифрования
* @param str зашифрованная строка в формате Base64
* @return расшифрованная строка
*/
public String decrypt(String str) throws IOException, IllegalBlockSizeException, BadPaddingException {
byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
byte[] utf8 = dcipher.doFinal(dec);
return new String(utf8, "UTF8");
}
/**
* Функция для проверки правильности работі класса
*/
public static void main(String[] s) throws IllegalBlockSizeException, BadPaddingException, IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException{
SecretKey key=null;
key = KeyGenerator.getInstance("DES").generateKey();
DesEncrypter encrypter = new DesEncrypter(key);
String OStr1="simple string";
String SStr = encrypter.encrypt(OStr1);
String OStr2 = encrypter.decrypt(SStr);
System.out.println("Open String:"+OStr1+
"\nAfter encripting: "+SStr+"\nAfter decripting: "+OStr2);
}
}
Подключение к MySQL с помощью Jdbc
Для начала рассмотрим список того что нам надо:
1. MySQL сервер, причём он должен быть запущен.
2. JDBC connector для MySQL, можно скачать с оффициального сайта MySQL (dev.mysql.com ).
3. Собственно java sdk.
Итак, Вы скачали всё необходимое, приступаем к работе.
Мы не будем рассматривать процесс установки и настройки MySQL сервера, но для дальнейшей работы нам необходимо что - бы:
- MySQL сервер был запущен;
- сущестовал пользователь root без пароля (настройки по умолчанию);
- существовала база данных test.
Допустим всё указанное выполено, и переходим к настройкам jdbc. Сначала разархивируйте mysql драйвер например в каталог: "c:\mysql- JDBC-3.0.17\". (Во время написания статьи была именно эта (3.0.17) версия jdbc драйвера, у Вас может быть более новая.)
В корне архива лежит файл: "c:\mysql-JDBC-3.0.17\mysql-connector-java-3.0.17-ga-bin.jar" , дальнейшая работа будет производиться именно с ним.
Создадим тестовый пример:
Немного объяснений.
String userName = "root";
String password = "";
имя пользователя в СУБД MySQL и его пароль. Этого пользователя создавать не надо, он существует в MySQL при установке.
String url = "jdbc:mysql://localhost/test";
Строка, подключения к бд, тут указывается что у нас локальный сервер MySQL (localhost) и база данных называется test.
Class.forName ("com.mysql.jdbc.Driver").newInstance ();
Инициализация драйвера jdbc для работы с MySQL.
В функию соеденения с бд getConnection() мы передаём все эти 3 параметра, и подключаемся к БД.
Замечание. Можно было не использовать отдельно имя пользователя и пароль, а создать строку подключение к БД следующего характера:
String url = "jdbc:mysql://localhost/[DB_Name]?user=[UserName]&password=[Password]";
Тогда функция соеденения с БД getConnection получала только один параметр, строку подключения.
conn.close ();
После завершения работы отключаемся от БД.
Замечание! Это всего лишь тестовый пример для того, что-бы научится подключать jdbc, в дальнейшем рекомендуется создать отдельный класс или покрайне мере функцию, которая будет получать как параметр настройки соеденения, и возвращать экземпляр класса Connection.
Компилируем и запускаем.
Не забываем, что для запуска необходимо подключить библиотеку mysql-connector-java-[version]-ga-bin.jar, или прописать её в переменную classpath, если вы не используете IDE.
1. MySQL сервер, причём он должен быть запущен.
2. JDBC connector для MySQL, можно скачать с оффициального сайта MySQL (dev.mysql.com ).
3. Собственно java sdk.
Итак, Вы скачали всё необходимое, приступаем к работе.
Мы не будем рассматривать процесс установки и настройки MySQL сервера, но для дальнейшей работы нам необходимо что - бы:
- MySQL сервер был запущен;
- сущестовал пользователь root без пароля (настройки по умолчанию);
- существовала база данных test.
Допустим всё указанное выполено, и переходим к настройкам jdbc. Сначала разархивируйте mysql драйвер например в каталог: "c:\mysql- JDBC-3.0.17\". (Во время написания статьи была именно эта (3.0.17) версия jdbc драйвера, у Вас может быть более новая.)
В корне архива лежит файл: "c:\mysql-JDBC-3.0.17\mysql-connector
Создадим тестовый пример:
/* файл Connect.java */
import java.io.*;
import java.sql.*;
public class Connect
{
public static void main (String[] args)
{
Connection conn = null;
try
{
String userName = "root";
String password = "";
String url = "jdbc:mysql://localhost/test";
Class.forName ("com.mysql.jdbc.Driver").newInstance ();
conn = DriverManager.getConnection (url, userName, password);
System.out.println ("Database connection established");
}
catch (Exception e)
{
System.err.println ("Cannot connect to database server");
e.printStackTrace();
}
finally
{
if (conn != null)
{
try
{
conn.close ();
System.out.println ("Database connection terminated");
}
catch (Exception e) { }
}
}
}
}
/*конец файла*/
Немного объяснений.
String userName = "root";
String password = "";
имя пользователя в СУБД MySQL и его пароль. Этого пользователя создавать не надо, он существует в MySQL при установке.
String url = "jdbc:mysql://localhost/test";
Строка, подключения к бд, тут указывается что у нас локальный сервер MySQL (localhost) и база данных называется test.
Class.forName ("com.mysql.jdbc.Driver").newInstance ();
Инициализация драйвера jdbc для работы с MySQL.
В функию соеденения с бд getConnection() мы передаём все эти 3 параметра, и подключаемся к БД.
Замечание. Можно было не использовать отдельно имя пользователя и пароль, а создать строку подключение к БД следующего характера:
String url = "jdbc:mysql://localhost/[DB
Тогда функция соеденения с БД getConnection получала только один параметр, строку подключения.
conn.close ();
После завершения работы отключаемся от БД.
Замечание! Это всего лишь тестовый пример для того, что-бы научится подключать jdbc, в дальнейшем рекомендуется создать отдельный класс или покрайне мере функцию, которая будет получать как параметр настройки соеденения, и возвращать экземпляр класса Connection.
Компилируем и запускаем.
Не забываем, что для запуска необходимо подключить библиотеку mysql-connector-java-[version]-ga-bin.jar, или прописать её в переменную classpath, если вы не используете IDE.
Сокеты
Сокеты позволяют реализовать клиент серверную архитектуру клиент - сервер.
Клиент, подключается к определённому порту сервера зная его имя или IP адрес. Большинство сетевых программ построенны именно на этой архитектуре. Рассмотрим как это реализуется в Java с помощью сокетов.
Итак, начнём с рассмотрения создания сокет сервера. Его основная задача: принимать входящие соеденения на какой то зарание определённый порт. Это реализуется с помощью класса java.net.ServerSocket. Следующий кусок кода отвечает за открытие порта №5000 на текущем компьютере (сервере) и приёме входящих подключений к серверу и создание экземпляра класса java.net.Socket для дальнейшей работы с подключённым клиентом.
try {
int port = 5000;
ServerSocket srv = new ServerSocket(port);
Socket socket = srv.accept();
} catch (IOException e) { }
Ну что ж сервер мы написали, следующий этап - написание клиента - программы которая будет подключатся к серверу. Номер порта сервера нам известен - №5000, в учебных целях клиент и сервер будем запускать на одном компьютере, тогда в качестве имени хоста можна использовать ключевое слово : localhost или IP адрес 127.0.0.1
try {
InetAddress addr = InetAddress.getByName("localhost");
int port = 5000;
Socket socket = new Socket(addr, port);
} catch (UnknownHostException e) {
} catch (IOException e) { }
Итак, на клиенте мы просто создаём новый сокет с указанными параметрами, если в момент запуска клиента сервер уже будет работать, значит подключение пройдёт успешно, без генерации исключений и мы сможем отправлять и получать данные.
В итоге мы имеем два работающих Socket, один на программе - сервере, второй на программе - клиенте. Реализуем возможность клиентом отправлять на сервер некую строку данных , а серверу получать её, обрабатывать и выводить в консоль, тогда на сервере надо создать экземпляр класса java.io.BufferedReader :
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str;
while ((str = rd.readLine()) != null) {
System.out.println(str);
}
rd.close ();
} catch (IOException e) { }
который прослушивает сокет и выводит на экран текст из потока ввода, до тех пор, пока из потока ввода поступают данные. На клиенте мы создадим экземпляр класса java.io.BufferedWriter, который будет передавать полученный текст в сокет:
try {
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
wr.write("Hello server");
wr.flush();
} catch (IOException e) {
}
В результате мы получили примитивное но вполне рабочее клиент - серверное приложение, которое способно обмениватся данными.
Клиент, подключается к определённому порту сервера зная его имя или IP адрес. Большинство сетевых программ построенны именно на этой архитектуре. Рассмотрим как это реализуется в Java с помощью сокетов.
Итак, начнём с рассмотрения создания сокет сервера. Его основная задача: принимать входящие соеденения на какой то зарание определённый порт. Это реализуется с помощью класса java.net.ServerSocket. Следующий кусок кода отвечает за открытие порта №5000 на текущем компьютере (сервере) и приёме входящих подключений к серверу и создание экземпляра класса java.net.Socket для дальнейшей работы с подключённым клиентом.
try {
int port = 5000;
ServerSocket srv = new ServerSocket(port);
Socket socket = srv.accept();
} catch (IOException e) { }
Ну что ж сервер мы написали, следующий этап - написание клиента - программы которая будет подключатся к серверу. Номер порта сервера нам известен - №5000, в учебных целях клиент и сервер будем запускать на одном компьютере, тогда в качестве имени хоста можна использовать ключевое слово : localhost или IP адрес 127.0.0.1
try {
InetAddress addr = InetAddress.getByName("localhost");
int port = 5000;
Socket socket = new Socket(addr, port);
} catch (UnknownHostException e) {
} catch (IOException e) { }
Итак, на клиенте мы просто создаём новый сокет с указанными параметрами, если в момент запуска клиента сервер уже будет работать, значит подключение пройдёт успешно, без генерации исключений и мы сможем отправлять и получать данные.
В итоге мы имеем два работающих Socket, один на программе - сервере, второй на программе - клиенте. Реализуем возможность клиентом отправлять на сервер некую строку данных , а серверу получать её, обрабатывать и выводить в консоль, тогда на сервере надо создать экземпляр класса java.io.BufferedReader :
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str;
while ((str = rd.readLine()) != null) {
System.out.println(str);
}
rd.close ();
} catch (IOException e) { }
который прослушивает сокет и выводит на экран текст из потока ввода, до тех пор, пока из потока ввода поступают данные. На клиенте мы создадим экземпляр класса java.io.BufferedWriter, который будет передавать полученный текст в сокет:
try {
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
wr.write("Hello server");
wr.flush();
} catch (IOException e) {
}
В результате мы получили примитивное но вполне рабочее клиент - серверное приложение, которое способно обмениватся данными.
Подписаться на:
Сообщения (Atom)