Скрытые возможности JSP / сервлета [закрыто]
меня интересуют ваши трюки и т. д., используемые при написании JSP/Servlet. Я начну:
Я несколько недавно узнал, как вы можете включить вывод одного тега JSP в атрибут другого тега:
<c:forEach items="${items}">
<jsp:attribute name="var">
<mytag:doesSomething/>
</jsp:attribute>
<jsp:body>
<%-- when using jsp:attribute the body must be in this tag --%>
</jsp:body>
</c:forEach>
1 ответ:
Примечание: мне трудно думать о каких-либо "скрытых функциях" для JSP/Servlet. На мой взгляд, "лучшие практики" - это лучшая формулировка, и я могу думать о любом из них. Это также действительно зависит от вашего опыта работы с JSP/Servlet. После многих лет разработки вы больше не видите эти "скрытые функции". В любом случае, я перечислю некоторые из тех небольших "лучших практик", о которых я в течение многих лет обнаружил, что многие начинающие не полностью осознают это. Они будут классифицированы как "скрытые функции" в глаз многих начал. Во всяком случае, вот список :)
скрыть страницы JSP от прямого доступа
поместив файлы JSP в
/WEB-INF
папка вы эффективно скрываете их от прямого доступа, напримерhttp://example.com/contextname/WEB-INF/page.jsp
. Это приведет к404
. Затем вы можете получить к ним доступ только с помощьюRequestDispatcher
в сервлете или с помощьюjsp:include
.
запрос предварительной обработки для JSP
большинство из них знают о Сервлет
doPost()
до post-обработка запроса (форма отправки), но большинство из них не знают, что вы можете использовать сервлетdoGet()
метод pre - обработка запроса на JSP. Например:protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<Item> items = itemDAO.list(); request.setAttribute("items", items); request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response); }
который используется для предварительной загрузки некоторых табличных данных, которые должны отображаться с помощью JSTL
c:forEach
:<table> <c:forEach items="${items}" var="item"> <tr><td>${item.id}</td><td>${item.name}</td></tr> </c:forEach> </table>
карта такого сервлета на
url-pattern
на/page
(или/page/*
) и просто вызватьhttp://example.com/contextname/page
по адресной строке браузера или ванильное ссылке, чтобы запустить его. См. также, например,метод dopost и doget С в сервлеты.
динамический включает в себя
вы можете использовать EL в
jsp:include
:<jsp:include page="/WEB-INF/${bean.page}.jsp" />
The
bean.getPage()
можно просто вернуть допустимое имя страницы.
EL может получить доступ к любому геттеру
EL не требует, чтобы объект для доступа был fullworthy Javabean. Этот наличие метода no-arg, который имеет префикс
get
илиis
более чем достаточно, чтобы получить доступ к нему в EL. Например:${bean['class'].name}
возвращает значение
bean.getClass().getName()
здесьgetClass()
метод фактически наследуется отObject#getClass()
. Обратите внимание, чтоclass
указывается с помощью "скобки нотации"[]
по причинам, упомянутым здесь instanceof check in EL expression language.${pageContext.session.id}
это возвращает значение
pageContext.getSession().getId()
что полезно в a. o.может ли апплет взаимодействовать с экземпляром сервлета.${pageContext.request.contextPath}
возвращает значение
pageContext.getRequest().getContextPath()
что полезно в a. o.как использовать относительные пути без включения корневого имени контекста?
EL также может получить доступ к картам
следующая нотация EL
${bean.map.foo}
разрешает
bean.getMap().get("foo")
. ЕслиMap
ключ содержит точку, вы можете использовать "скобки нотации"[]
С ключом в кавычках:${bean.map['foo.bar']}
который решает
bean.getMap().get("foo.bar")
. Если вы хотите динамический ключ, используйте скобки нотации, а затем без кавычек:${bean.map[otherbean.key]}
который решает
bean.getMap().get(otherbean.getKey())
.
итерации по карте с JSTL
можно использовать
c:forEach
а также перебиратьMap
. Каждая итерация даетMap.Entry
, который в свою очередьgetKey()
иgetValue()
методы (так что вы можете просто получить доступ к нему в EL by${entry.key}
и${entry.value}
). Пример:<c:forEach items="${bean.map}" var="entry"> Key: ${entry.key}, Value: ${entry.value} <br> </c:forEach>
см. также, например,отладка с jstl-как именно?
получить текущую дату в JSP
вы можете получить текущую дату с
jsp:useBean
и форматировать его с помощью JSTLfmt:formatDate
<jsp:useBean id="date" class="java.util.Date" /> ... <p>Copyright © <fmt:formatDate value="${date}" pattern="yyyy" /></p>
это печатает (на данный момент) следующим образом: "Copyright © 2010".
легкий дружественный URL-адрес
простой способ иметь дружественный URL-адрес, чтобы использовать
HttpServletRequest#getPathInfo()
и JSP спрятан в/WEB-INF
:protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/WEB-INF" + request.getPathInfo() + ".jsp").forward(request, response); }
если вы сопоставите этот сервлет, например
/pages/*
, то запрос наhttp://example.com/contextname/pages/foo/bar
будет эффективно отображаться/WEB-INF/foo/bar.jsp
. Вы можете получить шаг дальше, разделив pathinfo на/
и только взять первую часть в качестве URL страницы JSP и остаток как "бизнес-действия" (пусть сервлет действуйте как контроллер страницы). См. также, например,шаблоны проектирования веб-приложений.
Redisplay пользовательский ввод с помощью
${param}
неявный объект EL
${param}
что относится кHttpServletRequest#getParameterMap()
может использоваться для повторного отображения пользовательского ввода после отправки формы в JSP:<input type="text" name="foo" value="${param.foo}">
это в основном делает то же, что
request.getParameterMap().get("foo")
. См. также, например,как я могу сохранить значения полей HTML-формы в JSP после отправки формы на сервлет?
не забудьте предотвратить от XSS! См. следующую главу.
JSTL для предотвращения XSS
чтобы ваш сайт XSS, все, что вам нужно сделать, это (re)display управляемые пользователем данные с помощью JSTL
fn:escapeXml
илиc:out
.<p><input type="text" name="foo" value="${fn:escapeXml(param.foo)}"> <p><c:out value="${bean.userdata}" />
чередуя
<table>
строк сLoopTagStatus
The
varStatus
атрибут JSTLc:forEach
даетLoopTagStatus
назад, который в свою очередь имеет несколько методов геттера (которые могут быть использованы в EL!). Итак, чтобы проверить четные строки, просто проверьте, еслиloop.getIndex() % 2 == 0
:<table> <c:forEach items="${items}" var="item" varStatus="loop"> <tr class="${loop.index % 2 == 0 ? 'even' : 'odd'}">...</tr> <c:forEach> </table>
что будет эффективно в конечном итоге в
<table> <tr class="even">...</tr> <tr class="odd">...</tr> <tr class="even">...</tr> <tr class="odd">...</tr> ... </table>
используйте CSS, чтобы дать им другой цвет фона.
tr.even { background: #eee; } tr.odd { background: #ddd; }
заполнить запятую строку из списка / массива с помощью
LoopTagStatus
:еще один полезный
LoopTagStatus
методisLast()
:<c:forEach items="${items}" var="item" varStatus="loop"> ${item}${!loop.last ? ', ' : ''} <c:forEach>
что приводит к чему-то вроде
item1, item2, item3
.
EL функции
вы можете объявить
public static
служебные методы как функции EL (например, как функции JSTL), так что вы можете использовать их в ЭЛ. Е. Г.package com.example; public final class Functions { private Functions() {} public static boolean matches(String string, String pattern) { return string.matches(pattern); } }
с
/WEB-INF/functions.tld
которые выглядят следующим образом:<?xml version="1.0" encoding="UTF-8" ?> <taglib 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-jsptaglibrary_2_1.xsd" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>Custom_Functions</short-name> <uri>http://example.com/functions</uri> <function> <name>matches</name> <function-class>com.example.Functions</function-class> <function-signature>boolean matches(java.lang.String, java.lang.String)</function-signature> </function> </taglib>
что может использоваться как
<%@taglib uri="http://example.com/functions" prefix="f" %> <c:if test="${f:matches(bean.value, '^foo.*')}"> ... </c:if>
получить исходный URL-адрес запроса и строку запроса
если JSP был перенаправлен, вы можете получить исходный URL-адрес запроса,
${requestScope['javax.servlet.forward.request_uri']}
и исходная строка запроса запроса,
${requestScope['javax.servlet.forward.query_string']}
что это было так далеко. Может быть, я добавлю еще немного раньше или позже.