JAVA EE: Разработка web-приложения. View и Controller
Поиск по сайту:
О разработчеке сайта
Header image

Новые статьи и уроки JAVA

JAVA EE: Разработка web-приложения. View и Controller

Четвертая статья серии. В ней мы используя наш каркас приложения который мы создали на втором уроке продолжим изучение технологии Java EE. Познакомимся с дескриптором развертывания web.xml, уменьшим количество повторяемого кода в jsp страницах путем использования jsp сегментов. Далее мы создадим наш первый сервлет, который будет играть роль контроллера, и обработаем наш первый запрос с клиента.

1Готовый снимок урока можно забрать здесь https://github.com/TalismanFR/MyBlog/tree/article_4

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

так же можете добавить описание правил.

Создание группы правил 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. Также мы создали полноцено работающий сервлет и даже обработали запросы пользователя.

1Готовый снимок урока можно забрать здесь https://github.com/TalismanFR/MyBlog/tree/article_4

Следующая статья будет посвещена работе приложения с базой данных. Для начал мы ее создадим, затем использую панель управления сервером (с ней мы тоже познакомимся) настроим пуллы соединений.

14.08.2012

Комментарии

Спасибо за статью, подправьте орфографию, пожалуйста. А именно: "что-бы", "колонтилу", "для начал".

Может, нужно добавить ссылки на предыдущую/следующую статью? Я менял в адресе значение id, так и перемещался со страницы на страницу.

14.09.2016 Автор: Гость

Страница не открывалась пока в web.xml не прописал mapping

21.01.2017 Автор: Олег