«Содержание

    1. Обзор 2. Страницы JavaServer 2.1. Синтаксис JSP 2.2. Статическое и динамическое содержимое 2.3. Неявные объекты 2.4. Другие неявные объекты 2.5. Директивы 2.6. Страничные директивы 3.0. Три примера 3.1. HTML, отображаемый в сервлете 3.2. Java в статическом содержимом JSP 3.3. JSP с переадресацией 3.4. Попробуйте! 4. Заключение

1. Обзор

JavaServer Pages (JSP) позволяет вводить динамическое содержимое в статическое содержимое с помощью Java и сервлетов Java. Мы можем делать запросы к сервлету Java, выполнять соответствующую логику и отображать определенное представление на стороне сервера для использования на стороне клиента. В этой статье представлен подробный обзор страниц JavaServer с использованием Java 8 и Jave 7 EE.

Мы начнем с изучения нескольких ключевых понятий, относящихся к JSP: а именно, разницы между динамическим и статическим содержимым, жизненного цикла JSP и синтаксиса JSP, а также директив и неявных объектов, созданных при компиляции!

2. Страницы JavaServer

Страницы JavaServer (JSP) позволяют передавать специфичные для Java данные или помещать их в представление .jsp и использовать на стороне клиента.

Файлы JSP по существу представляют собой файлы .html с дополнительным синтаксисом и несколькими небольшими первоначальными отличиями:

  1. the .html suffix is replaced with .jsp (it’s considered a .jsp filetype) and
  2. the following tag is added to the top of the .html markup elements:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

Давайте рассмотрим некоторые ключевые концепции JSP.

2.1. Синтаксис JSP

Есть два способа добавить код Java в .jsp. Во-первых, мы можем использовать базовый синтаксис Java Scriptlet, который включает размещение блоков кода Java в двух тегах Scriptlet:

<% Java code here %>

Второй метод специфичен для XML:

<jsp:scriptlet>
    Java code here
</jsp:scriptlet>

Важно отметить, что можно использовать условную логику на стороне клиента с JSP. используя предложения if, then и else, а затем заключая соответствующие блоки разметки в эти скобки.

<% if (doodad) {%>
    <div>Doodad!</div>
<% } else { %>
    <p>Hello!</p>
<% } %>

Например, если doodad имеет значение true, мы отобразим первый элемент div, в противном случае мы отобразим второй элемент p!

2.2. Статическое и динамическое содержимое

Статическое веб-содержимое — это фиксированные активы, которые используются независимо от запросов RESTful, SOAP, HTTP, HTTPS или другой информации, предоставленной пользователем.

Статическое содержимое, однако, является фиксированным и не изменяется пользовательским вводом. Динамическое веб-содержимое — это те активы, которые реагируют, модифицируются или изменяются в свете действий или информации пользователя!

Технология JSP позволяет четко разделить обязанности между динамическим и статическим содержимым.

Сервер (сервлет) управляет динамическим содержимым, а клиент (фактическая страница .jsp) является статическим контекстом, в который вводится динамическое содержимое.

Давайте взглянем на неявные объекты, созданные JSP и позволяющие вам получить доступ к данным, относящимся к JSP, на стороне сервера!

2.3. Неявные объекты

Неявные объекты генерируются механизмом JSP автоматически во время компиляции.

Неявные объекты включают объекты HttpRequest и HttpResponse и предоставляют различные серверные функции для использования в вашем сервлете и для взаимодействия с вашим .jsp! Вот список создаваемых неявных объектов:

request request принадлежит классу javax.servlet.http.HttpServletRequest. Объект запроса предоставляет все данные, введенные пользователем, и делает их доступными на стороне сервера.

response response принадлежит классу javax.servlet.http.HttpServletResponse и определяет, что передается на клиентскую сторону после выполнения запроса.

Давайте подробнее рассмотрим неявные объекты запроса и ответа, так как они являются наиболее важными и часто используемыми.

Пример ниже демонстрирует очень простой, неполный метод сервлета для обработки запросов GET. Я опустил большую часть деталей, чтобы мы могли сосредоточиться на том, как использовать объекты запроса и ответа:

protected void doGet(HttpServletRequest request, 
  HttpServletResponse response) throws ServletException, IOException {
    String message = request.getParameter("message");
    response.setContentType("text/html");
    . . .
}

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

