scriptlet обработка - Как избежать Java-кода в JSP-файлах?




пример нажатия (25)

чтобы избежать java-кода в JSP-файлах java теперь предоставляет библиотеки тегов, такие как JSTL, также java придумал JSF, в который можно написать все структуры программирования в виде тегов

Я новичок в Java EE, и я знаю, что что-то вроде следующих трех строк

<%= x+1 %>
<%= request.getParameter("name") %>
<%! counter++; %>

является старым школьным способом кодирования, а в JSP версии 2 существует способ избежать Java-кода в JSP-файлах. Может кто-нибудь, пожалуйста, скажите мне альтернативные линии JSP 2 и что называется этой техникой?


Если мы используем в Java-приложении следующие вещи, java-код можно исключить из переднего плана JSP.

  1. Использовать архитектуру MVC для веб-приложения

  2. Использовать теги JSP

    а. Стандартные теги

    б. Пользовательские теги

  3. Язык выражений


JSP 2.0 имеет функцию «Файлы тегов» , вы можете писать теги без внешнего javaкода и tld. Вам нужно создать .tagфайл и поместить его, WEB-INF\tagsвы даже можете создать структуру каталогов для упаковки ваших тегов.

Например:

/WEB-INF/tags/html/label.tag

<%@tag description="Rensders a label with required css class" pageEncoding="UTF-8"%>
<%@attribute name="name" required="true" description="The label"%>

<label class="control-label control-default"  id="${name}Label">${name}</label>

Используйте его как

<%@ taglib prefix="h" tagdir="/WEB-INF/tags/html"%>
<h:label  name="customer name" />

Также вы можете легко прочитать тело тега

/WEB-INF/tags/html/bold.tag
<%@tag description="Bold tag" pageEncoding="UTF-8"%>
<b>
  <jsp:doBody/>
</b>

Используй это

<%@ taglib prefix="h" tagdir="/WEB-INF/tags/bold"%>
<h:bold>Make me bold</h:bold>

Образцы очень просты, но здесь вы можете выполнять множество сложных задач. Пожалуйста , обратите внимание вы можете использовать другие тег (например , JSTLкоторая имеет контрольные метки , как с if/forEcah/chosenтекстом , как format/contains/uppercaseили даже SQL тегов select/update), передавать все параметры типа, например Hashmap, доступ session, request... в файле теги тоже.

Файл тега настолько прост, что вам не нужно перезапускать сервер при их изменении, например, файлы jsp. Это облегчает их разработку.

Даже если вы используете фреймворк, такой как struts 2, в котором есть много хороших тегов, вы можете обнаружить, что наличие ваших собственных тегов может значительно сократить ваш код. Вы можете передать свои параметры тега в struts и таким образом настроить свой тег framework.

Вы можете использовать тег не только для того, чтобы избежать java, но и свести к минимуму ваши HTML-коды. Я сам пытаюсь просмотреть HTML-коды и быстро создавать теги, как только на моих страницах начнется просмотр дубликатов кода.

(Даже если вы в конечном итоге используете java в jsp-коде, который, надеюсь, нет, вы можете инкапсулировать этот код в тег)


Использование сценариев в JSP не является хорошей практикой.

Вместо этого вы можете использовать:

  1. Теги JSTL
  2. Выражения EL
  3. Пользовательские теги - вы можете определить свои собственные теги для использования.

Пожалуйста, обратитесь к:

  1. http://docs.oracle.com/javaee/1.4/tutorial/doc/JSTL3.html
  2. EL

Вы подняли хороший вопрос, и хотя у вас есть хорошие ответы, я бы посоветовал вам избавиться от JSP. Это устаревшая технология, которая в конечном итоге умрет. Используйте современный подход, например, движки шаблонов. У вас будет очень четкое разделение слоев бизнеса и презентаций и, конечно же, кода Java в шаблонах, поэтому вы можете создавать шаблоны непосредственно из программного обеспечения для редактирования веб-презентаций, в большинстве случаев использующих WYSIWYG.

