![]() |
|
... Соглашения в коде JavaServer Pages Окончание. Начало в КГ №11. JSP-объявления Как и соглашения, принятые в Java-коде, каждое объявление переменной в JSP, пусть даже одного и того же типа, необходимо размещать на разных строках:
А вообще JSP-объявления для переменных заметно осложняются, когда это приводит к использованию скриптового языка для описания бизнес-логики и Java-кода в JSP, который изначально проектировался для презентационных целей, а также осложняются переизбытком необходимости управлять целыми скопами переменных. JSP-скриптлеты По возможности следует избегать использования JSP-скриптлетов, в особенности когда библиотеки тэгов предоставляют эквивалентные функции. Такой подход делает страницы более читабельными и помогает отделить бизнес-логику от презентационной части/логики. Помимо этого ваши страницы будет очень просто переписать в стиле JSP версии 2.0 (хотя в JSP 2.0 есть поддержка скриптлетов, но их использование в этой спецификации всячески не приветствуется). В следующих примерах для каждого типа данных, которым представляется набор заказчиков, необходимо писать отдельный скриптлет: customers как массив объектов Customer <table> <% for (int i=0; i<customers.length; i++) { %> <tr> <td><%= customers[i].getLastName() %></td> <td><%= customers[i].getFirstName() %></td> </tr> <% } %> </table> customers как экземпляр класса Enumeration <table> <% for (Enumeration e = customers.elements(); e.hasMoreElements();) { Customer customer = (Customer)e.nextElement(); %> <tr> <td><%= customer.getLastName() %></td> <td><%= customer.getFirstName() %></td> </tr> <% } %> </table> Однако когда вы пользуетесь библиотекой тэгов, вы получаете более высокую гибкость при необходимости использования различных типов, которыми представляются заказчики. Например, следующий кусок JSP-кода будет поддерживать как массив, так и Enumeration-представление заказчиков: <table> <c:forEach var="customer" items="${customers}"> <tr> <td><c:out value="${customer.lastName}"/></td> <td><c:out value="${customer.firstName}"/></td> </tr> </c:forEach> </table> Это в духе применения шаблона проектирования MVC (model-view-controller) для послабления связи между презентационным ярусом и бизнес-логикой, поскольку JSP-скриптлеты вообще не должны использоваться для описания бизнес-логики. JSP-скриптлеты предпочтительнее использовать, если необходимо, для трансформирования данных (также иногда эти данные называют "объектами значений"), возвращаемых от обработанных клиентских запросов в подходящий, удобный формат. Но даже здесь лучше всего воспользоваться библиотекой тэгов или же отдельным сервлетом-контроллером. Например, следующий код получает имена заказчиков (customers) напрямую из базы данных и отображает их клиенту: <% // ЭТО НЕ РЕКОМЕНДУЕТСЯ ДЕЛАТЬ В ВИДЕ СКРИПТЛЕТА Connection conn = null; try { // Получаем объект Connection InitialContext ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("customerDS"); conn = ds.getConnection(); // Получаем имена заказчиков Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT name FROM customer"); // Выводим имена while (rs.next()) { out.println(rs.getString("name") + "<br>"); } } catch (SQLException e) { out.println("Невозможно получить имена заказчиков из базы данных:" + e); } finally { if (conn!= null) conn.close(); } %> Следующий сегмент JSP-кода будет намного лучше, если он делегирует функцию работы с базой данных custom-тэгу myTags:dataSource, который инкапсулирует и прячет все детали работы с базой данных в своей реализации: <myTags:dataSource name="customerDS" table="customer" columns="name" var="result" /> <c:forEach var="row" items="${result.rows}"> <c:out value="${row.name}" /> <br /> </c:forEach> result — это скриптовая переменная, введенная custom-тэгом myTags:dataSource для того, чтобы хранить полученные данные об именах заказчиков из базы данных. JSP-код также может быть более эффективным при условии поддержки сразу нескольких различных выходных форматов данных (HTML, XML, WML), которые определяются динамически в зависимости от потребностей клиента, без всяких угроз в сторону backend-кода (для тэга dataSource). Однако лучше всего было бы делегировать эту функцию на отдельный сервлет, который обрабатывал бы полученные данные и представлял результат для JSP-страницы посредством параметров-атрибутов. Подведем некоторый итог касательно JSP-скриптлетов: JSP-выражения должны применяться так же аккуратно, как и JSP-скриптлеты. Чтобы понять, почему так, давайте рассмотрим три следующих примера, которые выполняют одинаковые функции: Пример 1 (Java-код): <%= myBean.getName() %> Пример 2 (JSP-тэг): <jsp:getProperty name="myBean" property="name" /> Пример 3 (JSTL-тэг): <c:out value="${myBean.name}" /> В первом примере предполагается, что переменная myBean уже определена. В остальных двух предполагается, что переменная myBean — это атрибут, который может быть найден с использованием метода PageContext.findAttribute(). Кроме того, второй пример также предполагает, что переменная myBean была введена на этой странице при помощи тэга <jsp:useBean>. Из трех этих примеров предпочтение следует отдать третьему. Во-первых, третий вариант достаточно короток, чтобы сойти за JSP-выражение, во-вторых, его проще понять, и, в-третьих, он имеет мало общего с JSP-скриптлетами (которые предполагают, что web-разработчик знаком с языком Java, а также с основными API-вызовами). Более того, это позволяет странице больше походить на стиль JSP 2.0, где, для того чтобы выполнить аналогичную функцию, достаточно следующего кода: "${myBean.name}" в тексте шаблона. Какой бы пример ни применялся, он должен быть одобрен и согласован всеми web-разработчиками и быть последовательным во всех создаваемых JSP-страницах одного проекта. Также следует отметить, что третий пример, с использованием JSTL, несколько отличается от остальных тем, что получает значение myBean из контекста страницы, а не из локальной Java-переменной. И, наконец, предпочтительнее использовать JSP-выражения вместо эквивалентных JSP-скриптлетов, которые основываются на своем скриптовом языке. Например: <%= x %> лучше, чем <% out.print(x); %> Пустые линии и пробелы Пробельные символы обычно используются для того, чтобы сделать JSP-код более красивым, а также упростить процесс поддержки и изучения этого кода. В частности, пустые линии и пробелы должны присутствовать на JSP-страницах в местах, где имеет смысл их вставлять. Пустые линии Пустые линии обычно используются для улучшения точности и разборчивости JSP-страниц. Важно также, что пустые строки не вызывают каких-либо побочных эффектов для выходного формата. Например, ниже приведены два JSP-выражения, которые разделены пустой строкой и заключены в HTML-тэг <PRE>. В этом случае между результатами данных выражений на странице в браузере пользователя будет вставлена дополнительная пустая строка, как это было на самой JSP-странице до ее обработки. Однако, если блок тегов <PRE> отсутствует, то эта дополнительная пустая строка никак не скажется на внешнем виде результативной HTML-страницы в браузере пользователя.
Пробелы Символ пробела всегда должен присутствовать между самим JSP-тэгом и его содержимым. Например: <%= customer.getName() %> выглядит куда лучше, чем <%=customer.getName()%> Также присутствие пробельных символов желательно для разделения тэга комментария и самого комментария: <%— - многостроковый комментарий, который разбит - на две строки. —%> <%— короткий комментарий в одну строку —%> Именные соглашения Применяя именные соглашения, вы обеспечиваете элементам вашего web-компонента простоту идентификации, классифицирования и координации в проектах. В этой части статьи мы рассмотрим те именные соглашения, которые так или иначе касаются JSP. Имена JSP-файлов Имена JSP-файлов всегда должны начинаться с букв в нижнем регистре. Имя может состоять из нескольких слов. В таком случае каждое последующее слово (исключая начальное) следует начинать с заглавной буквы. Имя JSP-файла может быть как простым глаголом, так и небольшим предложением. Однако имен, состоящих только лишь из одного глагола, следует избегать, поскольку такие имена не несут в себе никакой информации для разработчиков. Например: perform.jsp не так понятно, как, скажем, вот это: performLogin.jsp В случае использования глагола как части имени JSP-файла по возможности лучше использовать этот глагол в настоящем времени, а не в виде герундия и прочих форм. Например: showAccountDetails.jsp предпочтительнее, чем showingAccountDetails.jsp Имена тэгов Ниже приведена таблица правил именования обработчиков JSP-тэгов и ассоциативных классов:
Также для того, чтобы эти классы тэгов было проще отличать от других классов, полезно добавлять суффиксы пакетов, тэгов, а также библиотек тэгов в имя пакета класса, например: com.mycorp.myapp.tags.XXXTag Префикс имен тэгов Префикс имени тэга должен быть достаточно коротким, соответствовать функции, выполняемой этим тэгом, а также начинаться, как и имена JSP-файлов, с буквы нижнего регистра. Префикс имени тэга не должен содержать каких бы то ни было неалфавитных символов. Вот несколько примеров:
JSP-страницы в синтаксисе XML JSP предоставляет два разных синтаксиса: стандартный синтаксис для написания JSP-странц и XML-синтаксис для написания JSP-документов. В этой статье мы преимущественно рассматривали стандартный синтаксис JSP. Однако многие из рассмотренных нами концепций могут также применяться и для JSP-документов. Введение JSP-документов произошло во многом из-за преобладания XML и его повсеместного внедрения, а также в целях предоставления возможности спецификации JSP 2.0 обеспечить более дружественное взаимодействие с XML-синтаксисом. Структура JSP-документа Все JSP-документы должны иметь примерно следующую структуру: <? xml version="1.0"?> <!— - Author(s): - Date: - Copyright Notice: - @(#) - Description: —> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:prefix1="URI-for-taglib1" xmlns:prefix2="URI-for-taglib2" version="1.2"> JSP Document... </jsp:root> Первая строчка — это опциальный XML-пролог, который, собственно, позволяет определить, что это есть некий XML-документ. После пролога идет комментарий к документу. Элемент <jsp:root> говорит о том, что это есть именно JSP-документ, а не какой-нибудь другой. Этот элемент должен быть корневым. Внутри этого тэга должны импортироваться все используемые именные пространства, а также библиотеки тэгов. Фактическое содержимое JSP-страницы — это все подэлементы корневого элемента <jsp:root>. Поскольку JSP-документы должны соответствовать всем правилам построения XML-документов, некоторые элементы, как, например, <% %> должны быть заменены их XML-эквивалентами (в этом случае — на <jsp:scriptlet />). За более подробной информацией обращайтесь к спецификации JSP. XML-комментарий В спецификации JSP ничего не сказано по поводу того, остаются ли XML-комментарии внутри документа после обработки его JSP-процессором, поэтому лучше всего воспользоваться обходным маневром, т.к. в этом случае клиент в любом случае получит желаемое вами. Например, вот так: ... <jsp:text><![CDATA[ <!— - Многостроковый комментарий, который - будет послан клиенту. —> ]]></jsp:text> ... Java-код в JSP-документах При использовании Java-кода внутри объявлений, скриптлетов или выражений элемент CDATA должен использоваться лишь тогда, когда необходимо быть уверенным, что ваш код не вредит структуре документа: ... <jsp:scriptlet> for(int level = 0; level < 3; level++) { </jsp:scriptlet> <tr> <td> <jsp:expression><![CDATA[ "<h" + level + ">Text</h" + level + ">" ]]></jsp:expression> </td> </tr> <jsp:scriptlet> } </jsp:scriptlet> ... А вообще написания Java-кода в ваших JSP-страницах следует избегать хотя бы по следующим причинам: JSP предоставляет подходящий элемент для инициализации всех свойств JavaBean'ов, например: <jsp:setProperty name="bankClient" property="*"/> Однако такой прием следует использовать с осторожностью. Во-первых, если бин содержит свойство, скажем, amount, и такого параметра (amount) не существует в текущем объекте ServletRequest или же его значение равно "", ничего не выйдет: JSP даже не присвоит null самым обыкновенным свойствам этого бина. Во-вторых, неэлементарные свойства, которые не имеют определенного заранее PropertyEditor'а, не обязательно будут проинициализированы строковым значением из объекта ServletRequest. В-третьих, злоумышленники могут указать дополнительные параметры в строке запроса, тем самым установив нежелательные свойства вашему бину в случае, если приложение спроектировано недостаточно тщательно. Если вы все равно не хотите отказываться от использования property="*" в тэге jsp:setProperty и таким образом хотите получать более чистый код, примите во внимание совет добавлять комментарий перед этим тэгом, в котором указывать, какие свойства вы предполагаете инициализировать у конкретного бина. Например, в следующем примере комментарий оповещает о том, что у бина bankClient должны быть проинициализированы два свойства: firstName и lastName. <%— - requires firstName and lastName from the ServletRequest —%> <jsp:setProperty name="bankClient" property="*" /> Кавычки Вместо одинарных кавычек (') в большинстве случаев следует использовать двойные кавычки ("). Это общепринятое соглашение. Например:
<jsp:include page='<%= getFoodMenuBar("Monday") %>' /> Использование JavaScript Все ваши скрипты на JavaScript не должны зависеть от каких-либо особенностей конкретного браузера, чтобы правильно функционировать на всех существующих браузерах, которые поддерживают JavaScript. Также правилом хорошего тона в программировании считается выносить JavaScript-скрипты в отдельные файлы, отдельно от JSP-страниц. Для того, чтобы вставить файл со скриптом, можно воспользоваться следующим HTML-выражением: <script language=javascript src="/js/main.js"> Это значительно увеличивает шансы этого скрипта на то, что им можно будет воспользоваться в других проектах в дальнейшем, и нисколько не осложнит JSP-код. Каскадные таблицы стилей (CSS) Как известно, каскадные таблицы стилей (Cascading Style Sheets) используются для централизации контроля над основными свойствами и характеристиками различных тэгов (заголовков, таблиц, ссылок и т.д.). Они значительно упрощают процесс поддержки кода и значительно уменьшают его размер. Так, вместо того, чтобы встраивать информацию о стиле в каждый HTML-тэг, где это необходимо, например: <H1><FONT color="blue">Chapter 1</FONT></H1> ... <H1><FONT color="blue">Chapter 2</FONT></H1> ... Можно определить информацию о стилистике заголовка H1 в файле (например, myJspStyle.css) следующим образом: H1 { color: blue } А после применить его к JSP-странице: <link rel="stylesheet" href="css/myJspStyle.css" type="text/css"> ... <H1>Chapter 1</H1> ... <H1>Chapter 2</H1> ... Прочие рекомендации В этой статье было представлено множество рекомендаций касательно соглашений в коде JSP и прочих артефактов при разработке web-компонентов с целью улучшить и тем самым упростить его дальнейшую поддержку, а также придать ему более профессиональный и стандартизированный вид. Однако, если вы углубитесь в этот процесс, то обнаружите множество других полезных и важных приемов. Например, в спецификации JSP 1.2 присутствует множество дополнительных рекомендаций, с которыми вы можете ознакомиться. Исходный код проекта, который использовался для написания этой статьи, а также уже собранный проект вы можете скачать отсюда: http://developer.java.sun.com/servlet/CodeConventionServlet/ . Вам понадобится скачать WAR-файл. По материалам Kam Hay Fung и Mark Roth Подготовил Алексей Литвинюк, http://www.litvinuke.hut.ru © Компьютерная газета
|
|