Мы можем получить доступ к параметрам запроса, используя функцию .getParameter(). Выше мы фиксируем параметр сообщения и инициализируем строковую переменную, чтобы мы могли использовать ее в нашей логике на стороне сервера. Мы также можем получить доступ к объекту ответа, который определяет, какие и как данные будут переданы в представление.

«Сверху устанавливаем на него тип контента. Нам не нужно возвращать объект ответа, чтобы его полезная нагрузка отображалась на странице JSP при рендеринге!

out out принадлежит классу javax.servlet.jsp.JspWriter и используется для записи содержимого клиенту.

Существует как минимум два способа печати на JSP-странице, и здесь стоит обсудить оба. out создается автоматически и позволяет вам писать в память, а затем в объект ответа:

out.print(“hello”);
out.println(“world”);

Вот и все!

Второй подход может быть более производительным, так как позволяет вам писать непосредственно в объект ответа! Здесь мы используем PrintWriter:

PrintWriter out = response.getWriter();
out.println("Hello World");

2.4. Другие неявные объекты

Вот некоторые другие неявные объекты, которые тоже полезно знать!

сеанс сеанса принадлежит классу javax.servlet.http.HttpSession, который хранит пользовательские данные в течение всего сеанса.

приложение приложение принадлежит классу javax.servlet.ServletContext хранит параметры приложения, установленные при инициализации или к которым необходимо получить доступ для всего приложения.

исключение exception принадлежит классу javax.servlet.jsp.JspException используется для отображения сообщений об ошибках на страницах JSP, которые имеют тег \u003c%@ page isErrorPage=“true” %\u003e.

страница страница принадлежит классу java.lang.Object позволяет получить доступ или сослаться на текущую информацию о сервлете.

pageContext pageContext принадлежит классу javax.servlet.jsp.PageContext по умолчанию относится к области страницы, но может использоваться для доступа к атрибутам запроса, приложения и сеанса.

config config принадлежит классу javax.servlet.ServletConfig — это объект конфигурации сервлета, позволяющий получить контекст, имя и параметры конфигурации сервлета.

Теперь, когда мы рассмотрели неявные объекты, предоставляемые JSP, давайте обратимся к директивам, которые позволяют страницам .jsp (косвенно) обращаться к некоторым из этих объектов.

2.5. Директивы

JSP предоставляет стандартные директивы, которые можно использовать для определения основных функций наших файлов JSP. Директивы JSP состоят из двух частей: (1) сама директива и (2) атрибут этой директивы, которому присваивается значение.

Три вида директив, на которые можно ссылаться с помощью тегов директив: \u003c%@ page … %\u003e, которая определяет зависимости и атрибуты JSP, включая тип контента и язык, \u003c%@ include … %\u003e, которая указывает импорт или файл, который будет использоваться, и \u003c%@ taglib …%\u003e, который указывает библиотеку тегов, определяющую пользовательские действия, которые будут использоваться страницей.

Итак, например, директива страницы может быть указана с использованием тегов JSP следующим образом: \u003c%@ атрибут страницы=“значение” %\u003e

И мы можем сделать это с помощью XML следующим образом: \u003c jsp:directive.page attribute=“значение” /\u003e

2.6. Атрибуты директивы страницы

В директиве страницы можно объявить множество атрибутов:

autoFlush \u003c%@ page autoFlush=“false” %\u003e

autoFlush контролирует вывод буфера, очищая его, размер буфера достигнут. Значение по умолчанию верно.

буфер \u003c%@ page buffer=“19kb” %\u003e

buffer задает размер буфера, используемого нашей JSP-страницей. Значение по умолчанию — 8 КБ.

errorPage \u003c%@ page errorPage=“errHandler.jsp” %\u003e

errorPage указывает страницу JSP как страницу ошибки.

extends \u003c%@ page extends=’org.apache.jasper.runtime.HttpJspBase’ %\u003e

extends указывает суперкласс соответствующего кода сервлета.

info \u003c%@ page info=“Это мой JSP!” %\u003e

info используется для установки текстового описания для JSP.

isELIgnored \u003c%@ page isELIgnored=“true” %\u003e

isELIGnored указывает, будет ли страница игнорировать язык выражений (EL) в JSP. EL позволяет уровню представления взаимодействовать с управляемыми компонентами Java и делает это с использованием синтаксиса ${…}, и хотя мы не будем вдаваться в подробности EL здесь, ниже приведено несколько примеров, которых достаточно для построения нашего пример JSP-приложения! Значение по умолчанию для isELIGnored — false.