И, конечно, избегайте фильтров и предварительной и последующей обработки, иначе вы можете столкнуться с проблемами поддержки / отладки, поскольку вы всегда не знаете, где переменная получает значение.


Как и многие ответы, используйте JSTL или создайте свои собственные теги. Here хорошее объяснение создания пользовательских тегов


В архитектурном шаблоне MVC JSP представляют собой слой «Вид». Встраивание java-кода в JSP считается плохой практикой. Вы можете использовать JSTL , freeMarker , velocity с JSP как «шаблонный движок». Поставщик данных для этих тегов зависит от структуры, с которой вы имеете дело. Struts 2 и webwork как реализация для MVC Pattern использует OGNL «очень интересную технику для выставления Beans Properties для JSP».


Использование скриптов очень старый и не рекомендуется. Если вы хотите напрямую вывести что-то на своих страницах JSP, используйте язык выражений (EL) и JSTL .

Существуют и другие варианты, такие как использование шаблонов, таких как Velocity, Freemarker, Thymeleaf и т. Д. Но использование простого JSP с EL и JSTL служит моей цели большую часть времени, и это также кажется самым простым для новичка.

Кроме того, обратите внимание на то, что для уровня бизнес-логики на уровне представления не лучше всего выполнять бизнес-логику на уровне сервиса и передавать результат на свои представления через контроллер.


Технически, JSP все преобразованы в Servlets во время выполнения . Первоначально JSP был создан с целью развязки бизнес-логики и логики проектирования, следуя шаблону MVC. Таким образом, JSP представляет собой технически все java-коды во время выполнения. Но для ответа на вопрос библиотеки тегов обычно используются для применения логики (удаления кодов Java) к страницам JSP.


Использование сценариев (те <% %> %% <% %> вещей) в JSP действительно сильно обескуражено с момента рождения taglib (например, JSTL ) и EL ( EL , эти вещи ${} ) еще в 2001 году.

Основными недостатками скриптлетов являются:

  1. Повторное использование: вы не можете повторно использовать скриптлеты.
  2. Заменяемость: вы не можете создавать абстрактные скриптлеты.
  3. OO-способность: вы не можете использовать наследование / состав.
  4. Отладка: если скриптлет порождает исключение наполовину, все, что вы получаете, это пустая страница.
  5. Возможность тестирования: сценарии не проверяются на единицу.
  6. Поддержание работоспособности : для каждого сальдо требуется больше времени для поддержания смешанной / загроможденной / дублированной логики кода.

Sun Oracle сам также рекомендует в соглашениях о кодировании JSP избегать использования сценариев, всякий раз, когда одни и те же функциональные возможности могут выполняться классами (тегами). Вот несколько ссылок, релевантных:

Из спецификации JSP 1.2 настоятельно рекомендуется использовать JSP стандартную библиотеку тегов (JSTL) в вашем веб-приложении, чтобы уменьшить необходимость создания сценариев JSP на ваших страницах. Страницы, которые используют JSTL, в общем, легче читать и поддерживать.

...

По возможности избегайте сценариев сценариев JSP, когда библиотеки тегов предоставляют эквивалентную функциональность. Это упрощает чтение и обслуживание страниц, помогает отделить бизнес-логику от логики представления и облегчит перевод ваших страниц на страницы в стиле JSP 2.0 (спецификация JSP 2.0 поддерживает, но не позволяет использовать скриптлеты).

...

В духе принятия шаблона проектирования Model-View-Controller (MVC) для уменьшения связи между уровнем представления из бизнес-логики сценарии сценариев JSP не должны использоваться для написания бизнес-логики. Скорее, сценарии сценариев JSP используются, если необходимо, для преобразования данных (также называемых «объектами значений»), возвращаемых при обработке запросов клиента в надлежащий готовый к клиенту формат. Даже тогда это было бы лучше сделать с сервлетом переднего контроллера или специальным тегом.

