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 poprzedzona get 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 &copy; <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ą JSTL fn: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.

 152
Author: BalusC,
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