Продвинутая обработка форм с использованием JSP
Гоувайнд Сишадри
Server-Side Java
Используйте паттерн дизайна Memento, используя JavaServer Pages и
JavaBeans.
Обзор Обработка форм HTML с использованием
servlets, или, более часто, скриптов CGI, одна из наиболее частых операций в
вебе. Однако, то что JavaServer Pages (JSPs) могут играть значительную роль в
изощренной обработке форм- мало известный секрет. В некоторых случаях, JSP
даже превышает возможности сервлетов и скриптов на Perl при обработке форм. В
этой статье Гоувайнд Сишадри обсуждает обработку регистрации пользователя
используя JSP и JavaBeans и реализует паттерн дизайна Memento. Эта статья
подразумевает, что читатель знаком с основами программирования JSP. (3000
слов)
Обработка HTML форм кажется легкой работой. Для простых форм так оно обычно и
есть. Однако, эта "легкая работа" (как может подтвердить любой, кому приходилось
писать достаточно изощренные веб-приложения) может быстро стать утомительной.
Это связано с тем, что обработка HTML форм включает значительно больше, чем
простой разбор параметров запроса и выдачу ответа клиенту. Обычно, обработка
форм включает работу множества фоновых компонет, где каждая компонента отвечает
за определенную дискретную задачу, такую как управление состоянием, проверка
данных, доступ к базе данных, и так далее. Существует масса примеров обработки
форм с использованием скриптов на Perl и сервлетов, однако JSP не привлекали
большого внимания для этой задачи. Для этого существуют определенные причины.
Даже если не учитывать то, что JSP достаточно новая технология, многие
рассматривают ее пригодность только для представления динамического содержания,
переданного из JavaBeans или сервлетов. Однако, как вы вскоре увидите,
комбинация JSP и JavaBeans достойна внимания при обработке HTML форм.
В этой статье я расскажу об обработке формы регистрации пользователя с
использованием JSP. Одна из основных особенностей програмирования JSP
заключается в делегировании как можно больше кода обработки компонетам JavaBean.
Мой JSP для обработки форм покажет некоторые интересные возможности. Он не
только предоставит простую проверку данных регистрационной информации
пользователя но и продемонстрирует поведение, независящее от состояния. Это
позволит заранее заполнить элементы формы проверенными данными пока пользователь
не заполнит правильно всю форму. Давайте рассмотрим наш пример.
Посмотрите на Листинг 1, который отображает регистрационную форму для
пользователя, показанную на Рисунке 1.
Листинг 1. register.html
<html>
<body>
<form action="/examples/jsp/forms/process.jsp" method=post>
<center>
<table cellpadding=4 cellspacing=2 border=0>
<th bgcolor="#CCCCFF" colspan=2>
<font size=5>USER REGISTRATION</font>
<font size=1>* Required Fields</font>
</th>
<tr bgcolor="#c8d8f8">
<td valign=top>
First Name*
<input type="text" name="firstName" value="" size=15 maxlength=20></td>
<td valign=top>
Last Name*
<input type="text" name="lastName" value="" size=15 maxlength=20></td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top>
E-Mail*
<input type="text" name="email" value="" size=25 maxlength=125>
</td>
<td valign=top>
Zip Code*
<input type="text" name="zip" value="" size=5 maxlength=5></td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top colspan=2>
User Name*
<input type="text" name="userName" size=10 value="" maxlength=10>
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top>
Password*
<input type="password" name="password1" size=10 value=""
maxlength=10></td>
<td valign=top>
Confirm Password*
<input type="password" name="password2" size=10 value=""
maxlength=10></td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top colspan=2>
What music are you interested in?
<input type="checkbox" name="faveMusic"
value="Rock">Rock
<input type="checkbox" name="faveMusic" value="Pop">Pop
<input type="checkbox" name="faveMusic" value="Bluegrass">Bluegrass
<input type="checkbox" name="faveMusic" value="Blues">Blues
<input type="checkbox" name="faveMusic" value="Jazz">Jazz
<input type="checkbox" name="faveMusic" value="Country">Country
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top colspan=2>
Would you like to receive e-mail notifications on our special
sales?
<input type="radio" name="notify" value="Yes" checked>Yes
<input type="radio" name="notify" value="No" > No
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td align=center colspan=2>
<input type="submit" value="Submit"> <input type="reset"
value="Reset">
</td>
</tr>
</table>
</center>
</form>
</body>
</html>
Рис. 1. Форма регистрации пользователя.
|
Форма в Листинге 1 совершенно стандартна. Она содержит все обычные элементы
ввода, включая текстовые поля, чекбоксы и кнопки. Однако, обратите внимание на
поле action:
<form action="/examples/jsp/forms/process.jsp" method=post>
Несмотря на то, что обычно вы указывали сервлет или скрипт на Perl, JSP также
прекрасно может справиться с обработкой данных из HTML форм. Вообще, это не
должно вас удивлять, потому-что что такое JSP, в конце-концов? Это всего лишь
высокоуровневая абстракция сервлетов. Следовательно, в большинстве случаев
вполне возможно написать JSP равнозначный сервлету.
Однако, вы должны всегда помнить, что технология JSP была создана для
совершенно другой цели, нежели быть заменителем (хотя иногда и более легким!)
написанию сервлетов. JSP нужен для облегчения разделения дизайна и динамического
содержания. Несмотря на то, что вы можете встроить любое количество Java-кода в
страницу JSP, все-таки лучше включить логику обработки в компоненты JavaBean.
Несмотря на это, по моему мнению, JSP вполне пригоден для создания страниц-
контроллеров. Такие страницы все-равно будут передавать большую часть
обработки в beans, но они будут содержать некоторую логику для ответа на
действия пользователя. Но такие страницы- контроллеры никогда не будут содержать
логику для представления элементов пользоваетльского интерфейса. Такие задачи
всегда будут выделены во внешние JSP- страницы, которые будут вызываться
контроллером, когда это необходимо.
Посмотрите на Листинг 2, который показывает страницу JSP, работающую как
контроллер.
Листинг 2. process.jsp
<%@ page import="java.util.*" %>
<%!
ResourceBundle bundle =null;
public void jspInit() {
bundle = ResourceBundle.getBundle("forms");
}
%>
<jsp:useBean id="formHandler" class="foo.FormBean" scope="request">
<jsp:setProperty name="formHandler" property="*"/>
</jsp:useBean>
<%
if (formHandler.validate()) {
%>
<jsp:forward page="<%=bundle.getString("process.success")%>"/>
<%
} else {
%>
<jsp:forward page="<%=bundle.getString("process.retry")%>"/>
<%
}
%>
Поскольку мы передаем основную часть обработки в JavaBeans, первое, что
контроллер должен сделать, это создать компонент bean. Это делается в тэге
<jsp:useBean> как показано:
<jsp:useBean id="formHandler" class="foo.FormBean" scope="request">
<jsp:setProperty name="formHandler" property="*"/>
</jsp:useBean>
Тэг <jsp:useBean> сначала ищет копию bean с определенным
именем и создает новую, если не может найти bean в определенной области. Здесь
атрибут области задает время жизни для bean. Новые beans получают область
страницы по-умолчанию, если не указано что-то другое. Заметьте, что в этом
случае я указал, что bean получает область запроса перед тем, как ответ
отсылается обратно клиенту, так как несколько страниц JSP участвуют в обработке
запроса от клиента.
Вас может смутить <jsp:setProperty> внутри тэга
<jsp:useBean>. Любой скриптлет или тэг
<jsp:setProperty> установленный внутри тэга
<jsp:useBean> выполняется только когда создается копия bean и
используется для инициализации свойств bean. Конечно, в этом случае я мог
написать тэг <jsp:setProperty> вне тэга
<jsp:useBean>. Разница между ними в том, что содержимое тела
не выполняется если bean получен из определенной области -- что спорно в нашем
случае, так как bean создается при каждом вызове контроллера.
Волшебство интроспекции Когда вы
разрабатываете beans для обработки данных из формы, вы можете следовать паттерну
дизайна, когда имена свойств bean соответствуют именам элементов ввода формы. Вы
также должны будете определить методы getter/setter для каждого свойства bean.
Например, в FormBean (показан на Листинге 3), я определил свойство
firstName и методы доступа getFirstName() и
setFirstName(), соответствующие элементу формы
firstName. Преимущество такого подхода в том, что вы теперь можете
направить JSP engine для разбора всех входящих значений из элементов формы HTML,
а потом назначить их соответствующим свойствам bean внутри единственной строчки
кода, как здесь:
<jsp:setProperty name="formHandler" property="*"/>
Такое волшебство во время исполнения программы возможно благодаря процессу,
называмому интроспекцией (introspection), который позволяет классу
отображать свои свойства по запросу. Интроспекция управляется JSP engine и
реализована с помощью механизма Java reflection. Эта особенность может
сэкономить массу времени при обработке форм с большим количеством элементов
ввода.
Листинг 3. FormBean.java
package foo;
import java.util.*;
public class FormBean {
private String firstName;
private String lastName;
private String email;
private String userName;
private String password1;
private String password2;
private String zip;
private String[] faveMusic;
private String notify;
private Hashtable errors;
public boolean validate() {
boolean allOk=true;
if (firstName.equals("")) {
errors.put("firstName","Please enter your first name");
firstName="";
allOk=false;
}
if (lastName.equals("")) {
errors.put("lastName","Please enter your last name");
lastName="";
allOk=false;
}
if (email.equals("") || (email.indexOf('@') == -1)) {
errors.put("email","Please enter a valid email address");
email="";
allOk=false;
}
if (userName.equals("")) {
errors.put("userName","Please enter a username");
userName="";
allOk=false;
}
if (password1.equals("") ) {
errors.put("password1","Please enter a valid password");
password1="";
allOk=false;
}
if (!password1.equals("") && (password2.equals("") ||
!password1.equals(password2))) {
errors.put("password2","Please confirm your password");
password2="";
allOk=false;
}
if (zip.equals("") || zip.length() !=5 ) {
errors.put("zip","Please enter a valid zip code");
zip="";
allOk=false;
} else {
try {
int x = Integer.parseInt(zip);
} catch (NumberFormatException e) {
errors.put("zip","Please enter a valid zip code");
zip="";
allOk=false;
}
}
return allOk;
}
public String getErrorMsg(String s) {
String errorMsg =(String)errors.get(s.trim());
return (errorMsg == null) ? "":errorMsg;
}
public FormBean() {
firstName="";
lastName="";
email="";
userName="";
password1="";
password2="";
zip="";
faveMusic = new String[] { "1" };
notify="";
errors = new Hashtable();
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
public String getUserName() {
return userName;
}
public String getPassword1() {
return password1;
}
public String getPassword2() {
return password2;
}
public String getZip() {
return zip;
}
public String getNotify() {
return notify;
}
public String[] getFaveMusic() {
return faveMusic;
}
public String isCbSelected(String s) {
boolean found=false;
if (!faveMusic[0].equals("1")) {
for (int i = 0; i < faveMusic.length; i++) {
if (faveMusic[i].equals(s)) {
found=true;
break;
}
}
if (found) return "checked";
}
return "";
}
public String isRbSelected(String s) {
return (notify.equals(s))? "checked" : "";
}
public void setFirstName(String fname) {
firstName =fname;
}
public void setLastName(String lname) {
lastName =lname;
}
public void setEmail(String eml) {
email=eml;
}
public void setUserName(String u) {
userName=u;
}
public void setPassword1(String p1) {
password1=p1;
}
public void setPassword2(String p2) {
password2=p2;
}
public void setZip(String z) {
zip=z;
}
public void setFaveMusic(String[] music) {
faveMusic=music;
}
public void setErrors(String key, String msg) {
errors.put(key,msg);
}
public void setNotify(String n) {
notify=n;
}
}
Свойства bean не обязательно должны соответствовать именам элементов ввода
формы, так как вы всегда можете перевести их самостоятельно, например:
<jsp:setProperty name="formHandler" param="formElementName"
property="beanPropName"/>
Вы можете легко создать соответствие между элементами формы, такими как
текстовые поля или кнопки и скалярными свойствами bean, такими как
String, однако вам придется использовать индексированные свойства,
такие как String[] для работы с чекбоксами (checkboxes). Несмотря
на это, как только вы создадите подходящий установочный метод (setter) вы можете
использовать JSP engine для установки значений даже нескалярных типов путем
автоматического разбора соответствующего элемента формы из запрашивающего
объекта.
Посмотрите на этот установочный метод, назначающий значения выделенных
чекбоксов:
public void setFaveMusic(String[] music) {
faveMusic=music;
}
Я также показывал простой прием для того, чтобы обойтись без жесткого задания
выходных ресурсов в контроллере. Здесь, выход задается во внешнем файле свойств,
forms.properties, как показано в Листинге 4. Этот файл может
находиться где угодно в пределах CLASSPATH, видимого для контейнера
JSP. Метод jspInit(), объявленный внутри страницы, автоматически
выполняется контейнером JSP, когда страница JSP (или, если быть более точным,
сервлет, представляющий эту страницу) загружается в память и вызывается только
один раз за все время существования JSP. Используя механизм
ResourceBundle, ваша страница может получать доступ к ресурсам по
имени, также как если бы вы использовали объект Hashtable.
Листинг 4. forms.properties
process.success=success.jsp
process.retry=retry.jsp
Обработка форм с использованием паттерна дизайна
Memento Обрабатывающая логика в пределах контроллера страницы
проста. После того, как bean создан, вызывается его метод
validate(). Метод validate() имеет двойной эффект.
Если ошибка встречается во время подтверждения правильности элементов ввода
формы, метод validate() не только возвращает значение
соответствующего свойства bean, но и устанавливает соответствующее сообщение об
ошибке, которое может быть позже отображено для данного элемента ввода.
Если любой из требуемых элементов формы не был успешно проверен, контроллер
пересылает запрос JSP-странице retry.jsp (см. Листинг 5), позволяя пользователю
сделать изменения и заново отправить форму. Если там нет ошибок, запрос
передается в success.jsp, показанной на Листинге 6.
В retry.jsp, вы сначала получаете ссылку на bean, который был предварительно
создан и размещен контроллером в запросе. Также, поскольку вы не хотите, чтобы
пользователь повторно вводил успешно проверенные данные, вы заполняете элементы
формы, считывая их предыдущие значения из bean, как показано ниже:
<input type="text" name="firstName"
value='<%=formHandler.getFirstName()%>' size=15 maxlength=20>
Любое сообщение об ошибке, которое относится к элементу ввода формы может
быть получено и отображено через:
<font size=2 color=red>
<%=formHandler.getErrorMsg("firstName")%>
</font>
Также обратите внимание на то, каким образом я восстановил предыдущее
состояние элементов ввода, таких как кнопки и чекбоксы, используя сервисные
методы isRbSelected(String s) и isCbSelected(String
s), которые были включены в bean. Рисунок 2 показывает форму, созданную с
помощью retry.jsp, которая показывает некоторые ошибки при проверке.
Листинг 5. retry.jsp
<jsp:useBean id="formHandler" class="foo.FormBean" scope="request"/>
<html>
<body>
<form action="process.jsp" method=post>
<center>
<table cellpadding=4 cellspacing=2 border=0>
<th bgcolor="#CCCCFF" colspan=2>
<font size=5>USER REGISTRATION</font>
<font size=1>* Required Fields </font>
</th>
<tr bgcolor="#c8d8f8">
<td valign=top>
First Name*
<input type="text" name="firstName"
value='<%=formHandler.getFirstName()%>' size=15 maxlength=20>
<font size=2
color=red><%=formHandler.getErrorMsg("firstName")%></font>
</td>
<td valign=top>
Last Name*
<input type="text" name="lastName"
value='<%=formHandler.getLastName()%>' size=15 maxlength=20>
<font size=2
color=red><%=formHandler.getErrorMsg("lastName")%></font>
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top>
E-Mail*
<input type="text" name="email" value='<%=formHandler.getEmail()%>'
size=25 maxlength=125>
<font size=2 color=red><%=formHandler.getErrorMsg("email")%></font>
</td>
<td valign=top>
Zip Code*
<input type="text" name="zip" value='<%=formHandler.getZip()%>' size=5
maxlength=5>
<font size=2 color=red><%=formHandler.getErrorMsg("zip")%></font>
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top colspan=2>
User Name*
<input type="text" name="userName" size=10
value='<%=formHandler.getUserName()%>' maxlength=10>
<font size=2
color=red><%=formHandler.getErrorMsg("userName")%></font>
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top>
Password*
<input type="password" name="password1" size=10
value='<%=formHandler.getPassword1()%>' maxlength=10>
<font size=2
color=red><%=formHandler.getErrorMsg("password1")%></font>
</td>
<td valign=top>
Confirm Password*
<input type="password" name="password2" size=10
value='<%=formHandler.getPassword2()%>' maxlength=10>
<font size=2
color=red><%=formHandler.getErrorMsg("password2")%></font>
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td colspan=2 valign=top>
What music are you interested in?
<input type="checkbox" name="faveMusic" value="Rock"
<%=formHandler.isCbSelected("Rock")%>>Rock
<input type="checkbox" name="faveMusic" value="Pop"
<%=formHandler.isCbSelected("Pop")%>>Pop
<input type="checkbox" name="faveMusic" value="Bluegrass"
<%=formHandler.isCbSelected("Bluegrass")%>>Bluegrass
<input type="checkbox" name="faveMusic" value="Blues"
<%=formHandler.isCbSelected("Blues")%>>Blues
<input type="checkbox" name="faveMusic" value="Jazz"
<%=formHandler.isCbSelected("Jazz")%>>Jazz
<input type="checkbox" name="faveMusic" value="Country"
<%=formHandler.isCbSelected("Country")%>>Country
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td colspan=2 valign=top>
Would you like to receive e-mail notifications on our special
sales?
<input type="radio" name="notify" value="Yes"
<%=formHandler.isRbSelected("Yes")%>>Yes
<input type="radio" name="notify" value="No"
<%=formHandler.isRbSelected("No")%>> No
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td colspan=2 align=center>
<input type="submit" value="Submit"> <input type="reset"
value="Reset">
</td>
</tr>
</table>
</center>
</form>
</body>
</html>
Рис. 2. Форма, созданная с помощью retry.jsp.
|
Так как retry.jsp также передает данные в process.jsp, контроллер постоянно
создает компонет bean и проверяет данные из формы, пока пользователь не введет
корректную информацию во все поля формы.
Такое использование bean внутри формы может быть рассмотрено как реализация
паттерна дизайна Memento. Memento- это поведенческий паттерн, чье предназначение
в получении состояния объекта таким образом, что объект может быть восстановлен
в этом состоянии позже, без нарушения его инкапсуляции. Так как bean создается и
вызывается в границах одного и того же запроса, инкапсуляция memento не
затрагивается.
Как я говорил ранее, контроллер передает запрос в success.jsp только после
того, как все данные из формы успешно прошли проверку. Success.jsp, в свою
очередь, выделяет bean из запроса и сообщает об успешной регистрации клиенту.
Заметьте, что несмотря на то, что скалярные свойства bean могут быть получены
используя выражения JSP или тэг <jsp:getProperty>, вам
все-равно придется преодолеть некоторые препятствия для получения
индексированных свойств:
<%
String[] faveMusic = formHandler.getFaveMusic();
if (!faveMusic[0].equals("1")) {
out.println("<ul>");
for (int i=0; i<faveMusic.length; i++)
out.println("<li>"+faveMusic[i]);
out.println("</ul>");
} else out.println("Nothing was selected");
%>
В будущем, вам не следует использовать тэги скриптлета для доступа к
индексированным свойствам, вместо этого используте свои собственные тэги с
поддержкой циклов. Рисунок 3 показывает клиент, успешно прошедший регистрацию.
Листинг 6. success.jsp
<jsp:useBean id="formHandler" class="foo.FormBean" scope="request"/>
<html>
<body>
<center>
<table cellpadding=4 cellspacing=2 border=0>
<th bgcolor="#CCCCFF" colspan=2>
<font size=5>USER REGISTRATION SUCCESSFUL!</font>
</th>
<font size=4>
<tr bgcolor="#c8d8f8">
<td valign=top>
First Name
<jsp:getProperty name="formHandler" property="firstName"/>
</td>
<td valign=top>
Last Name
<jsp:getProperty name="formHandler" property="lastName"/>
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top>
E-Mail
<jsp:getProperty name="formHandler" property="email"/>
</td>
<td valign=top>
Zip Code
<jsp:getProperty name="formHandler" property="zip"/>
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top colspan=2>
User Name
<jsp:getProperty name="formHandler" property="userName"/>
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td colspan=2 valign=top>
What music are you interested in?
<%
String[] faveMusic = formHandler.getFaveMusic();
if (!faveMusic[0].equals("1")) {
out.println("<ul>");
for (int i=0; i<faveMusic.length; i++)
out.println("<li>"+faveMusic[i]);
out.println("</ul>");
} else out.println("Nothing was selected");
%>
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td colspan=2 valign=top>
Would you like to receive e-mail notifications on our special
sales?
<jsp:getProperty name="formHandler" property="notify"/>
</td>
</tr>
</font>
</table>
</center>
</body>
</html>
Рис. 3. Подтверждение успешной регистрации.
|
Изменение запроса с помощью JSP страниц и
сервлетов Хотя вы уже видели bean, осуществляющий управление
внутренним состоянием и обработку формы, вы можете заметить, что проверка
элемента userName была только на то, что он не пуст. В основном,
когда добавляют нового пользователя в базу данных, ваша программа регистрации
проверяет, что имя пользователя уникально и раньше не вводилось в базу данных.
Если вы уже имеете для этой задачи сервлет доступа к базе данных -- Вам будет
интересно, как интегрировать его в рассматриваемый сценарий. Ответ -- "Очень
легко!". Вы можете просто передать запрос сервлету, точно также как и JSP
страничке, и продолжить обработку. Сервлет, в свою очередь, изменит bean (или
даже добавит новые beans к запросу) и передаст запрос другому ресурсу дальше по
цепи.
Например, вместо того, чтобы посылать его в success.jsp, как это было сделано
раньше, вы можете сделать небольшие изменения в контроллере, process.jsp, с тем
чтобы передать запрос сервлету для проверки на доступ:
<% if (formHandler.validate()) {
%>
<jsp:forward page="/servlet/DBHandler"/>
<%
} else {
// continue as before
}
%>
Посмотрите на сервлет DBHandler, показанный на Листинге 7.
Листинг 7. Сервлет для доступа к базе данных
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import foo.FormBean;
public class DBHandler extends HttpServlet {
public void doPost
(HttpServletRequest request, HttpServletResponse response) {
try {
FormBean f = (FormBean) request.getAttribute("formHandler");
boolean userExists = false;
//obtain a db connection and perform a db query
//ensuring that the username does not exist
//set userExists=true if user is found in db
//for a simple test, you can disallow the registration
//of the username "rogerm" as:
//if (f.getUserName().equals("rogerm")) userExists=true;
if (userExists) {
f.setErrors("userName","Duplicate User: Try a different username");
getServletConfig().getServletContext().
getRequestDispatcher("/jsp/forms/retry.jsp").
forward(request, response);
} else {
// retrieve the bean properties and store them
// into the database.
getServletConfig().getServletContext().
getRequestDispatcher("/jsp/forms/success.jsp").
forward(request, response);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Так как bean по-прежнему содержится в пределах запроса, вы можете легко
получить к нему доступ из сервлета, как здесь:
FormBean f = (FormBean) request.getAttribute ("formHandler");
Предположив, что сервлет выполнив запрос к базе данных, нашел другого
пользователя с таким же именем, сервлет может легко вызвать установочный метод
bean, для того, чтобы отобразить ошибочную ситуацию:
f.setErrors("userName","Duplicate User: Try a different username");
Опять-таки, сервлет может отправить запрос в его счастливый путь, используя
диспетчер запросов:
getServletConfig().getServletContext().
getRequestDispatcher("/jsp/forms/retry.jsp").
forward(request, response);
Рисунок 4 отображает ситуацию, в которой сервлет DBHandler
обнаружил дублирование имен пользователей.
Рис. 4. Созданная сервлетом форма, отображающая ошибку
дублирования имен пользователей.
|
Если сервлет не смог найти дублирование имен пользователя, он может обновить
базу данных, после получения доступа к регистрационной информации из полей bean
и последующей передачи запроса в success.jsp для подтверждения успешной
регистрации.
Доставка приложения Я буду полагать,
что вы используете новейший JavaServer Web Development Kit (JSWDK) от Sun для
запуска этого примера. Если у вас его нет, обратитесь к секции Resources
для того чтобы найти откуда его можно получить. Полагая, что сервер установлен в
jswdk-1.0.1, его директории по-умолчанию в Microsoft Windows, расположите файлы
вашего приложения как показано:
Скопируйте register.htm в jswdk-1.0.1webpages
Создайте каталог "forms" в jswdk-1.0.1examplesjsp
Скопируйте process.jsp в jswdk-1.0.1examplesjspforms
Скопируйте retry.jsp в jswdk-1.0.1examplesjspforms
Скопируйте success.jsp в jswdk-1.0.1examplesjspforms
Скопируйте forms.properties в jswdk-1.0.1examplesWEB-INFjspbeans
Скопируйте FormBean.java в jswdk-1.0.1examplesWEB-INFjspbeans
Откомпилируйте FormBean.java, набрав javac -d . FormBean.java
Должен быть создан
jswdk-1.0.1examplesWEB-INFjspbeansfooFormBean.class. Если вы
также тестируете сервлет, вы должны:
Обновить process.jsp для передачи запроса в сервлет, как показано ранее
Обновить classpath, чтобы включить jswdk-1.0.1examplesWEB-INFjspbeans
Скопировать DBHandler.java в jswdk-1.0.1examplesWEB-INFservlets
Откомпилировать DBHandler.java, набрав javac DBHandler.java
Как только вы запустили сервер, вы должны получить возможность запустить
приложение, набрав http://localhost:8080/register.htm в качестве URL.
Выводы Несмотря на то, что имеется
множество решений для обработки форм HTML, существует масса причин, почему JSP
может быть достойной альтернативой для распространненых подходов. JSP, с их
компонентной, основанной на bean архитектурой, может упростить обработку сложных
форм. Контейнер JSP также может снизить сложность обработки, автоматически
создавая компонеты bean и разбирая запрос. Следование основанному на bean
подходу также упрощает реализацию паттернов дизайна, таких как Memento, что
может играть важную роль в проверке данных из формы. Использование JSP для
обработки форм не устраняет использование сервлетов, так-как эти технологии
могут успешно сочетаться при использовании такой техники, как передача запроса.
Об авторе
<Гоувайнд
Сишадри Java гуру в jGuru.com и автор Enterprise Java Computing --
Applications and Architecture, изданной Cambridge University Press (1999).
Узнайте больше о Гоувайнд на
jGuru.com.
Ресурсы
Get the source code for the example: http://www.javaworld.com/javaworld/jw-03-2000/forms/Forms.jar
Download the latest JavaServer Web Development Kit: http://java.sun.com/products/jsp/download.html
Reprinted with permission from the March 2000 edition of JavaWorld magazine.
Copyright © ITworld.com, Inc., an IDG Communications company. View the
original article at: http://www.javaworld.com/jw-03-2000/jw-0331-ssj-forms.html
Перевод на русский © Николай
Малеванный, Сергей
Миссан, 2000
|