Как заменить скрипты полностью зависит от единственной цели кода / логики. Более часто этот код должен быть помещен в полноценный Java-класс:

  • Если вы хотите вызывать один и тот же код Java при каждом запросе, меньше или больше, независимо от запрашиваемой страницы, например, проверять, зарегистрирован ли пользователь, затем внедрить filter и записать код соответственно в метод doFilter() . Например:

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
            ((HttpServletResponse) response).sendRedirect("login"); // Not logged in, redirect to login page.
        } else {
            chain.doFilter(request, response); // Logged in, just continue request.
        }
    }
    

    При сопоставлении с соответствующим <url-pattern> охватывающим интересующие страницы JSP, вам не нужно копировать одну и ту же часть кода поверх всех страниц JSP.

  • Если вы хотите вызвать некоторый код Java для предварительной обработки запроса, например, предварительно загрузив некоторый список из базы данных, чтобы отобразить в какой-либо таблице, при необходимости на основе некоторых параметров запроса, затем реализовать servlet и написать код соответственно в методе doGet() . Например:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            List<Product> products = productService.list(); // Obtain all products.
            request.setAttribute("products", products); // Store products in request scope.
            request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response); // Forward to JSP page to display them in a HTML table.
        } catch (SQLException e) {
            throw new ServletException("Retrieving products failed!", e);
        }
    }
    

    Этот способ справиться с исключениями проще. БД недоступен в середине рендеринга JSP, но намного раньше, чем отображается JSP. У вас все еще есть возможность изменять ответ, когда доступ к БД вызывает исключение. В приведенном выше примере будет отображаться страница с ошибкой по умолчанию 500, которую вы можете в любом случае настроить с помощью <error-page> в web.xml .

  • Если вы хотите вызвать некоторый Java-код для постпроцесса запроса, например, обработать форму submit, затем реализовать servlet и написать код соответственно в методе doPost() . Например:

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = userService.find(username, password);
    
        if (user != null) {
            request.getSession().setAttribute("user", user); // Login user.
            response.sendRedirect("home"); // Redirect to home page.
        } else {
            request.setAttribute("message", "Unknown username/password. Please retry."); // Store error message in request scope.
            request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to JSP page to redisplay login form with error.
        }
    }
    

    Таким образом, упростить работу с разными адресами страниц результатов: повторное отображение формы с ошибками проверки в случае ошибки (в этом конкретном примере вы можете перерисовать ее с помощью ${message} в EL ) или просто перейти на желаемую целевую страницу в случае успеха.

  • Если вы хотите вызвать некоторый Java-код для управления планом выполнения и / или местом назначения запроса и ответа, тогда выполните servlet соответствии с шаблоном Front Controller MVC . Например:

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            Action action = ActionFactory.getAction(request);
            String view = action.execute(request, response);
    
            if (view.equals(request.getPathInfo().substring(1)) {
                request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
            } else {
                response.sendRedirect(view);
            }
        } catch (Exception e) {
            throw new ServletException("Executing action failed.", e);
        }
    }
    

    Или просто примените структуру MVC, такую ​​как JSF , Spring MVC , Wicket и т. Д., Чтобы вы получили только страницу JSP / Facelets и класс Javabean без необходимости использования специального сервлета.

  • Если вы хотите вызвать некоторый Java-код для управления потоком внутри JSP-страницы, вам нужно захватить (существующий) тегlib потока управления, например, JSTL-ядро . Например, отображение List<Product> в таблице:

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    ...
    <table>
        <c:forEach items="${products}" var="product">
            <tr>
                <td>${product.name}</td>
                <td>${product.description}</td>
                <td>${product.price}</td>
            </tr>
        </c:forEach>
    </table>
    

    С тегами XML-стиля, которые хорошо подходят для всего HTML, код лучше читается (и, следовательно, лучше обслуживается), чем куча скриптов с различными открывающимися и закрывающимися фигурными скобками ( «К черту эта закрывающая фигурная скобка принадлежит?» ). Легкая помощь заключается в том, чтобы настроить веб-приложение, чтобы генерировать исключение, когда скриптлеты все еще используются, добавив следующий фрагмент в web.xml :

    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <scripting-invalid>true</scripting-invalid>
        </jsp-property-group>
    </jsp-config>
    

    В Facelets , преемник JSP, который является частью Java EE, обеспечил JSF структуру MVC, уже невозможно использовать скрипты . Таким образом, вы автоматически вынуждены делать что-то «правильно».

  • Если вы хотите вызвать некоторый Java-код для доступа и отображения «бэкэнда» данных на странице JSP, вам нужно использовать EL (язык выражений), эти ${} вещи. Например, отображение отображаемых входных значений:

    <input type="text" name="foo" value="${param.foo}" />
    

    ${param.foo} отображает результат request.getParameter("foo") .

  • Если вы хотите вызвать какой-то Java-код утилиты непосредственно на странице JSP (обычно это public static методы), вам необходимо определить их как функции EL. В JSTL есть стандартная функция taglib , но вы также можете легко создавать функции самостоятельно . Вот пример того, как JSTL fn:escapeXml полезен для предотвращения attacks XSS .

    <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
    ...
    <input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
    

    Обратите внимание, что чувствительность XSS никоим образом не связана с Java / JSP / JSTL / EL / независимо от того, какая проблема должна быть учтена в каждом веб-приложении, которое вы разрабатываете. Проблема сценариев заключается в том, что он не предоставляет никаких встроенных предупреждений, по крайней мере, не используя стандартный Java API. Преемник JSP's Facelets уже неявный HTML-экранирование, поэтому вам не нужно беспокоиться о дырах XSS в Facelets.