isErrorPage \u003c%@ page isErrorPage=“true” %\u003e

«isErrorPage сообщает, является ли страница страницей с ошибкой. Мы должны указать страницу ошибки, если мы создаем обработчик ошибок для нашей страницы в приложении.

isThreadSafe \u003c%@ page isThreadSafe=“false” %\u003e

isThreadSafe имеет значение по умолчанию true. isThreadSafe определяет, может ли JSP использовать многопоточность сервлета. В общем, вы никогда не захотите отключить эту функцию.

язык \u003c%@ page language=“java” %\u003e

язык определяет, какой язык сценариев использовать в JSP. Значение по умолчанию — Java.

session \u003c%@ page session=“значение” %\u003e

session определяет, следует ли поддерживать сеанс HTTP. По умолчанию он равен true и принимает значения true или false.

trimDirectiveWhitespaces \u003c%@ page trimDirectiveWhitespaces = «true» %\u003e

trimDirectiveWhitespaces удаляет пробелы на странице JSP, сжимая код в более компактный блок во время компиляции. Установка этого значения в true может помочь уменьшить размер кода JSP. Значение по умолчанию неверно.

3. Три примера

Теперь, когда мы рассмотрели основные концепции JSP, давайте применим эти концепции к некоторым базовым примерам, которые помогут вам настроить и запустить ваш первый сервлет, обслуживающий JSP!

Существует три основных способа внедрить Java в .jsp, и мы рассмотрим каждый из них ниже, используя встроенные функции в Java 8 и Jakarta EE.

Во-первых, мы отобразим нашу разметку на стороне сервера для отображения на стороне клиента. Во-вторых, мы рассмотрим, как добавить код Java непосредственно в наш файл .jsp независимо от объектов запроса и ответа javax.servlet.http.

В-третьих, мы продемонстрируем, как перенаправить HttpServletRequest на конкретный .jsp и привязать к нему Java, обработанный на стороне сервера.

Давайте настроим наш проект в Eclipse, используя тип File/New/Project/Web/Dynamic web project/ для размещения в Tomcat! После создания проекта вы должны увидеть:

|-project
  |- WebContent
    |- META-INF
      |- MANIFEST.MF
    |- WEB-INF
      |- lib
      |- src

Мы добавим несколько файлов в структуру приложения, чтобы в итоге получилось:

|-project
  |- WebContent
    |- META-INF
      |- MANIFEST.MF
    |- WEB-INF
      |-lib
      *-web.xml
        |- ExampleTree.jsp
        |- ExampleTwo.jsp
        *- index.jsp
      |- src
        |- com
          |- baeldung
            *- ExampleOne.java
            *- ExampleThree.java

Давайте настроим index.jsp, который будет отображаться когда мы обращаемся к контексту URL в Tomcat 8:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>JSP Examples</title>
    </head>
    <body>
        <h1>Simple JSP Examples</h1>
        <p>Invoke HTML rendered by Servlet: <a href="ExampleOne" target="_blank">here</a></p>
        <p>Java in static page: <a href="ExampleTwo.jsp" target="_blank">here</a></p>
        <p>Java injected by Servlet: <a href="ExampleThree?message=hello!" target="_blank">here</a></p>
    </body>
</html>

Есть три a, каждая из которых ссылается на один из примеров, которые мы рассмотрим ниже в разделах с 4.1 по 4.4.

Нам также нужно убедиться, что у нас настроен наш файл web.xml:

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
    <servlet-name>ExampleOne</servlet-name>
    <servlet-class>com.baeldung.ExampleOne</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ExampleOne</servlet-name>
    <url-pattern>/ExampleOne</url-pattern>
</servlet-mapping>

Основное замечание здесь — как правильно сопоставить каждый из наших сервлетов с конкретным отображением сервлетов. При этом каждый сервлет связывается с определенной конечной точкой, где он может использоваться! Теперь мы пройдемся по всем остальным файлам ниже!

3.1. HTML-рендеринг в сервлете

В этом примере мы фактически пропустим создание файла .jsp!

Вместо этого мы создадим строковое представление нашей разметки, а затем запишем его в ответ GET с помощью PrintWriter после того, как сервлет ExampleOne получит запрос GET:

