Java Servlets

Download Report

Transcript Java Servlets

Сървлети
Борислава Спасова
Java Web Developer
Acsior Ltd.
www.acsior.com
Светлин Наков
Национална академия по
разработка на софтуер
academy.devbg.org
Съдържание
1. Преглед на технологията на сървлетите
• Какво е сървлет?
• Услуги на сървлетите
• Защо да използваме сървлети?
• Time Servlet – Пример
• Разгръщане на сървлети с NetBeans IDE
2. Архитектура на сървлетите
• API интерфейсът на сървлетите
• Жизнен цикъл на сървлета
Съдържание (2)
3. Примерни сървлети
• Обработка на параметри – Hello Servlet
• Image Counter Servlet
4. Използване на сесии
• Какво е сесия?
• API интерфейсът за проследяване на
сесии
• Изтичане на сесия
Съдържание (3)
5. Примери със сесии
•
Login / Logout приложение
•
Проблеми с кеша на браузъра
Сървлети
Преглед на технологията
Какво е сървлет?
• Java сървлетите са:
• Технология за генериране на динамични уеб
страници (като PHP, ASP, ASP.NET, ...)
• Независими от платформата и протокола
сървърни компоненти, написани на Java,
които разширяват стандартните уеб сървъри
• Java програми, обработващи HTTP заявки
• Класът HttpServlet
• Предоставя динамично генериране на
съдържание (HTML, XML, …)
Какво е сървлет? (2)
• Сървлети
• Предоставят общ framework за услуги
базирани на модела заявка-отговор
• Преносими на всеки Java приложен
сървър
• Имат достъп до цялата фамилия от
Java и Java EE API интерфейси
• JDBC, Persistence, EJB, JMS, JAX-WS,
JTA, JTS, RMI, JNDI, JAXP, ...
• Основна част от всички Java web
application технологии (JSP, JSF, ...)
Услуги на сървлетите
• Сървлетите предоставят много полезни
услуги
• Предоставят API интерфейси от ниско
ниво за изграждане на интернет услуги
• Служат като основа за JavaServer Pages
(JSP) и JavaServer Faces (JSF)
технологиите
• Могат да предоставят разнообразни
типове данни за какъвто и да е клиент
• XML, HTML, WML, GIF и т.н.
• Могат да служат като “Controller” за
JSP/Servlet приложенията
Защо да използваме
сървлети?
• Преносими
• Пишем веднъж, изпълняваме ги
навсякъде
• Мощни
• Могат да се възползват от всички
предимства на Java платформата
• Елегантни
• Леснота дължаща се на абстракцията
• Ефективни и устойчиви
• Висока скалируемост
Защо да използваме
сървлети?
• Сигурност
• Силно типизирани
• Управление на паметта
• Интеграция
• Сървлетите са тясно свързани със сървъра
• Разширяемост и гъвкавост
• Сървлетите са проектирани да бъдат лесно
разширяеми, и в същото време
оптимизирани за работа с HTTP протокола
• Гъвкаво извикване на сървлети (SSI, servletchaining, филтри и т.н.)
Пример – Time Servlet
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class TimeServlet extends HttpServlet {
public void doGet(HttpServletRequest aRequest,
HttpServletResponse aResponse)
throws ServletException, IOException {
PrintWriter out = aResponse.getWriter();
out.println("<HTML>");
out.println("The time is: " +
new java.util.Date());
out.println("</HTML>");
}
}
Разгръщане на сървлети с
NetBeans IDE
• Създаваме ново Web приложение
Разгръщане на сървлети с
NetBeans IDE (2)
• Добавяме нов сървлет към Web
приложението
Разгръщане на сървлети с
NetBeans IDE (3)
• Изпълняваме сървлета
Разгръщане на сървлети с
NetBeans IDE (4)
• Сървлетът в действие
Time Servlet
Демонстрация
Сървлети
Архитектура
Архитектура на
сървлетите
• Класът HttpServlet
• Обслужва HTTP заявки от клиента
• За всеки от HTTP методите GET, POST и
други, е дефиниран съответен метод:
• doGet(…) – обработва HTTP GET заявки
• doPost(…) – обработва HTTP POST заявки
• doPut(…), doHead(…), doDelete(…),
doTrace(…), doOptions(…)
• Сървлетът обикновено предефинира един
от първите два метода или метода
service(…)
Архитектура на
сървлетите(2)
• Обектът HttpServletRequest
• Съдържа данните от заявката на клиента
• Заглавните части на HTTP заявката
• Данни от форми и параметри на заявката
• Други данни от клиента (бисквитки, път и
т.н.)
• Обектът HttpServletResponse
• Капсулира данни изпращани обратно на
клиента
• Заглавни части на HTTP отговора (content
type, бисквитки и други)
• Тяло на отговора (като OutputStream)
Архитектура на
сървлетите(3)
• HTTP GET методът се използва когато:
• Обработката на заявката не променя
състоянието на сървъра
• Количеството данни от формата е малко
• Искаме да позволим добавяне на заявката в
bookmarks
• HTTP POST методът се използва когато:
• Обработката на заявката променя
състоянието на сървъра, например запис на
данни в база данни
• Количеството данни от формата е голямо
• Съдържанието на данните не трябва да е е
видимо в URL-то (например пароли)
API интерфейсът на
сървлетите
• Най-важната функционалност на
сървлетите:
• Получаване на параметри от форми (GET
и POST параметри)
HttpServletRequest.getParameter(String)
• Получаване на инициализационни
параметри на сървлет
ServletConfig.getInitParameter()
• Получаване на информация за заглавната
част на заявка
HttpServletRequest.getHeader(String)
API интерфейсът на
сървлетите (2)
• Задаване на header / content type на HTTP
отговора
HttpServletResponse.setHeader(<name>, <value>) /
HttpServletResponse.setContentType(String)
• Получаване на текстов поток за отговора
HttpServletResponse.getWriter()
• Получаване на двоичен поток за отговора
HttpServletResponse.getOutputStream()
• Пренасочване на HTTP заявка към друг
URL
HttpServletResponse.sendRedirect()
Жизнен цикъл на сървлет
• Уеб контейнерът
управлява
жизнения цикъл
на инстанциите на
сървлетите
New
init()
Destroyed
Running
service()
destroy()
...()
• Методите от този doGet()
doDelete()
цикъл не трябва
doPost()
doPut()
да се извикват от
нашия код
• Можем да предефинираме тези методи в
класовете наследници на HttpServlet, за
да управляваме инстанцията на сървлета и
ресурсите, от които зависи
Методът init()
• Извиква се от уеб контейнера когато
сървлетът се създава за първи път
• Спецификацията на сървлетите
гарантира, че сървлетът няма да
обработва заявки преди завършването
на метода init().
• Предефинирайте метода init() когато:
• Трябва да създадете специфични за
сървлета ресурси, които са необходими
за обработка на потребителските заявки
• Имате нужда от инициализация на
състоянието на сървлета
Методът service()
• Извиква се от уеб контейнера, за да
обработи всяка потребителска заявка
• Извиква методите doGet(…),
doPost(…) и т.н. в зависимост от
метода на HTTP заявката (GET, POST и
т.н.)
• Изпраща резултата като отговор
• Обикновено няма нужда да
предефинираме този метод
Методът destroy()
• Извиква се от уеб контейнера когато се
премахва инстанцията на сървлета
• Спецификацията на сървлетите
гарантира, че всички заявки ще бъдат
обработени преди извикването на този
метод
• Предефинирайте метода destroy()
когато :
• Трябва да освободите специфични за
сървлета ресурси, които сте заделили в
метода init()
• Трябва да запазите състоянието на сървлета
Java сървлети
Примери
Обработка на параметри –
Hello Servlet
• Искаме да създадем сървлет, който
приема за параметър потребителско име
и казва "Hello, <потребителско_име>"
• Нуждаем се от HTML форма с текстово
поле
<form method="GET or POST" action="the servlet">
<input type="text" name="user_name">
</form>
• По късно сървлетът може да извлече
стойността въведена в полето
String name = request.getParameter("user_name");
Пример – Hello Servlet
HelloForm.html
<html><body>
<form method="GET" action="HelloServlet">
Please enter your name:
<input type="text" name="user_name">
<input type="submit" value="OK">
</form>
</body></html>
HelloServlet.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloServlet extends HttpServlet {
Пример – Hello Servlet
HelloServlet.java
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
ServletOutputStream out =
response.getOutputStream();
String userName =
request.getParameter("user_name");
out.println("<html><head>");
out.println("\t<title>Hello Servlet</title>");
out.println("</head><body>");
out.println("\t<h1>Hello, " + userName + "</h1>");
out.println("</body></html>");
}
Създаване на формата с
NetBeans IDE
• Създаване на нова HTML форма
Създаване на нов сървлет
с NetBeans IDE
• Създаване на нов сървлет
Hello Servlet в действие
Hello Servlet
Демонстрация
Hello Servlet –
HTTP Заявка
• Какво се случва когато потребителят
въведе името си?
• Internet Explorer (IE) изпраща следната HTTP
заявка към Tomcat
GET /FirstWebApp/HelloServlet?user_name=Nakov HTTP/1.1
Accept: image/gif, image/x-xbitmap,
image/jpeg,image/pjpeg, application/vnd.ms-excel,
application/vnd.ms-powerpoint, application/msword,
application/x-shockwave-flash, */*
Accept-Language: bg
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows
NT 5.1; Q312461)
Host: nakov:8084
Connection: Keep-Alive
Hello Servlet –
HTTP Отговор
• Какво се случва когато Tomcat получи и
обработи HTTP заявката
• Tomcat изпраща следния HTTP отговор към
Internet Explorer
HTTP/1.1 200 OK
Content-Length: 100
Date: Fri, 26 Mar 2006 10:06:28 GMT
Server: Apache-Coyote/1.1
<html><head>
<title>Hello Servlet</title>
</head><body>
<h1>Hello, Nakov</h1>
</body></html>
Image Counter Servlet
• Искаме да създадем сървлет, който
показва брояч във вид на изображение
(изображение в JPEG формат)
• Сървлетът трябва да поддържа
вътрешен брояч
• Можем да го инициализираме в метода
init()и да го увеличаваме в метода
doGet()
• Резултатът трябва да е изображение (в
JPEG формат)
• За стойност на content type трябва да
зададем "image/jpeg"
Image Counter Servlet (2)
import javax.servlet.*;
import javax.servlet.http.*;
...
public class ImageCounterServlet extends HttpServlet {
private String mStartDate;
private int mVisitCounter;
public void init() {
mStartDate = (new Date()).toString();
mVisitCounter = 0;
}
public BufferedImage createImage(String msg) {
...
}
Image Counter Servlet (3)
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
String msg;
synchronized(this) {
mVisitCounter++;
msg = "" + mVisitCounter + " visits since " +
mStartDate;
}
BufferedImage image = createImage(msg);
response.setContentType("image/jpeg");
OutputStream out = response.getOutputStream();
// Encode the image in JPEG format and
// write the image to the output stream
}
}
Image Counter Servlet в
действие
Image Counter Servlet
Демонстрация
Проследяване на
сесии
Какво е сесия?
• Сесията е състояние, свързано с определен
потребител, което се поддържа от страна
на сървъра
• Сесиите се запазват между HTTP заявките
• Сесиите ни позволяват да създаваме
приложения, които зависят от лични
потребителски данни. Например:
•
•
•
•
Login / logout функционалност
Wizard страници
Колички за пазаруване
Запазване на потребителски настройки
Проследяване на сесии в
сървлети
• Сървлетите предоставят вграден API
интерфейс за проследяване на сесии
• Сесиите се поддържат автоматично, без
писане на допълнителен код
• Уеб контейнерът асоциира уникален
HttpSession обект с всеки отделен
клиент
• Различните клиенти имат различни
сесийни обекти на сървъра
• Заявките от даден клиент имат един и
същ сесиен обект
• Сесиите могат да съхраняват данни
API интерфейсът за
проследяване на сесии
• . API интерфейсът позволява
• Получаване на HttpSession обект от
HTTPServletRequest обект
• Извличане на данни от сесийния обект
асоцииран с клиента
• Добавяне на данни към сесийния обект
асоцииран с клиента
• Извличане на мета информация за
сесийния обект като например кога е
създадена сесията
Получаване на сесиен
обект
• За да получим сесийния обект
използваме метода
HttpServletRequest.getSession()
• Например:
HttpSession session = request.getSession();
• Ако сесията вече е създадена, то се
връща съществуващата сесия
• Ако сесията не съществува, то се
създава и връща нова сесия
• Можем да проверим дали сесията е
нова като извикаме метода isNew()
Зад кулисите
• Когато извикаме getSession() с всеки
потребител автоматично се свързва
уникално Session ID
• Как това Session ID стига до потребителя?
• Вариант 1: Ако браузърът поддържа
бисквитки, сървлетът автоматично създава
бисквитка и запазва session ID в нея.
• В Tomcat, бисквитката се нарича JSESSIONID
• Вариант 2: Ако браузърът не поддържа
бисквитки, сървлетът ще опита да извлече
session ID от URL-то
Извличане на данни от
сесията
• Сесийният обект работи като HashMap
• Позволява съхранение на всякакъв тип Java
обекти
• Обектите се съхраняват по ключ (като в хеш
таблица)
• Извличане на съществуващ обект:
Integer accessCount =
(Integer)session.getAttribute("accessCount");
• Извличане на списък от всички “ключове”
асоциирани със сесията
Enumeration attributes =
request.getAttributeNames();
Запазване на данни в
сесията
• Можем да запазим данни в сесийния
обект и да ги използваме по-късно
HttpSession session = request.getSession();
session.setAttribute("name", "Svetlin Nakov");
• Можем да премахнем обекти от сесията,
ако повече не са ни нужни
session.removeAttribute("name");
Допълнителна
информация за сесията
• Получаване на идентификатора на сесията,
асоцииран с потребителя, напр. gj9xswvw9p
public String getId();
• Проверка дали сесията е току що създадена
public boolean isNew();
• Проверка кога е била създадена сесията
public long getCreationTime();
• Проверка кога последно е била активна
сесията
public long getLastAccessedTime();
Изтичане на сесия
• Можем да получим максималния интервал
на валидност на сесията (в секунди)
public int getMaxInactiveInterval();
• Сесията автоматично става невалидна,
когато времето между достъпите на клиента
надхвърли този интервал
• Можем да изменяме максималния интервал
на валидност
public void setMaxInactiveInterval (int seconds);
• Отрицателна стойност указва, че сесията
никога не изтича
Прекратяване на сесия
• За да прекратим сесията ръчно
използваме следния метод:
public void invalidate();
• Обикновено го правим при “изход на
потребителя"
• Сесията може да стане невалидна не
само при ръчното и прекратяване
• Сесиите могат да изтичат автоматично
поради липса на активност
Пример – Login / Logout
• Искаме да създадем просто уеб приложение,
което ограничава достъпа чрез форма за вход
• Ще използваме сесии, за да запазваме
информация за валидните потребители
• Ще използваме ключа "username"
• Ако го има, значи потребителят вече е влязъл
• При Login ще добавяме потребителското име в
сесията
• Logout ще прекратява сесията
• Main servlet ще проверява текущия потребител
Login Form
LoginForm.html
<html>
<head><title>Login</title></head>
<body>
<form method="POST" action="LoginServlet">
Please login:<br>
Username:
<input type="text" name="username"><br>
Password:
<input type="password" name="password"><br>
<input type="submit" value="Login">
</form>
</body>
</html>
Login Servlet
LoginServlet.java
public class LoginServlet extends HttpServlet {
public void doPost(HttpServletRequest req,
HttpServletResponse resp)
throws IOException, ServletException {
String username = req.getParameter("username");
String password = req.getParameter("password");
PrintWriter out = resp.getWriter();
if (isLoginValid(username, password)) {
HttpSession session = req.getSession();
session.setAttribute("USER", username);
response.sendRedirect("MainServlet");
} else {
response.sendRedirect("InvalidLogin.html");
}
}
}
Main Servlet
MainServlet.java
public class MainServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse resp)
throws ServletException, IOException {
HttpSession session = request.getSession();
String userName = (String)
session.getAttribute("USER");
if (userName != null) {
response.setContentType("text/html");
ServletOutputStream out = resp.getOutputStream();
out.println("<html><body><h1>");
out.println("Hello, " + userName + "! ");
out.println("</h1></body></html>");
} else {
response.sendRedirect("LoginForm.html");
}
}
}
Logout Servlet
LogoutServlet.java
public class LogoutServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
session.invalidate();
response.setContentType("text/html");
ServletOutputStream out =
response.getOutputStream();
out.println("<html><head>");
out.println("<title>Logout</title></head>");
out.println("<body>");
out.println("<h1>Logout successfull.</h1>");
out.println("</body></html>");
}
}
Invalid Login Page
InvalidLogin.html
<html>
<head>
<title>Error</title>
</head>
<body>
<h1>Invalid login!</h1>
Please <a href="LoginForm.html">try again</a>.
</body>
</html>
Проблеми с кеша на
браузъра
• Повечето браузъри кешират
показваните страници и изображения
• Това може да доведе до показване на
старо съдържание на страниците
• Изглежда като грешка в приложението
• Трябва да забраним кеширането, за да
предотвратим показването на старо
съдържание:
response.setHeader("Pragma", "No-cache");
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-cache");
Login / Logout
Демонстрация
Сървлети
Въпроси?
Упражнения
1. Създайте сървлет, който отпечатва в
таблица числата от 1 до 1000 и
техните квадратни корени.
2. Създайте сървлет, който приема като
параметри две цели числа и
изчислява сумата им.
Създайте HTML форма, извикваща
сървлета. Опитайте да използвате
методи GET и POST.
Упражнения (2)
3. Създайте сървлет, който играе
“Познай числото". Когато клиентът
извика сървлета за пръв път той
генерира произволно число в
интервала [1..100]. Потребителят
трябва да познае това число. При
всеки опит сървлетът изписва само
“по-голямо" или “по-малко". Играта
приключва, когато потребителят
познае числото.
Задачи за домашно
1. Създайте сървлет, който приема като
параметър число и го показва като
изображение, трудно за разпознаване от
OCR софтуер. Изображението трябва да
има умишлено въведени дефекти.
2. Създайте HTML форма и сървлет за
преобразуване на разстояния от едни
мерни единици в други. Да се поддържат
следните мерни единици: сантиметър,
метър, километър, фут, инч, ярд, миля.
1 см = 0.01 метра
1 фут = 0.3048 метра
1 ярд = 0.9144 метра
1 км = 1000 метра
1 инч = 0.0254 метра
1 миля = 1609.344 метра
Задачи за домашно (2)
3. Създайте последователност от HTML
форми и сървлети, позволяващи
въвеждане на информация за студент.
Информацията се въвежда на 3 стъпки в 3
отделни форми:
Стъпка 1: Име, фамилия, възраст
Стъпка 2: Адрес (държава, град, улица)
Стъпка 3: Университет, факултет,
специалност
Данните въведени в 3-те стъпки трябва да
се запазят в сесията и да се покажат
накрая.
4. Създайте сървлет, който чете изображение
(от WEB-INF\img\logo.gif) и го връща.