Jakarta Servlet

Problem

  • Как разрабатывать сервер на Java?

  • В частности: при взаимодействии по HTTP

Solution

Jakarta EE

Jakarta Servlet

Основы

What is Jakarta Servlet?

  • Компонент Jakarta EE

  • Спецификация

  • Для работы необходим Servlet container

What is Jakarta Servlet?

  • Java-класс

  • Работает на стороне сервера

  • Обрабатывает запросы клиентов и динамически генерирует ответы на них

  • Если запросы отсутствуют – находится в состоянии ожидания

Servlet Container

  • Программа, являющаяся сервером

  • Обеспечивает жизненный цикл Servlet в соответствии со спецификацией

  • Обеспечивает обмен данными между Servlets и клиентами, а также между различными Servlets

  • Apache Tomcat - servlet container

Servlet API

  • Классы для работы с Servlets находятся в библиотеке servlet-api.jar, которой нет в поставке JDK.

  • Разработчик загружает servlet-api.jar в проект самостоятельно или используя различные инструменты.

  • servlet-api.jar присутствует в директории lib сервера Apache Tomcat.

Servlet Hierarchy

Servlet Hierarchy

Servlet Architecture

Servlet Application Architecture

Servlet Application Architecture

Servlet Application Architecture

Simple Servlet

Web app directory structure

Servlet Application Architecture

HttpServlet methods

  • doGet()

  • doPost()

  • doPut()

  • doDelete()

  • doOptions()

  • doHead()

  • doTrace()

HttpServlet methods

public abstract class HttpServlet extends GenericServlet {
    protected void doGet(HttpServletRequest req,
                        HttpServletResponse resp)
            throws ServletException, IOException {
        // ...
    }
}

HelloServlet

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req,
            HttpServletResponse resp)
        throws ServletException, IOException {
        resp.setContentType("text/html");
        PrintWriter writer = resp.getWriter();
        writer.write("<p><span style='color: blue;'>" +
            "Hello, world!" +
            "</span></p>");
    }
}

Way 1: xml config with web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_4_0.xsd"
    version="4.0">

    <servlet>
        <servlet-name>MyCustomAnyNameForServlet</servlet-name>
        <servlet-class>classes.HelloServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>MyCustomAnyNameForServlet</servlet-name>
        <url-pattern>/sayhello</url-pattern>
    </servlet-mapping>
</web-app>

<servlet> in web.xml

<servlet>
    <servlet-name>MyCustomAnyNameForServlet</servlet-name>
    <servlet-class>classes.HelloServlet</servlet-class>
</servlet>
  • Задает внутреннее имя Servlet, по которому к нему можно обратиться в дескрипторе

  • Имя может быть совершенно произвольным

<servlet-mapping> in web.xml

<servlet-mapping>
    <servlet-name>MyCustomAnyNameForServlet</servlet-name>
    <url-pattern>/sayhello</url-pattern>
</servlet-mapping>
  • Привязывает Servlet к определенному суффиксу URL адреса, т.е. servlet-url-pattern

  • Полный адрес образуется следующим образом: ${tomcat-url}/${project-name}/${servlet-url-pattern}

  • Пример: http://localhost:8080/myApp/test

Way 2: annotation @WebServlet

С выходом Servlet Api 3.0 и Tomcat 7 можно производить регистрацию Servlet не используя файл web.xml, а используя аннотацию @WebServlet:

@WebServlet(
        name = "MyCustomAnyNameForServlet",
        urlPatterns = {"/my-custom-url-pattern"}
)
public class HelloWorldServlet extends HttpServlet {
    // servlet code
}

How works it?

Web dynamic app

Servlet Lifecycle

Servlet methods

public interface Servlet {
    void init(ServletConfig config) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

Servlet Lifecycle

Servlet Lifecycle

Servlet Lifecycle

Servlet Lifecycle

JVM and Servlet Container

JVM and Servlet Container

Read data from HTTP client

Where is data?

  • HTTP Path Parameters

  • HTTP Query Parameters

  • HTTP Headers

  • HTTP Request body

HTTP Path Parameters

@WebServlet("/example/reader/path/*")
public class HttpPathParametersReaderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String pathInfo = req.getPathInfo();
        String bodyAsJson = "{\n" +
                "\t\"pathInfo\":\"" + pathInfo + "\"\n" +
                "}";

        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        writer.write(bodyAsJson);
    }
}

HTTP Query Parameters

@WebServlet("/example/reader/query-params")
public class HttpQueryParametersReaderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Enumeration<String> parameterNames = req.getParameterNames();

        StringBuffer sb = new StringBuffer();
        sb.append("{\n");

        while (parameterNames.hasMoreElements()) {
            String parameterName = parameterNames.nextElement();
            sb.append("\t\"")
                    .append(parameterName)
                    .append("\": \"")
                    .append(req.getParameter(parameterName))
                    .append("\",\n");
        }
        String bodyAsJson = (sb.length() == 2)
                ? "{}"
                : sb.substring(0, sb.length() - 2) + "\n}";

        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        writer.write(bodyAsJson);
    }
}

HTTP Headers

@WebServlet("/example/reader/headers")
public class HttpHeadersReaderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Enumeration<String> parameterNames = req.getHeaderNames();

        StringBuilder sb = new StringBuilder();

        while (parameterNames.hasMoreElements()) {
            String headerName = parameterNames.nextElement();
            sb.append("\t\"")
                    .append(headerName)
                    .append("\": \"")
                    .append(req.getHeader(headerName))
                    .append("\",\n");
        }
        String bodyAsJson = (sb.length() == 2)
                ? "{}"
                : "{\n" + sb.substring(0, sb.length() - 2) + "\n}";

        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json");
        PrintWriter writer = resp.getWriter();
        writer.write(bodyAsJson);
    }
}

HTTP Request body

Лучше будет показать :)