Логин:   Пароль:






Новости
Рассылки
Форум
Поиск


Java
- Апплеты
- Вопрос-ответ
- Классы
- Примеры
- Руководства
- Статьи
- IDE
- Словарь терминов
- Скачать

Мобильная Java
- Игры
- Примеры
- Статьи
- WAP, WML и пр.

JavaScript
- Вопрос-ответ
- Примеры
- Статьи

Веб-мастеринг
- HTML
- CSS
- SSI

Разминка для ума
Проекты
Книги
Ссылки
Программы
Юмор :)




Rambler's Top100
Rambler's Top100

Java: СтатьиЭффективный способ обработки JSP с помощью JavaBeans

Эффективный способ обработки JSP с помощью JavaBeans

Очередная версия концепции технологии JavaServer Pages Model II уже получила достаточно широкую известность среди сообщества JSP-разработчиков. Основная идея данной концепции заключается в том, чтобы визуальное представление (HTML) было отделено от программного кода, выполняющего обработку. В данной статье предлагается рассмотреть удобный способ перемещения динамичного содержания, обработки и системы валидации из самой страницы JavaServer Page в соответствующий компонент JavaBean. Данная методика предполагает использование проектной модели Template Method Design Pattern, позволяющей реализовывать и многократно использовать стандартное поведение и дизайн JSP в пределах всего Web-приложения. Кроме того, такая модель обеспечивает простой механизм коммуникации между винами в рамках одной HTTP-сессии.

Содержание

Технология JavaServer Pages (JSP) предлагает широкий выбор средств, облегчающих создание Web-приложений. Тем не менее, при использовании этих средств без предварительного планирования и структуры ваш код может незаметно для вас превратиться в смесь меток HTML, JSP и Java-кода, которую будет очень сложно анализировать, отлаживать и в последствии сопровождать. Задача, таким образом, заключается в том, чтобы изолировать код JSP, который очень похож на HTML, переместив рабочий код в компоненты JavaBeans. Преимущество такого подхода заключается в том, что HTML-программист или графический дизайнер могут заниматься разработкой визуальной части (с помощью многочисленных HTML-редакторов), в то время как вы - Java-программист - будете заниматься логикой приложения. Кроме того, такой подход позволит вам легко изменять "look and feel" одного и того же Web-приложения.

Предлагаемая мной модель "Template Method Design Рattern" позволяет применять одинаковый дизайн для всего приложения и реализовывать одинаковое поведение в каждой из JSP. В понятие поведения включены управление состоянием страницы, одинаковая обработка страницы и возникающих ошибок и механизм предоставления данных для совместного использования несколькими страницами. Это всё определяется только один раз, оставляя вам только необходимость заниматься специфическими особенностями конкретной страницы.

В качестве примера использования этой модели я покажу простое приложение для голосования. Было бы неплохо, если бы вы владели основами JSP и Java, и не помешали бы кое-какие знания UML.

Обзор статической структуры

В этом разделе приводится описание основных действующих элементов модели, а также образец приложения для голосования.

Центральный элемент данной оболочки состоит из двух стандартных файлов для включения JSP (JSP include file) и двух классов, описываемых далее. Их роль заключается в том, чтобы представлять стандартное поведение:

  • includeheader.jsp : Включать JSP-файл, который должен статично вноситься в начало каждой JSP.
  • includefooter.jsp : Включать JSP-файл, который должен статично вноситься в конец каждой JSP.
  • AbstractJSPBean: Абстрактный класс, который вы должны будете использовать в качестве прототипа (super type) всех классов JavaBean для JSP. Это основной класс нашей модели.
  • SharedSessionBean : Используется для обеспечения связей между всеми JavaBean-объектами JSP в рамках одной HTTP-сессии.

Назначение Web-страницы JSP заключается в представлении данных. Каждая JSP должна иметь соответствующий компонент JavaBean, выполняющий специфическую для данной страницы логику. Каждая страница JSP должна статично включать в себя includeheader.jsp и includefooter.jsp. Каждый JavaBean должен расширять AbstractJSPBean, содержащий шаблонные методы, обеспечивающие стандартное поведение.