Смотрите также:


Просто используйте тег JSTL и выражение EL.


Независимо от того, насколько вы пытаетесь избежать, когда вы работаете с другими разработчиками, некоторые из них по-прежнему предпочитают скриптлет, а затем вставляют злой код в проект. Поэтому настройка проекта при первом знаке очень важна, если вы действительно хотите уменьшить код сценария. Существует несколько способов преодолеть это (в том числе несколько фреймворков, о которых упоминалось выше). Однако, если вы предпочитаете чистый JSP-путь, используйте файл тегов JSTL. Самое приятное в этом - вы также можете настроить мастер-страницы для своего проекта, чтобы другие страницы могли наследовать мастер-страницы

Создайте главную страницу под названием base.tag под вашими WEB-INF / тегами со следующим содержимым

<%@tag description="Overall Page template" pageEncoding="UTF-8"%>

<%@attribute name="title" fragment="true" %>

<html>
  <head>
    <title>  
       <jsp:invoke fragment="title"></jsp:invoke>
    </title>

  </head>
  <body>
    <div id="page-header">
       ....
    </div>
    <div id="page-body">
      <jsp:doBody/>
    </div>
    <div id="page-footer">
      .....
    </div>
  </body>
</html>

На этой странице mater я создал фрагмент под названием «title», так что на дочерней странице я мог вставить больше кодов в это место главной страницы. Кроме того, тег <jsp:doBody/> будет заменен содержимым дочерней страницы

Создайте дочернюю страницу (child.jsp) в папке WebContent:

<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>

<t:base>
    <jsp:attribute name="title"> 
        <bean:message key="hello.world" />
    </jsp:attribute>

    <jsp:body>
    [Put your content of the child here]
    </jsp:body>   
</t:base>

