JSP: Java Server Pages
Что такое JSP?
Технология Java Server Pages (tm) (JSP) позволяет разработчикам и дизайнерам web-приложений быстро разрабатывать и легко сопровождать web-страницы с динамическим наполнением информацией. Но описание практически каждой технологии подобного назначения (ASP, PHP, Net.Data) сопровождают подобные слова -- быстро и легко ...При внешней схожести JSP отличают некоторые моменты, делающие данную технологию чем-то большим, чем ещё одно средство для создания динмически генерируемого содержания web-страниц.
Сначала простое перечисление:
- действительно высокая межплатформенная переносимость; использование универсального языка высокого уровня Java в качестве скриптового;
- JSP -- это не какое-то отдельно стоящее средство для решения достаточно узкого круга задач, пусть и достаточно мощное, а ещё одно в ряде целой плеяды технологий, объединяемых Java;
- реальная возможность разделить задачи написания бизнес-логики web-приложения и пользовательского интерфейса, что позволяет разрабатывать и сопровождать различные части проекта независимо;
Количество тегов достаточно невелико, что упрощает начальное освоение данной
технологии; впрочем, для простых вещей та же Net.Data или PHP тоже весьма
просты. Как водится, рассмотрим примитивный случай класса Hello World!
<%@ page contentType="text/html; charset=ibm866" %>
<%@ page import ="java.net.*" %>
<%@ page import ="java.util.Date" %>
<HTML>
<HEAD>
<TITLE>Who Am I?</TITLE>
</HEAD>
<BODY>
<%
InetAddress localHost = InetAddress.getLocalHost();
Date localTime = new Date();
%>
<H1>Who Am I?</H1>
I am called <%= localHost.getHostName() %> (<%= localHost.getHostAddress() %>).<br>
This page last executed at <%= localTime.toString() %>.
</BODY>
</HTML>
Даже у человека, не знающего Java, понимание вышеприведенного кода, скорее
всего, не вызовет проблем. Остановимся на некоторых моментах: код, находящийся
внутри тегов
Если мощь таких конкурирующих (наверное, это всё-таки так ;-) инструментов, как PHP и Net.Data, обусловлены в первую очередь огромным набором предопределённых функций, то за JSP стоит весь конгломерат классов и технологий Java.
Но на таком простом примере вовсе не очевидно, почему нужно выбрать JSP и всё с ними связанное, в первую очередь servlets и beans. Тем не менее попытаемся рассмотреть некоторые приятные стороны JSP.
Session Management
Значения, которые сохраняются и извлекаются из объекта сессии, не могут быть примитивными типами данных (int, double) и должны быть представлены в виде своих классов-аналогов (Integer, Double).HttpSession session=request.getSession();//get session object or create one session.getId() //get the session ID number Integer item = (Integer) session.getValue("item") // retrieve Integer object session.putValue("ItemValue", itemName);//ItemValue must not be primitive
Application Management
Иногда необходимо обеспечить сервером некоторых значений переменных на уровне сайта, каждый клиент использует и манипулирует копиями этих данных. JSP использует объект ServletContext, который обеспечивает механизм, схожий с сессией (i.e. no primitive types).getServletContext().setAttribute("Item", ItemValue);//to set an application variable Integer i=(Integer)getServletContext().getAttribute("ItemName");//get item
JSP-Specific Language
Директивы JSP "говорят" серверу делать что-либо, когда они преобразуются из JSP в сервлет; директивы предваряются символом @. Некоторые важные директивы JSP перечислены ниже, для более полного знакомства естественно придется почитать что-то ещё.include - включение статического или динамического файла (Server Side Include) <%@ include file="hello.jsp" %> import - итоговый сервлет будт импортировать данный пакет <%@ import = "java.util.*" %> extends - сервлет будет расширять (наследовать) указанный класс (это superclass) <%@ extends = "java.util.Dictionary" %> implements - сервлет будет имплементировать интерфейс <%@ implements = "java.util.Enumeration" %> content_type - устанавливает тип ответа, генерируемого сервлетом <%@ content_type = "text/plain" %> или <%@ content_type = "text/html" %>
Известно, что задачи в этом сложном мире бывают не только простые или даже очень простые. Если поддаться соблазну делать всё средствами скриптлетов (динамических вставок Java кода среди статического HTML), и рассматривать внешние классы как мощную библиотеку функций, очень легко сделать из динамической страницы объёмного монстра, тяжёлого в отладке и с огромными трудностями при дальнейших модификациях и расширении.
Да, как и у конкурентов, сложность можно нивелировать, разбив сложную страницу на несколько логически обособленных кусков и собирая их вместе с помощью средства включения (include).
Есть два варианта include:
- Статическое включение, при этом обрабатываются JSP-элементы во
включаемом файле, если они есть и попадают в результирующий сгенерированый
Java-код, фактически серлет:
<%@ include file="includeheader.jsp"%>
или так<%@ include file="includeheader.html"%>
то есть включаемый файл вовсе не обязан быть JSP страницей. - Динамическое включение, при этом контент включаемого файла
обрабатывается независимо, фактически ему передается управление на момент
выполнения:
<jsp:include page="topic.html" flush=true />
Практически каждый, начав делать web-приложение, сталкивается с необходимостью предоставить пользователю удобное средство для ввода информации, и тут, как правило, возникают большие проблемы, чем просто с предоставлением информации в виде сгенерёных HTML-страниц. Необходимо обеспечить достаточную интеллектуальность ввода, кроме того, при ошибках ввода не терять ранее введённое и передавать требуемую общую информацию от страницы к странице. В Net.Data, например, я не нашёл способа делать это иначе, чем использовать hidden-поля в формах ввода, хранение же информации с временем жизни "session" вырастает в сложную задачу; как можно выкрутиться с решением этой задачи в PHP, я не в курсе. Что же касается JSP/servlets -- есть стандартное средство JavaBeans (в данном контексте не будем останавливаться на таком более мощном развитии данной концепции, как EJB) -- это полноценные классы Java с некоторыми дополнительными правилами программирования.
Это очень мощное средство, но оно требует некоторой ломки стереотипов. JavaBeans -- это компоненты Java, которые могут выполнять хорошо определённые задачи и включать в себя объекты данных. JavaBeans следуют структурной объектной модели: Bean имеет public constructor, который не имеет аргументов, и его свойства устанавливаются с помощью управляющего сервлета с использованием интроспекции (introspection/reflection).
Включение некоторого бина в "страницу" JSP делается например так:
<jsp:useBean id="formHandler" class="VagonCardFormBean" scope="request" > <jsp:setProperty name="formHandler" property="*" /> </jsp:useBean> ... <tr><td>Дополнение</td> <td><input type=text name=description value="<%= formHandler.getDescription()%>"></td> <td><%=formHandler.getErrorMsg("description")%></td></tr> <tr><td>Владелец</td> <td><%= formHandler.getOwnerName()%> | <%= formHandler.getOwnerName()%></td> <td><%=formHandler.getErrorMsg("owner")%></td></tr> <tr><td>===></td><td><input type=submit value=Ввод></td><td></td></tr>или вот ещё один
<jsp:useBean id="Cindy" class="Coffee" /> <jsp:setProperty name="Cindy" property="Flavor" Value="RaspberryMocha"/> I like <%= Cindy.getFlavor() %> coffee. //The Coffee Bean: Public class Coffee { private String m_flavor; public Coffee() { m_flavor = "Regular"; } public void setFlavor(String flavor) { m_flavor = flavor; } public String getFlavor() { return m_flavor; } }
Некоторые пояснения к этой выжимке: scope="request" означает, что время жизни бина -- request, property="*" означает, что данный бин принимает с помощью своих методов все параметры, переданные в запросе на данную страницу. Эти методаы имеют простое правило именования: если параметр формы -- lastName, то метод, принимающий данные, будет иметь имя setLastName, а отдающий данные -- getLastName.
К сожалению, достаточно трудно продемонстрировать всю мощь использования бинов в простом приложении. Впрочем, данная статья и не ставит своей целью дать всю глубину, задача заинтересовать.
Генеральная линия, которая прослеживается во множестве публикаций последнего времени -- разделение работы дизайнера и работы программиста, обеспечивающего написание собственно работы с базой данных и бизнес-логику web-приложения. Большая часть этого может быть вынесена именно на уровень бинов. К сожалению, трудоемкость написания, по крайней мере на начальном этапе, у связки JSP-servlets-beans выглядит большей, чем у Net.Data и PHP (впрочем, с последним я знаком на уровне чуть большем "Hello World!"). Но даже использование бинов не освобождает совсем от минимального использования Java на странице. Чтобы дойти до логического конца и оставить дизайнеру только правильную расстановку тегов на странице, в JSP ввели возможность написания библиотек тегов (custom JSP tag libraries).
Использование библиотек тегов позволяет, во первых, ещё повысить повторное
использование кода, во вторых, снизить сложность написания прриложения, и, в
третьих, ещё больше помочь в разделении труда. К сожалению, последнее в нашей
действительности ещё не приобрело должного веса при выборе средства разработки.
В заключение приведу небольшой пример использования пользовательских тегов,
например, запрос к базе с выводом результата в виде таблицы может выглядеть вот
так:
<%@ taglib uri="xsql.tld" prefix="xsql" %>
...
<xsql:connect id="tConn" url="jdbc:db2:sample" name="user" password="password" />
<table border=1>
<tr><th>что-то</td><th>нечто</td><th>описание</td></tr>
<xsql:select req="select Ref, TName, Comment from vcRefList;" conn="tConn">
<tr><td>"$1$"</td><td>"$2$"</td><td>"$3$"</td></tr>
</xsql:select>
</table>
<xsql:disconnect conn="tConn" />
но это вовсе не значит, что он должен так выглядеть ;-)
На самом деле тема слишком обширна, чтобы быть охваченой без белых пятен в столь коротком изложении.
Serge Popov