Ukryte funkcje JSP / Servlet [zamknięte]
Jestem zainteresowany twoimi sztuczkami itp używanymi przy pisaniu JSP / Servlet. Zacznę:
Niedawno dowiedziałem się, w jaki sposób można włączyć wyjście jednego tagu JSP do atrybutu innego tagu:
<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 answers
Uwaga: trudno mi wymyślić jakieś "ukryte funkcje" dla JSP / Servleta. Moim zdaniem "najlepsze praktyki" to lepsze sformułowanie i mogę myśleć o każdej z nich. Zależy to również od twoich doświadczeń z JSP / Servletem. Po latach rozwoju nie widzisz już tych "ukrytych funkcji". W każdym razie wymienię niektóre z tych małych "najlepszych praktyk", z których w latach odkryłem, że wielu starterów nie jest w pełni tego świadomych. Te byłyby klasyfikowane jako "ukryte cechy" w oku wielu przystawek. Tak czy siak, oto lista :)
Ukryj strony JSP przed bezpośrednim dostępem
Umieszczając pliki JSP w folderze /WEB-INF
skutecznie ukrywasz je przed bezpośrednim dostępem przez na przykład http://example.com/contextname/WEB-INF/page.jsp
. Spowoduje to 404
. Możesz wtedy uzyskać do nich dostęp tylko przez RequestDispatcher
w Servlet lub za pomocą jsp:include
.
Preprocess request for JSP
Większość wie o Serwletach doPost()
aby post - przetworzyć żądanie (formularz submit), ale większość nie wie, że można używać Servletów doGet()
method to pre - process a request for a JSP. Na przykład:
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);
}
W tym celu należy wykonać następujące czynności:]}
<table>
<c:forEach items="${items}" var="item">
<tr><td>${item.id}</td><td>${item.name}</td></tr>
</c:forEach>
</table>
Mapuj taki servlet na url-pattern
Z /page
(lub /page/*
) i po prostu wywołaj http://example.com/contextname/page
przez pasek adresu przeglądarki lub zwykły link waniliowy, aby go uruchomić. Zobacz też np. doGet i doPost w Servlets .
Dynamiczny zawiera
Możesz użyć EL w jsp:include
:
<jsp:include page="/WEB-INF/${bean.page}.jsp" />
{[36] } może po prostu zwrócić poprawną nazwę strony.
EL może uzyskać dostęp do dowolnego gettera
Nie jest to możliwe w przypadku, gdy obiekt nie jest w pełni zgodny z programem Javabean. Obecność metody no-arg, która jest poprzedzonaget
lub {[38] } jest więcej niż wystarczająca, aby uzyskać do niej dostęp w EL. Np.:
${bean['class'].name}
Zwraca wartość bean.getClass().getName()
gdzie metoda getClass()
jest rzeczywiście dziedziczona z Object#getClass()
. Zauważ, że {[42] } jest określona za pomocą "zapisu nawiasowego" []
z powodów wymienionych tutaj instanceof check w języku wyrażeń EL.
${pageContext.session.id}
Zwraca wartość pageContext.getSession().getId()
co jest przydatne w a.o. czy aplet może komunikować się z instancją servlet.
${pageContext.request.contextPath}
Zwraca wartość pageContext.getRequest().getContextPath()
co jest przydatne w a.o. jak aby używać ścieżek względnych bez włączania głównej nazwy kontekstu?
EL ma również dostęp do map
Następująca notacja EL
${bean.map.foo}
Rozwiązuje bean.getMap().get("foo")
. Jeśli klucz Map
zawiera kropkę, możesz użyć "zapisu nawiasowego" []
Z cytowanym kluczem:
${bean.map['foo.bar']}
, który rozwiązuje bean.getMap().get("foo.bar")
. Jeśli chcesz użyć klawisza dynamicznego, użyj również notacji nawiasowej, ale nie cudzysłowu:
${bean.map[otherbean.key]}
, która zmienia się na bean.getMap().get(otherbean.getKey())
.
Iteracja na mapie z JSTL
Możesz użyć c:forEach
jak również do iteracji nad Map
. Każda iteracja daje Map.Entry
który z kolei ma metody getKey()
i getValue()
(tak, że można uzyskać do niego dostęp w EL przez ${entry.key}
i ${entry.value}
). Przykład:
<c:forEach items="${bean.map}" var="entry">
Key: ${entry.key}, Value: ${entry.value} <br>
</c:forEach>
Zobacz też np. debugowanie z jstl - jak dokładnie?
Get current date in JSP
Możesz uzyskać aktualną datę z jsp:useBean
i sformatować za pomocą JSTL fmt:formatDate
<jsp:useBean id="date" class="java.util.Date" />
...
<p>Copyright © <fmt:formatDate value="${date}" pattern="yyyy" /></p>
To drukuje (od teraz) jak następuje: "Copyright © 2010".
Easy friendly URL ' s
Łatwym sposobem na posiadanie przyjaznych adresów URL jest wykorzystanie HttpServletRequest#getPathInfo()
i JSP jest ukryty w /WEB-INF
:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF" + request.getPathInfo() + ".jsp").forward(request, response);
}
Jeśli mapujesz ten servlet na przykład /pages/*
, wtedy żądanie na http://example.com/contextname/pages/foo/bar
wyświetli /WEB-INF/foo/bar.jsp
. Możesz zrobić krok dalej, dzieląc pathinfo na /
i wziąć tylko pierwszą część jako adres URL strony JSP i remnant jako "działania biznesowe" (niech servlet działa jako kontroler strony ). Patrz również np. wzorce projektowe aplikacje internetowe .
Redisplay wejście użytkownika za pomocą ${param}
Implicit el object {[66] } który odnosi się do HttpServletRequest#getParameterMap()
może być użyty do ponownego wyświetlenia danych wejściowych użytkownika po przesłaniu formularza w JSP:
<input type="text" name="foo" value="${param.foo}">
To w zasadzie robi to samo, co request.getParameterMap().get("foo")
. Zobacz też np. Jak mogę zachować wartości pól formularza HTML w JSP po przesyłanie formularza do Servleta?
nie zapomnij zapobiec XSS! Patrz następujący rozdział.
JSTL aby zapobiec XSS
Aby uniemożliwić witrynie XSS , wystarczy (ponownie)wyświetlić kontrolowane przez użytkownika dane za pomocą JSTLfn:escapeXml
lub c:out
.
<p><input type="text" name="foo" value="${fn:escapeXml(param.foo)}">
<p><c:out value="${bean.userdata}" />
Przemienne <table>
wiersze z LoopTagStatus
Atrybut varStatus
JSTL c:forEach
daje LoopTagStatus
back, który z kolei posiada kilka metod gettera (które można wykorzystać w EL!). Tak więc, aby sprawdzić parzyste wiersze, po prostu sprawdź, czy 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>
Który skutecznie skończy w
<table>
<tr class="even">...</tr>
<tr class="odd">...</tr>
<tr class="even">...</tr>
<tr class="odd">...</tr>
...
</table>
Użyj CSS, aby nadać im inny kolor tła.
tr.even { background: #eee; }
tr.odd { background: #ddd; }
Uzupełnij ciąg znaków przecinkami z listy / tablicy o LoopTagStatus
:
Kolejny przydatny LoopTagStatus
metoda jest isLast()
:
<c:forEach items="${items}" var="item" varStatus="loop">
${item}${!loop.last ? ', ' : ''}
<c:forEach>
Co skutkuje czymś w rodzaju item1, item2, item3
.
Funkcje EL
Możesz zadeklarować public static
metody użytkowe jako funkcje EL (jak as funkcje JSTL ), dzięki czemu możesz ich używać w EL. Np.
package com.example;
public final class Functions {
private Functions() {}
public static boolean matches(String string, String pattern) {
return string.matches(pattern);
}
}
Z /WEB-INF/functions.tld
które wyglądają następująco:
<?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>
Które mogą być używane jako
<%@taglib uri="http://example.com/functions" prefix="f" %>
<c:if test="${f:matches(bean.value, '^foo.*')}">
...
</c:if>
Pobierz oryginalny adres URL żądania i ciąg zapytania
Jeśli plik JSP został przekazany, można uzyskać oryginalny adres URL żądania przez,${requestScope['javax.servlet.forward.request_uri']}
I pierwotne Zapytanie o zapytanie string by,
${requestScope['javax.servlet.forward.query_string']}
to by było na tyle. Może prędzej czy później dodam więcej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:25:58