<t:base> используется для указания основной страницы, которую вы хотите использовать (в данный момент это base.tag). Все содержимое внутри тега <jsp:body> здесь заменит <jsp:doBody/> на главной странице. Ваша дочерняя страница также может содержать любые теги lib, и вы можете использовать ее, как и другие. Однако, если вы используете любой скриптлетный код здесь ( <%= request.getParameter("name") %> ...) и попробуйте запустить эту страницу, вы получите JasperException because Scripting elements ( &lt;%!, &lt;jsp:declaration, &lt;%=, &lt;jsp:expression, &lt;%, &lt;jsp:scriptlet ) are disallowed here . Таким образом, другие люди не могут включить злой код в файл jsp

Вызов этой страницы с вашего контроллера:

Вы можете легко вызвать файл child.jsp с вашего контроллера. Это также хорошо работает с ракурсами struts


если вы просто хотите избежать недостатков Java-кодирования в JSP, вы можете сделать это даже с помощью скриптов. Просто следуйте некоторой дисциплине, чтобы иметь минимальную Java в JSP и почти нет вычислений и логики на странице JSP.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%//instantiate a JSP controller
MyController clr = new MyController(request, response);

//process action if any
clr.process(request);

//process page forwaring if necessary

//do all variable assignment here
String showMe = clr.getShowMe();%>

<html>
    <head>
    </head>
    <body>
        <form name="frm1">
            <p><%= showMe %>
            <p><% for(String str : clr.listOfStrings()) { %>
            <p><%= str %><% } %>

            // and so on   
        </form>
    </body>
</html>

Как защитник: отключить скрипты для хорошего

Как еще один вопрос обсуждает, вы можете и всегда должны отключать скрипты в вашем web.xml веб-приложения web.xml .

Я всегда делал это, чтобы любой разработчик не добавлял сценарии, особенно в крупных компаниях, где рано или поздно вы потеряете обзор. Настройки web.xml выглядят следующим образом:

<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
     <scripting-invalid>true</scripting-invalid>
  </jsp-property-group>
</jsp-config>

JSTL предлагает теги для условных выражений, циклов, наборов, наборов и т. Д. Например:

<c:if test="${someAttribute == 'something'}">
   ...
</c:if>

JSTL работает с атрибутами запроса - они чаще всего задаются в запросе сервлетом, который пересылается в JSP.


Используя теги JSTL вместе с выражением EL, вы можете избежать этого. На странице jsp добавьте следующие вещи:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

Опыт показывает, что JSP имеет некоторые недостатки, один из которых трудно избежать смешивания разметки с фактическим кодом.

Если вы можете, подумайте о том, чтобы использовать специализированную технологию для того, что вам нужно сделать. В Java EE 6 есть JSF 2.0, который обеспечивает множество приятных функций, включая склеивание Java-компонентов вместе с страницами JSF с помощью подхода #{bean.method(argument)} .


Ничто из этого больше не используется моим другом, мой совет - отделить представление (css, html, javascript и т. Д.) От сервера.

В моем случае я использую свои системы, обрабатывающие представление с помощью Angular, и любые необходимые данные приводятся с сервера с использованием служб отдыха.

Поверьте мне, это изменит ваш дизайн


Научитесь настраивать и писать свои собственные теги с помощью JSTL

Обратите внимание, что EL является EviL (исключения времени выполнения, рефакторинг)
Калитка может быть и злой (производительность, трудная для небольших приложений или простой уровень обзора)

Пример из java2s ,

Это необходимо добавить в web.xml веб-приложения

<taglib>
    <taglib-uri>/java2s</taglib-uri>
    <taglib-location>/WEB-INF/java2s.tld</taglib-location>
</taglib>

создайте файл: java2s.tld в / WEB-INF /

<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
   "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<!-- a tab library descriptor -->
<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">
    <tlib-version>1.0</tlib-version>
    <jsp-version>1.2</jsp-version>
    <short-name>Java2s Simple Tags</short-name>

    <!-- this tag manipulates its body content by converting it to upper case
    -->
    <tag>
        <name>bodyContentTag</name>
        <tag-class>com.java2s.BodyContentTag</tag-class>
        <body-content>JSP</body-content>
        <attribute>
          <name>howMany</name>
        </attribute>
    </tag>
