Четвертая статья серии. В ней мы используя наш каркас приложения который мы создали на втором уроке продолжим изучение технологии Java EE. Познакомимся с дескриптором развертывания web.xml, уменьшим количество повторяемого кода в jsp страницах путем использования jsp сегментов. Далее мы создадим наш первый сервлет, который будет играть роль контроллера, и обработаем наш первый запрос с клиента.
1Повторю еще раз, что для работы нам понадобится каркас приложения созданный на втором уроке.
Перемещение JSP страниц в WEB-INF
Сейчас в нашем проекте имеется три jsp страницы: index.jsp, article.jsp, registration.jsp. Сейчас доступ к каждой странице можно получить просто набрав путь к ней: localhost:8080/myblog/article.jsp. Что-бы исправить этот недостаток необходимо переложить все jsp файлы внутрь папки WEB-INF. Доступ к этой папке из браузера невозможен, вызов localhost:8080/WEB-INF/... приведет лишь к ошибке 404.
Папка WEB-INF была создана намерено что-бы разграничить файлы классов и библиотеки классов используемые приложением от остальных html, jpg и прочих файлов, к которых пользователь должен иметь прямой доступ по протоколу http.
Создадим в папке WEB-INF новую папку "views".
Во вновь созданную папку необходимо переместить файлы article.jsp и registration.jsp. Файл index.jsp перемещать не нужно. Он входной файл приложения. В результате проделанных действий, менеджер проектов должен выглядеть следующим образом:
Теперь прямой доступ к перемещенным файлам невозможен. Что-бы перенаправить вывод на эти файлы необходимо использовать сервлет. Им мы займемся чуть позже. А пока познакомимся с дескриптором развертывания.
Создание дескриптора развертывания и jsp сегментов
Пришло время создать дескриптор развертывания приложения.
Дескриптор развертывания - это файл xml файл, который описывает настройки развертывания компонента на сервере. JavaEE приложение и каждый его модуль содержит свой собственный дескриптор. Поскольку информация в дескрипторе объявляется декларативно, она может быть изменена без вмешательства в исходный код. Сервер JavaEE действует согласно считанному дескриптору развертывания.
Нажмите на кнопку "Создать файл..." и в категории "Веб" выберите тип файла "Стандартный дескриптер развертывания".
После нажмите кнопку "Готово".
В папке WEB-INF создался новый файл web.xml.
Можете открыть и посмотреть его содержимое. В данный момент там лишь указывается время работы сессии.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/
javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
Теперь давайте взглянем на наши jsp файлы. Во всех имеется повторяющаяся часть кода: голова (header) и подвал (footer). Т.к. эти части повторяются из документа в документ, то было бы логично вынести их в отдельный файл и не загромождать код. Сделаем это.
Создайте новую папку с именем jspf в папке WEB-INF. Теперь создайте новый jsp сегмент. В окне выбора типа файла выберите "jsp", далее введите название файла header и поставьте галочку в поле "Создать в виде сегмента jsp".
Тем-же способом создайте файл footer.jspf.
В файл header.jspf необходимо скопировать код из jsp страниц вплоть до тега </header>.
<%@ page pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/style.css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Мой блог</title>
</head>
<body>
<header>
<a href="/"><img alt="Логотип" id="top-image" src="#"/></a>
<div id="user-panel">
<a href="#"><img alt="Иконка юзера" scr=""/></a>
<a href="javascript:void(0);">[Панель для юзера]</a>
</div>
</header>
Во всех jsp файлов этот кусок кудок необходимо удалить.
В файл footer.jspf переносим код от тега <footer>
<%@ page pageEncoding="UTF-8" %>
<footer>
<div>
<span>Тестовое приложение JAVA EE</span>
<span><a target="_blanc" href="http://onedeveloper.ru/search?w=Java">Уроки по JavaEE</a></span>
</div>
</footer>
</body>
</html>
и так же удалить этот кусок кода из всех jsp страниц.
Отлично, мы создали jsp сегменты для нашего сайта. Теперь необходимо указать в какие страницы нужно вставлять верхний и нижний колонтитулы. Это можно сделать путем вствки тега <jsp:include> в jsp файлы. Однако это не решает проблему повторяемости кода. Для этой задачи можно использовать дескриптор развертывания.
Откройте файл дескриптора развертывания web.xml и перейдите на вкладку "Страницы". В ней добавте новую группу свойств. В шаблоне адресов нужно указать файлы к которым будет применяться правила, в нашем случае это index.jsp, article.jsp и registration.jsp. Поэтому поле шаблонов адресов укажите:
/WEB-INF/views/*, /index.jsp
так же можете добавить описание правил.
Далее выберите файлы для вводной и заключительной части (header.jspf и footer.jspf соответственно). В итоге, вкладка "Страницы" должна выглядеть следующим образом:
Сохранив и запустив проект вы увидите что разметка осталась прежней, значит мы все сделали правильно.
Создание servlet'a
Сервлет - java интерфейс необходимый для расширения функционала веб-сервера. Именно сервлеты принимают и обрабатывают запросы поступившие от пользователя, на основе их решает как поступить дальше и какой ответ дать пользователю. Для разных запросов пользователя можно назначить свой сервлет.
Будем рассматривать сервлеты версии 3.0 (самая последняя на момент написания статьи), в ней активно используется понятие аннотация, благодаря чему работа с сервлетами становится весьма проста.
1К одному и тому же запросу пользователя можно привязать не более одного сервлета.
Как мы говорили ранее, сервлет у нас будет играть роль контроллера. Он будет принимать запросы пользователей, на их основе выбирать тот или иной бизнес-метод, вызывать необходимый view и передавать нужные параметры.
Что-бы создать контроллер нажмите на кнопку создания нового файла , и списке типа файла выберите "Сервлет". Введите имя сервлета "web_controller" и имя пакета "Controller".
Нажмите "Готово".
Среда разработки создала готовый каркас сервлета. В нем объявлены методы doGet и doPost которые обрабатывают GET и POST запросы с клиента соответственно. Эти методы получают два параметра:
HttpServletRequest request;
HttpServletResponse response;
Request содержит информацию полученную от пользователя, Response содержит информацию которая будет передана пользователю.
IDE объединила оба метода в один - processRequest и ему передаются оба параметра. Если важно различать методы doGet и doPost, то реализацию их обработчика нужно писать прямо в них. Нам вполне сойдет и processRequest.
Что-бы зарегистрировать сервлет на сервере используется аннотация вида @WebServlet. В данный момент в ней указана имя сервлета и адреса вызовов которые будет обрабатывать сервлет. Давайте поправим поле urlPatterns так, что-бы оно указывало необходимые нам пути. Замените строку объявления сервлета на следующею:
@WebServlet(name = "web_controller", urlPatterns = {"/article", "/registration"})
Теперь каждый запрос пользователя произведенный по адресу ../article или ../registration будет обрабатывать данный сервлет.
Обработаем данные запросы в сервлете. Будем вызывать соответствующие представления в ответ на данные запросы пользователей.
Добавьте в тело функции processRequest следующею строку:
String userPath=request.getServletPath();
Метод getServletPath() возвращает путь по которому обратился пользователь.
Далее впишите:
if ("/article".equals(userPath)){
// TODO: обработка запроса статьи
}else
if ("/registration".equals(userPath)){
//TODO: обработка запроса регистрации
}
Это заготовка для обработчика. В заключение добавьте следующий строку:
request.getRequestDispatcher("/WEB-INF/views"+userPath+".jsp").forward(request, response);
Методом getRequestDispather вызываем необходимое нам представление (jsp страницу) и передаем ей параметры запроса и ответа.
Теперь набрав в строке адреса браузера http://localhost:8080/myblog/article мы попадем на страницу статьи, а набрав http://localhost:8080/myblog/registration на страницу регистрации. Тем самым мы наглядно убедились что наш сервлет обработал эти два запроса и перенаправил нас на нужные страницы.
Полный код контроллера приведен ниже:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package controller;
import com.sun.org.apache.bcel.internal.generic.GOTO;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author Egorov A.
*/
@WebServlet(name = "web_controller", urlPatterns = {"/article", "/registration"})
public class web_controller extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String userPath=request.getServletPath();
if ("/article".equals(userPath)){
// TODO: обработка запроса статьи
}else
if ("/registration".equals(userPath)){
//TODO: обработка запроса регистрации
}
request.getRequestDispatcher("/WEB-INF/views"+userPath+".jsp").forward(request, response);
}
/**
* Handles the HTTP
* <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP
* <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
Создание базы данных решил перенести в следующию статью т.к. она несколько выбивается из тематики, да и без того уже объемный материал получился.
И так, в этой статье мы познакомились с дескрипетером развертывания, создали колонтилу для верхней и нижней части страниц использую jsp сегменты и web.xml. Также мы создали полноцено работающий сервлет и даже обработали запросы пользователя.
Следующая статья будет посвещена работе приложения с базой данных. Для начал мы ее создадим, затем использую панель управления сервером (с ней мы тоже познакомимся) настроим пуллы соединений.
Комментарии
Спасибо за статью, подправьте орфографию, пожалуйста. А именно: "что-бы", "колонтилу", "для начал".
Может, нужно добавить ссылки на предыдущую/следующую статью? Я менял в адресе значение id, так и перемещался со страницы на страницу.
Страница не открывалась пока в web.xml не прописал mapping