Приложение для голосования состоит из следующих JS-страниц и соответствующих им JavaBean-компонентов:

  • login.jsp, LoginJSPBean : Аутентификация и log для голосования 
  • vote.jsp, VoteJSPBean : Выполнение голосования 
  • confirmation.jsp, ConfirmationJSPBean: Показ подтверждения и результатов голосованияface="Arial Cyr">

Мы не будем очень подробно рассматривать классы, которые эмулируют базу данных или бизнес-логику (Voter , Candidate и VoteDB), но они нужны для нашему примеру для нормальной работы. А теперь, поскольку внешнюю сторону я объяснил, давайте заглянем внутрь одной страницы JSP.

Пример JSP

Каждая страница должна придерживаться определённой структуры, чтобы соответствовать нашей модели.

Пример 1. login.jsp

 <% AbstractJSPBean _abstractJSPBean = _loginJSPBean; %>
<%@ include file="includeheader.jsp" %>

<html>
<head><title>Vote Login</title></head>
<body bgcolor="white">

<font size=4>
  Please enter your Voter ID and Password

</font>

<font size="3" color="Red">
  <jsp:getProperty name="_loginJSPBean" property="errorMsg"/>

</font>

<font size=3>
  <form method=post>
     Voter ID <input type=text name=voterId value=<jsp:getProperty
        name="_loginJSPBean" property="voterId"/>>

     Password <input type=password name=password value=<jsp:getProperty
        name="_loginJSPBean" property="password"/>>



     <input type=submit value="Login">
  </form>
</font>
</body>
</html>

<%@ include file="includefooter.jsp" %>

Структура JSP выглядит так: страница начинается несколькими утверждениями (JSP statement). Следующий за ними HTML-код никак не зависит от директив, утверждений, скриплетов и других элементов JSP. Единственным исключением являются директивы. Вам следует использовать только директивы для получения динамического содержания из бин-компонента. И наконец, страница заканчивается директивой включения (JSP include directive).

Рассмотрим некоторые из наиболее существенных утверждений JSP:

<jsp:useBean id="_loginJSPBean" class="lbm.examples.LoginJSPBean" scope="session"/>
<jsp:setProperty name="_loginJSPBean" property="*"/>

Показанный выше код устанавливает связь между JSP и соответствующим ей бин-компонентом. Второе утверждение имплицитно передаёт значения всех полей формы (хранящихся в виде параметров HTTP-запроса) соответствующим свойствам бин-компонента. Код использует установочные методы бина. Более детальное описание того, как это всё работает можно найти в работе Говинда Сешарди "Advanced form processing using JSP".

<% AbstractJSPBean _abstractJSPBean = _loginJSPBean; %>
<%@ include file="includeheader.jsp" %>

Первое утверждение позволит includeheader.jsp выполнить стандартную обработку. А includeheader.jsp статично включается во второе утверждение. Обратите внимание, что _loginJSPBean и _abstractJSPBean теперь ссылаются на один и тот же объект, но только через разные интерфейсы.

Пример 2. includeheader.js

 <%-- Set the SharedSessionBean --%>
<jsp:useBean id="_sharedSessionBean" class="lbm.jsputil.SharedSessionBean" scope="session"/>
<% _abstractJSPBean.setSharedSessionBean(_sharedSessionBean); %>

<%-- Set implicit Servlet objects --%>
<% _abstractJSPBean.setRequest(request); %>
<% _abstractJSPBean.setResponse(response); %>
<% _abstractJSPBean.setServlet(this); %>

<%-- Perform the processing associated with the JSP --%>
<% _abstractJSPBean.process(); %>