</taglib>

скомпилируйте следующий код в WEB-INF \ classes \ com \ java2s

package com.java2s;

import java.io.IOException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class BodyContentTag extends BodyTagSupport{
    private int iterations, howMany;

    public void setHowMany(int i){
        this.howMany = i;
    }

    public void setBodyContent(BodyContent bc){
        super.setBodyContent(bc);
        System.out.println("BodyContent = '" + bc.getString() + "'");
    }

    public int doAfterBody(){
        try{    
            BodyContent bodyContent = super.getBodyContent();
            String bodyString  = bodyContent.getString();
            JspWriter out = bodyContent.getEnclosingWriter();

            if ( iterations % 2 == 0 ) 
                out.print(bodyString.toLowerCase());
            else
                out.print(bodyString.toUpperCase());

            iterations++;
            bodyContent.clear(); // empty buffer for next evaluation
        }
        catch (IOException e) {
            System.out.println("Error in BodyContentTag.doAfterBody()" + e.getMessage());
            e.printStackTrace();
        } // end of catch

        int retValue = SKIP_BODY;

        if ( iterations < howMany ) 
            retValue = EVAL_BODY_AGAIN;

        return retValue;
    }
}

Запустите сервер и загрузите bodyContent.jsp в браузере.

<%@ taglib uri="/java2s" prefix="java2s" %>
<html>
    <head>
        <title>A custom tag: body content</title>
    </head>
    <body>
        This page uses a custom tag manipulates its body content.Here is its output:
        <ol>
            <java2s:bodyContentTag howMany="3">
            <li>java2s.com</li>
            </java2s:bodyContentTag>
        </ol>
    </body>
</html>

Wicket также является альтернативой, которая полностью отделяет java от html, поэтому разработчик и программист могут работать вместе и на разных наборах кода, не понимая друг друга.

Посмотри на Калитку.


Как избежать Java-кода в JSP-файлах?

Вы можете использовать теги библиотеки табуляции, такие как JSTL, в дополнение к языку выражений ( EL ). Но EL не работает с JSP. Поэтому, вероятно, лучше полностью отказаться от JSP и использовать Facelets .

Facelets - это первый язык декларации страницы, не предназначенный для JSP, разработанный для JSF (Java Server Faces), который предоставил разработчикам JSF более простую и более мощную модель программирования по сравнению с JSP. Он решает различные проблемы, возникающие в JSP для разработки веб-приложений.


Вы можете использовать теги JSTL вместе с выражениями EL, чтобы избежать смешения Java и HTML-кода:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<html>
    <head>
    </head>
    <body>

        <c:out value="${x + 1}" />
        <c:out value="${param.name}" />
        // and so on

    </body>
</html>

Используйте JSTL Tag libraries в JSP, которые будут работать идеально.


Используйте основную, угловатую структуру javascript для дизайна пользовательского интерфейса и извлекайте данные, используя rest api. Это полностью устранит зависимость java от пользовательского интерфейса.


ArrayList расширяет AbstractList и реализует интерфейс List. ArrayList - это динамический массив.
Можно сказать, что он был создан в основном для преодоления недостатков массивов.

Класс LinkedList расширяет AbstractSequentialList и реализует интерфейс List, Deque и Queue.
Спектакль
arraylist.get()O (1), тогда linkedlist.get()как O (n)
arraylist.add()является O (1) и linkedlist.add()0 (1)
arraylist.contains()является O (n) и linkedlist.contains()O (n)
arraylist.next()является O (1) и linkedlist.next()O (1)
arraylist.remove()является O (n), тогда как linkedlist.remove()O (1)
В arraylist
iterator.remove()есть O (n),
тогда как в связанном списке
iterator.remove()O (1)





java jsp scriptlet