public class ExampleOne extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request, 
    HttpServletResponse response) throws ServletException, IOException {
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      out.println(
	"<!DOCTYPE html><html>" +
	"<head>" +
	"<meta charset=\"UTF-8\" />" +
	"<title>HTML Rendered by Servlet</title>" +
	"</head>" +
	"<body>" +
	"<h1>HTML Rendered by Servlet</h1></br>" +
	"<p>This page was rendered by the ExampleOne Servlet!</p>" +
	"</body>" +
	"</html>"
     );
   }
}

Здесь мы вводим нашу разметку через наша обработка запроса сервлета напрямую. Вместо тега JSP мы генерируем наш HTML вместе со всеми специфичными для Java данными, которые нужно вставить, исключительно на стороне сервера без статического JSP!

Ранее мы рассмотрели объект out, который является функцией JspWriter.

Выше я использовал вместо этого объект PrintWriter, который пишет непосредственно в объект ответа.

JspWriter фактически буферизует строку для записи в память, которая затем записывается в объекты ответа после очистки буфера в памяти.

PrintWriter уже подключен к объекту ответа. По этим причинам я предпочел писать непосредственно в объект ответа в примерах выше и ниже.

3.2. Java в статическом содержимом JSP

Здесь мы создаем файл JSP с именем ExampleTwo.jsp с тегом JSP. Как видно выше, это позволяет добавлять Java непосредственно в нашу разметку. Здесь мы случайным образом печатаем элемент String[]:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
    <head>
        <title>Java in Static Page Example</title>
    </head>
    <body>
        <h1>Java in Static Page Example</h1>
	    <% 
              String[] arr = {"What's up?", "Hello", "It's a nice day today!"}; 
	      String greetings = arr[(int)(Math.random() * arr.length)];	
            %>
        <p><%= greetings %></p>
    </body>
</html>

Выше вы увидите это объявление переменной в объектах тегов JSP: тип variableName и инициализация, как в обычной Java.

«Я включил приведенный выше пример, чтобы продемонстрировать, как добавить Java на статическую страницу, не прибегая к конкретному сервлету. Здесь Java просто добавляется на страницу, а жизненный цикл JSP позаботится обо всем остальном.

3.3. JSP с пересылкой

А теперь последний и самый сложный пример! Здесь мы собираемся использовать аннотацию @WebServlet в ExampleThree, которая устраняет необходимость сопоставления сервлетов в server.xml.

@WebServlet(
  name = "ExampleThree",
  description = "JSP Servlet With Annotations",
  urlPatterns = {"/ExampleThree"}
)
public class ExampleThree extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
      String message = request.getParameter("message");
      request.setAttribute("text", message);
      request.getRequestDispatcher("/ExampleThree.jsp").forward(request, response);
   }
}

ExampleThree принимает параметр URL, переданный в качестве сообщения, привязывает этот параметр к объекту запроса, а затем перенаправляет этот объект запроса в ExampleThree.jsp.

Таким образом, мы не только создали по-настоящему динамичный веб-интерфейс, но и сделали это в приложении, содержащем несколько файлов .jsp.

getRequestDispatcher().forward() — это простой способ убедиться, что отображается правильная страница .jsp.

Все данные, привязанные к объекту запроса, отправленному его (файлу .jsp), будут отображаться! Вот как мы обрабатываем последнюю часть:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
    <head>
        <title>Java Binding Example</title>
    </head>
    <body>
        <h1>Bound Value</h1>
	    <p>You said: ${text}</p>
    </body>
</html>

Обратите внимание на тег JSP, добавленный в начало файла ExampleThree.jsp. Вы заметите, что я поменял теги JSP здесь. Я использую язык выражений (о котором я упоминал ранее) для отображения нашего установленного параметра (который связан как ${text})!

3.4. Попробуйте!

Теперь мы экспортируем наше приложение в .war для запуска и размещения в Tomcat 8! Найдите свой server.xml, и мы обновим наш контекст до:

<Context path="/spring-mvc-xml" docBase="${catalina.home}/webapps/spring-mvc-xml">
</Context>

Что позволит нам получить доступ к нашим сервлетам и JSP на локальном хосте: 8080/spring-mvc-xml/jsp/index.jsp! Возьмите рабочую копию по адресу: GitHub. Поздравляю!

4. Заключение

Мы рассмотрели довольно много материала! Мы узнали, что такое страницы JavaServer, для чего они были введены, их жизненный цикл, как их создавать и, наконец, несколько различных способов их реализации!

На этом введение в JSP завершено! Будьте здоровы и кодируйте!