<%-- If getSkipPageOutput equals false, do not output the JSP page --%>
<% if (! _abstractJSPBean.getSkipPageOutput()) { %>


Класс includeheader.jsp является одним из ключевых элементов нашей модели. Поэтому он будет использоваться всеми JSP-страницами.

Первые два утверждения, используемые в Примере 2, позволяют бин-компонентам JSP (хоть и из разных страниц, но в пределах одной и той же HTTP-сессии) взаимодействовать друг с другом. В принципе, каждая JSP будет иметь два JavaBean-компонента, ассоциирующихся со специфическим для этой JSP JavaBean-компонентом (к примеру, LoginJSPBeanface="Courier New Cyr" ) и стандартным SharedSessionBean. Таким образом, SharedSessionBean будет использоваться как общий элемент для связи всех страниц.

Следующие три утверждения из includeheader.jsp имеют дело имплицитными объектами Servlet.

<% _abstractJSPBean.setRequest(request); %>
<% _abstractJSPBean.setResponse(response); %>
<% _abstractJSPBean.setServlet(this); %>

Спецификация JSP обеспечивает доступ к имплицитным объектам, являющимся частью спецификации Java Servlet. Объекты типа request , response и servlet очень часто используются для обработки страницы. Поэтому они передаются в бин-компонент JSP.

<% _abstractJSPBean.process(); %>


Это утверждение инициирует процесс обработки, связанный со страницей JSP. Как вы можете видеть, вы запускаете метод из абстрактного бин-компонента JSP, а не какого-то конкретного LoginJSPBean. Почему? В следующем разделе объясню.

Применение проектной модели Template Method Design Рattern

Основным рабочим элементом Template Method Design Рattern является AbstractJSPBean . Каждый отдельный JavaBean-компонент JSP должен расширять этот класс.

Пример 3. AbstractJSPBean.java

 package lbm.jsputil;

import java.util.*;
import javax.servlet.http.*;
import javax.servlet.*;

public abstract class AbstractJSPBean {

  /* constants used for _state */
  public static final int NEW = 0;
  public static final int FIRSTPASS = 1;
  public static final int PROC = 2;
  public static final int ERR = -1;

  private int _state; // current state
  private String _errorMsg; // current message that is being appended
                            // during validation  
                            // private boolean _skipPageOutput;
                            // should the page output be skipped

  private SharedSessionBean _sharedSessionBean; // used for associating the
                                                // JSP Bean with the HTTP
                                                // Session

  /* standard Servlet objects that need to be setup for each JSP Bean */
  protected HttpServletRequest _request;
  protected HttpServletResponse _response;
  protected Servlet _servlet;

  public AbstractJSPBean () {
     setState(NEW);
  }

  protected abstract void beanProcess() throws java.io.IOException;

  protected abstract void beanFirstPassProcess() throws java.io.IOException;

  protected abstract void beanFooterProcess() throws java.io.IOException;

  protected abstract String getJSPCode();

  public void process() throws java.io.IOException {
     setSkipPageOutput(false); // by default do not skip page output.    
                               //Specific bean process
                               // methods can override it.
     if (getState() == NEW) {
       setState(FIRSTPASS);
       beanFirstPassProcess();
     } else {
       resetErrorMsg();
       setState(PROC);
       beanProcess();
     }

     // validation that all common fields have been properly set by the  
     // application this is actually checking that the code has been  
     // written properly
     String l_err = "";
     if (_sharedSessionBean == null) l_err = l_err + "; SharedSessionBean
            must be set";
     if (_request == null) l_err = l_err + "; Request must be set";
     if (_response == null) l_err = l_err + "; Response must be set";
     if (_servlet == null) l_err = l_err + "; Servlet must be set";
     if (l_err != "") throw new IllegalStateException(l_err);
  }

  public void footerProcess() throws java.io.IOException {
     beanFooterProcess();
  }

  protected void addErrorMsg (String addErrorMsg) {
     if (_errorMsg == null) _errorMsg = addErrorMsg;
     else _errorMsg = _errorMsg + " <br>n" + addErrorMsg;

     setState(ERR);
  }
  protected void resetErrorMsg () {
     _errorMsg = null;
  }
  public String getErrorMsg () {
     if (_errorMsg == null) return "";
     else return _errorMsg;
  }

  protected void setState (int newState) {
     _state = newState;
  }
  public int getState () {
     return _state;
  }

  public void setSharedSessionBean (SharedSessionBean newSharedSessionBean) {
     if (_sharedSessionBean == null) {
       _sharedSessionBean = newSharedSessionBean;
       _sharedSessionBean.putJSPBean(getJSPCode(), this);
     } else {
       if (_sharedSessionBean != newSharedSessionBean) {
         throw new IllegalStateException("SharedSessionBean is not set    
                properly. SharedSessionBean must be the same for all  
                  PageBeans within the session");
       }
     }
  }
  public SharedSessionBean getSharedSessionBean () {
     return _sharedSessionBean;
  }

  public void setSkipPageOutput (boolean newSipPageOutput) {
     _skipPageOutput = newSipPageOutput;
  }
  public boolean getSkipPageOutput () {
     return _skipPageOutput;
  }

  protected void redirect (String redirectURL) throws java.io.IOException {
     // skip the page output since we are redirecting
     setSkipPageOutput(true);
     _response.sendRedirect(redirectURL);
  }

  public void setRequest (HttpServletRequest newRequest) {
     _request = newRequest;
  }
  public void setResponse (HttpServletResponse newResponse) {
     _response = newResponse;
  }
  public void setServlet (Servlet newServlet) {
     _servlet = newServlet;
  }
}

AbstractJSPBean содержит следующие абстрактные методы: beanFirstPassProcess(), beanProcess() и beanFooterProcess(). Эти методы названы примитивными методами (primitive method). Это просто дежурные методы, которые должны быть реализованы в конкретных подклассах JavaBean-компонентов JSP. Каждый из них расширяется в процессе выполнения конкретной фазы обработки JSP.

  • beanFirstPassProcess() -- Обработка, выполняемая при первом обращении к странице, до того как появятся выходные данные. Он удобен для инициализации динамического содержания и подтверждения права доступа к странице. Вы можете посмотреть, как этот метод реализован в классе VoteJSPBean для подтверждения права доступа к странице и управления потоком данных в приложении. (См. Исходный код в разделе Дополнительные источники)
  • beanProcess() -- Обработка, выполняемая во время второго и последующих вызовов страницы, до того как появятся выходные данные. Его можно использовать, к примеру, для подтверждения правильности заполнения HTML-форм и обновления баз данных. Вы можете посмотреть, как этот метод реализован в классе LoginJSPBean  для выполнения обработки HTML-форм и в классе VoteJSPBean для сохранения информации в базе данных. (См. Исходный код в разделе Дополнительные источники)
  • beanFooterProcess() -- Обработка, выполняемая после того как представление выходных данных заканчивается. Вы можете использовать его для окончания или прерывания сессии. . Вы можете посмотреть, как этот метод реализован в классе ConfirmationJSPBean для прекращения сессии, после того как голосование закончилось и появилась страница с подтверждением. (См. Исходный код в разделе Дополнительные источники)

А теперь обратим внимание на метод process(), приведенный ниже:

   public void process() throws java.io.IOException {
     setSkipPageOutput(false); // by default do not skip page output.  
                               //Specific bean process
                               // methods can override it.
     if (getState() == NEW) {
       setState(FIRSTPASS);
    beanFirstPassProcess();
  } else {
    resetErrorMsg();
    setState(PROC);
    beanProcess();
  }
  ....

Сначала метод process() определяет состояние JSP, а затем, в зависимости от этого состояния, вызывает соответствующий примитивный метод. Он также устанавливает и нужное состояние JSP.

Методы process() и footerProcess() названы шаблонными методами (template method). Они вызываются непосредственно из JSP (из includeheader.jsp и includefooter.jsp ). Бин-компоненты не должны переопределять их функции. Шаблонные методы содержат стандартные структурные алгоритмы. Типичный алгоритм шаблонного метода отвечает за процесс обработки в нужные моменты времени вызывает примитивные (абстрактные) методы (beanFirstPassProcess() , beanProcess() и beanFooterProcess()), реализация которых зависит от конкретного JavaBean-компонента JSP. Структурные алгоритмы могут также вызывать и конкретные методы, реализованные в AbstractJSPBean. Все только что сказанное представляет собой сущность проектной модели Template Method Design Pattern.

Преимущества этого подхода заключаются в следующем:

  • Вы можете многократно использовать один и тот же код, заложив стандартное поведение в шаблонном методе.
  • Вы применяете одинаковый дизайн и поведение в пределах всего приложения.

Кроме логики обработки, AbstractJSPBean содержит следующие методы, помогающие подклассам (JavaBean-компонента конкретного JSP) реализовывать свои задачи в процессе обработки. Эти методы тоже нельзя переопределять.

  • Методы для обработки ошибок пользователя -- addErrorMsg() , resetErrorMsg() и getErrorMsg()
  • Методы для управления состоянием страницы -- setState() и getState()
  • Методы для управления связями с SharedSessionBean 
  • Методы, определяющие, выдавать ли получаемый результат в виде HTML как части JSP или нет -- setSkipPageOutput() и getSkipPageOutput()
  • Метод redirect
  • Методы доступа к объектам сервлета -- request , response и servlet

Обработка форм, динамическое содержание, взаимодействие bean-компонентов

В Примере 4 показан один из JavaBean-компонентов JSP, LoginJSPBean, который реализует специфический для страницы механизм обработки.

Пример 4. LoginJSPBean

 package lbm.examples;

import lbm.jsputil.*;
import java.util.*;

public class LoginJSPBean extends AbstractJSPBean {

  public static final String PAGE_CODE = "login";

     private String _voterId;
  private String _password;
  private Voter _voter = null;

  public LoginJSPBean() {
  }

  public void setVoterId (String newVoterId) {
     _voterId = newVoterId;
  }

  public String getVoterId() {
       if (_voterId == null) return "";
       else return _voterId;
  }

  public void setPassword (String newPassword) {
          _password = newPassword;
  }

  public String getPassword() {
       if (_password == null) return "";
       else return _password;
  }

  public Voter getVoter () {
     return _voter;
  }

       protected void beanProcess () throws java.io.IOException {
     if (_voterId == null || _voterId.equals("")) {
           addErrorMsg("Voter must be entered");
     }

     if (_password == null || _password.equals("")) {
           addErrorMsg("Password must be entered");
     }

     if (getState() != ERR) {
       //If all the fields are entered, try to login the voter
       Voter voter = VoteDB.login(_voterId, _password);
       if (voter == null) {
           addErrorMsg("Unable to authenticate the Voter. Please try
             again.");
       }
       else {
         _voter = voter;

         if (_voter.getVotedForCandidate() != null) {
            // if the voter has already voted, send the voter to the last  
            // page redirect("confirmation.jsp");
         }
         else {
            // go to the Vote page
            redirect("vote.jsp");
         }
       }
     }
  }

  protected void beanFirstPassProcess() throws java.io.IOException {
  }

  protected void beanFooterProcess() throws java.io.IOException {
  }

  protected String getJSPCode() {
     return PAGE_CODE;
  }
}

Обратите внимание на set- и get-методы класса LoginJSPBean. Как отмечалось ранее, они используются для обеспечения динамичного соответствия и для передачи значений между полями формы (параметры запросов) и свойствами бин-компонента.

Метод beanProcess(), показанный в том же Примере 4, иллюстрирует некоторые основные моменты обработки. Этот метод выполняется во время второго и последующих вызовов страницы, прежде чем начнёт выдаваться результат. Это означает, что он будет выполнен только после того, как пользователь нажмёт на кнопку Login и сработает соответствующее действие.

Сначала вы подтверждаете, что обязательные для ввода поля voterId и password заполнены. О любой обнаруженной ошибке тут же сообщается вызовом метода addErrorMsg . Этот метод устанавливает свойство errorMsg класса AbstractJSPBean, которое используется JSP для отображения ошибок пользователя:

<jsp:getProperty name="_loginJSPBean" property="errorMsg"/>

Если подтверждение правильности ввода данных проходит успешно, метод beanProcess() вызывает базу данных для подтверждения прав пользователя. И в конце он переадресует полученный ответ на соответствующую страницу, вызвав метод redirect(). Реализованный в классе AbstractJSPBean . >

А теперь давайте рассмотрим несколько методов из класса VoteJSPBean. Они проиллюстрируют другие аспекты нашей модели, такие как взаимодействие между JavaBean-компонентами JSP и управлением процессом выполнения приложения.

Пример 5. Метод beanFirstPassProcess() класса VoteJSPBean >

   protected void beanFirstPassProcess() throws java.io.IOException {
     // get the Voter from Login page
     _voter = null;

     LoginJSPBean loginJSPBean =
        (LoginJSPBean)  
          getSharedSessionBean().getJSPBean(LoginJSPBean.PAGE_CODE);

     if (loginJSPBean != null) {
        _voter = loginJSPBean.getVoter();
     }

     if (_voter == null) {
        // voter is not logged in yet. Send it to Login page
        setState(NEW);
        redirect("login.jsp");
     }
  }face="Courier New">

Показанный метод использует объект _sharedSessionBean класса AbstractJSPBean. Класс SharedSessionBean использует простой метод, обеспечивающий взаимодействие между всеми JavaBean-объектами JSP в рамках одной HTTP-сессии. Он хранит карту (Map) всех JavaBean-компонентов JSP в рамках одной сессии. Map является интерфейсом, соединяющим Java Collections framework, представленную в Java 1.2. Для тех знаком с Java 1.1, это очень сильно будет напоминать Hashtable. Ключом к JavaBean-компоненту JSP будет PAGE_CODE, который хранится в виде постоянной в каждом из классов JavaBean-компонентов JSP.

В этом примере метод beanFirstPassProcess() сначала определяет местонахождения объекта LoginJSPBean. Затем он достаёт объект Voter из объекта LoginJSPBean и сохраняет ссылку на него для последующего использования. Если Voter равен нулю, это значит, что пользователь попал на страницу голосования, не зарегистрировавшись вначале, и значит, будет переадресован на Login-страницу. Это простой пример управления процессом выполнения приложения. Можно создать и более сложные методы, использовать умные диспетчеры, но это выходит за рамки нашего обсуждения.

Пример 6. Метод getCandidateList() класса VoteJSPBea

   public String getCandidateList () {
     StringBuffer candidateList = new StringBuffer();
     Candidate candidate;

     Iterator candidates = VoteDB.getCandidates();
     while (candidates.hasNext()) {
        candidate = (Candidate) candidates.next();

        candidateList.append("<input type=radio
           name="candidateName" value="");
        candidateList.append(candidate.getName());
        candidateList.append(""> ");
        candidateList.append(candidate.getName());
        candidateList.append("<br>n");
     }

     return candidateList.toString();
  }

Метод getCandidateList(), показанный ниже, вызывается из с помощью следующего утверждения:

<jsp:getProperty name="_voteJSPBean" property="candidateList"

Задача метода заключается в том, чтобы обеспечивать содержание HTML на основе данных, получаемых из базы данных. Это требует от Java-программиста владеть знаниями в области HTML. В противном случае, вы можете обзавестись библиотекой утилит HTML, которые будут формировать HTML за вас. Утилиты могли бы брать уже заранее подготовленные типы входных данных, вроде Iterator, и выдавать полученный результат в виде заранее созданного формата. Ещё одним вариантом может быть использование библиотек меток (См. Дополнительные источники)

Дополнения: среда моделирования

Отделив друг от друга визуальную часть и логику, модель даёт вам возможность модифицировать и то (JSP) и другое (bean) независимо друг от друга. То есть вы можете изменять логику в бин-компонентах, даже не прикасаясь к JSP, при условии что свойства бинов (сигнатуры их методов доступа) останутся неизменными. То же самое относится и к коду JSP, что предоставляет полную свободу HTML-разработчикам и графическим дизайнерам в вопросе изменения внешнего вида сайта без необходимости залазить в Java-код.

Вы также можете модифицировать и ключевые компоненты самой модели, чтобы они отвечали требованиям конкретного приложения. Можно добавить новые вспомогательные или переделать имеющиеся шаблонные методы. Важно не забывать, что ваши JSP и JavaBean-компоненты должны согласовываться друг с другом в рамках всего приложения.

Такая среда моделирования может показаться в начале сложной, что в принципе справедливо, учитывая три страницы кода в качестве примера приложения. Тем не менее, когда вы сами начнёте писать своё приложение, вы заметите, как всё чётко укладывается на своё место, и что объём кода, который вы пишите, растёт значительнее медленнее, чем сложность вашего приложения.

Показанная здесь модель не относится к многоуровневым средам, обычно используемым в Web-приложениях. В принципе речь в данном случае идёт только об уровне визуального представления данных с помощью JSP. Для построения трёх- и более уровневых систем придётся использовать не только JavaBean-компоненты, но и Enterprise JavaBean-компоненты, к которым они будут обращаться, или другие варианты реализации бизнес-логики.

Мой пример иллюстрирует применение среды моделирования для приложений, отслеживающих работу HTTP-сессий. Тем не менее, эта модель будет прекрасно работать, даже если вы не захотите полагаться на сессии. И страницы приложения и порядок его работы должны моделироваться независимо друг от друга. Возможно, что SharedSessionBean вам не понадобится. Вполне возможно, что вам нужны будут отдельные страницы для представления данных и отдельные для обработки и подтверждения, а HTML будет не нужен. Для этих целей можно воспользоваться beanFirstPassProcess() методом.

Дополнения: пример

Я применил и протестировал пример с помощью Tomcat 3.1. Он совместим со спецификациями JSP 1.1 и Servlet 2.2. В этой статье не рассматривались особенности применения JSP и Tomcat (См. Дополнительные источники)
Ознакомьтесь с исходным кодом класса VoteDB, чтобы получить Voter Ids, которым вы сможете пользоваться для лога в процессе тестирования (пароли такие же, как и IDs). Чтобы пример правильно работал в браузере, нужно будет разрешить cookies. Если вы хотите, что бы приложение работало без них, понадобится переписать URL-адреса (с помощью метода encodeURL() из класса javax.servlet.http.HttpServletResponse ). Придётся переписывать все адреса в приложении, включая ссылки на ваши JSP, действия в метках форм и адреса, используемые для переадресации HTTP-ответов в JavaBean-компоненты JSP.

Заключение

Среда моделирования, предложенная в этой статье, представляет собой вполне доступное решение для проектирования JSP-приложений. Она позволяет неоднократно использовать созданный код, определяет архитектуру приложения и допускает возможность дальнейшего расширения. Одним из наиболее существенных преимуществ этой модели является возможность отделения логики от визуального представления для их независимого модифицирования.


Об авторе
Milan Adamovic является независимым консультантом и живёт и работает в Ванкувере, Британская Колумбия, Канада. В сферу его обязанностей входят системный анализ и проектирование, (объектно-ориентированный анализ и проектирование, UML, Oracle CASE, проектирование баз данных), программирование на Java для серверов (сервлеты, JSP, EJB), база данных Oracle и другие программные языки. Круг его интересов также включает Интернет-технологии, архитектуры Web-приложений, методология разработки программного обеспечения.


Warning: mysql_connect() [function.mysql-connect]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/books/show2b.php on line 11

Warning: mysql_db_query() [function.mysql-db-query]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/books/show2b.php on line 19

Warning: mysql_db_query() [function.mysql-db-query]: A link to the server could not be established in /pub/home/javaport/javaportal/books/show2b.php on line 19

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /pub/home/javaport/javaportal/books/show2b.php on line 30
Узнай о чем ты на самом деле сейчас думаешь тут.


[an error occurred while processing this directive]



Warning: mysql_connect() [function.mysql-connect]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/news/worldnews.php on line 91

Warning: mysql_db_query() [function.mysql-db-query]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/news/worldnews.php on line 93

Warning: mysql_db_query() [function.mysql-db-query]: A link to the server could not be established in /pub/home/javaport/javaportal/news/worldnews.php on line 93

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /pub/home/javaport/javaportal/news/worldnews.php on line 95