Zielony Smok - logo witryny

Java 11: Budowa aplikacji serwerowej do testowania HTTP/2

Budowa aplikacji serwerowej do testowania HTTP/2

Wstępny opis

Nasza aplikacja ma strukturę przedstawiona na Rys. 140:

Aplikacja serwerowa
Rys. 140. Struktura aplikacji

Na razie jest to klasyczna aplikacja składająca się z 2 stron JSP i serwletu.

Na stronie getfibo.jsp znajduje się formularz, w którym klient wpisuje, który wyraz ciągu Fibonacciego należy obliczyć.

Dane z formularza przekazywane są na serwer do serwletu. Serwlet weryfikuje dane i oblicza podany wyraz ciągu. Wynik obliczenia jest wpisywany na stronie wynikfibo.jsp i wysyłany do przeglądarki klienta.

Strony JSP są wyłącznie dla celów testowych. Przeglądarka jest niezbędna do pracy ze stronami JSP.

Naszym końcowym zadaniem będzie budowa aplikacji Java, która zastąpi przeglądarkę i strony JSP, łącząc się z serwerem przy użyciu protokołu HTTP/2.

Do budowy aplikacji i wstępnych testów użyłam Netbeans 8.2 działających na JDK 8u191 i sprzężonych z Tomcatem 8.0.27. Wygenerowany plik fiboservlet.war zostanie umieszczony na serwerze Tomcat 9.0.12 działającym na OpenJDK-11 – również jako serwer lokalny. Jest to niezbędne ze względu na to, że protokół HTTP/2 jest obsługiwany (w tym module i pakiecie) dopiero od Java 11.

Aplikacja końcowa zostanie napisana w IntelliJ IDEA v. Community z wykorzystaniem OpenJDK-11.

Pliki

context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/fiboservlet"/>
Plik fibo.css
#content2 {
    font-family: Arial, Helvetica, sans-serif;
    width: 400px;
    margin: 10px auto;
    padding: 5px 20px;
    background: #FFFFFF;
    border: 1px solid #000000;
}
.center { text-align: center; }
fieldset {
    margin-top: 1em;
    margin-bottom: 1em;
}
legend {
    color: black;
    font-weight: bold;
    font-size: 85%;
}
.formLayout {
    padding-top: 1em;
}
.formLayout label {
    float: left;
    width: 10em;
    text-align: right;
}
.formLayout input, .formLayout select {
    margin-left: 0.5em;
    margin-bottom: 0.5em;
}
.formLayout select {
    width: 11em;
}
.formLayout br {
    clear: both;
}
.error {
    color: red;
}
.notice {
    color: red;
    font-size: 67%;
    text-align: right;
}
Plik web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:jsp="http://java.sun.com/xml/ns/javaee/jsp"
         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         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-app_3_0.xsd">
    <servlet>
        <servlet-name>FiboServlet</servlet-name>
        <servlet-class>fibo.FiboServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FiboServlet</servlet-name>
        <url-pattern>/fibo</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <session-config>
        <session-timeout>10</session-timeout>
    </session-config>
</web-app>
getfibo.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <link rel="stylesheet" type="text/css" href="styles/fibo.css">
        <title>Podaj numer wyrazu ciągu Fibonacciego</title>
    </head>
    <body>
        <div id="page1">
            <div id="content2">
                <p class="notice">Podaj numer ≤ 100 000</p>
                <form action="fibo" method="get" name="fibo_form" id="fibo_form">
                    <fieldset>
                        <legend>Numer wyrazu ciągu Fibonacciego</legend>
                        <div class="formLayout">
                            <label for="fibon">Numer:</label>
                            <input type="text" name="fibon" id="fibon"
                                   value="${fibon}" size="20"
                                   maxlength="60"> <font size="2"
                                   color="#FF0000">${wiadFibo}</font><br>
                        </div>
                    </fieldset>
                    <fieldset>
                        <legend>Podaj wynik</legend>
                        <div class="formLayout">
                            <label> </label>
                            <input type="submit" id="register" value="Oblicz">
                        </div>
                    </fieldset>
                </form>
            </div>
        </div>
    </body>
</html>
wynikfibo.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <link rel="stylesheet" type="text/css" href="styles/fibo.css">
        <title>Twoje wyniki</title>
    </head>
    <body>
        <div>
            <p><%=session.getAttribute("fibon")%> wyraz ciągu Fibonacciego</p>
            <p><%=session.getAttribute("fibofull")%></p>
        </div>
    </body>
</html>
FiboServlet.java
package fibo;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class FiboServlet extends HttpServlet {
    protected void doProcess(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        HttpSession session;
        RequestDispatcher dispatcher;
        String url;
        String fi = request.getParameter("fibon");
        String wiadFibo = VerifyFibo.isFibo(fi);
        if (wiadFibo.length() > 0) {
            url = "/getfibo.jsp";
            session = request.getSession();
            session.setAttribute("wiadFibo", wiadFibo);
            dispatcher = getServletContext().getRequestDispatcher(url);
            dispatcher.forward(request, response);
            session.invalidate();
        } else {
            session = request.getSession();
            session.setAttribute("fibon", fi);
            session.setAttribute("fibofull", FiboUtil.fibonacci(Long.parseLong(fi)));
            url = "/wynikfibo.jsp";
            dispatcher = getServletContext().getRequestDispatcher(url);
            dispatcher.forward(request, response);
        }
    }
    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }
}
FiboUtil.java
package fibo;
import java.math.BigInteger;
public class FiboUtil {
    private FiboUtil() {
    }
    public static String fibonacci(long n) {
        BigInteger[] tabl = {BigInteger.ONE, BigInteger.ONE, BigInteger.ONE,
            BigInteger.ZERO};
        BigInteger[] tablKonc = {BigInteger.ONE, BigInteger.ONE, BigInteger.ONE,
            BigInteger.ZERO};
        if (n == 0) {
            return BigInteger.ZERO.toString();
        }
        if (n == 1) {
            return BigInteger.ONE.toString();
        }
        for (long i = 0; i < n; i++) {
            tablKonc = multi(tablKonc, tabl);
        }
        return tablKonc[3].toString();
    }
    /**
     * z domeny publicznej 'Wikipedii'
     */
    private static BigInteger[] multi(BigInteger[] a, BigInteger[] b) {
        BigInteger[] t = new BigInteger[4];
        t[0] = (a[0].multiply(b[0])).add(a[1].multiply(b[2]));
        t[1] = (a[0].multiply(b[1])).add(a[1].multiply(b[3]));
        t[2] = (a[2].multiply(b[0])).add(a[3].multiply(b[2]));
        t[3] = (a[2].multiply(b[1])).add(a[3].multiply(b[3]));
        return t;
    }
}
VerifyFibo.java
package fibo;
public class VerifyFibo {
    public static final String GIVE_NUMBER = " Podaj numer. ";
    public static final String IMPR_NUMBER = " Nieprawidłowy numer. ";
    private VerifyFibo() {
    }
    public static String isFibo(String fibo) {
        if (fibo == null || fibo.length() == 0) {
            return GIVE_NUMBER;
        }
        if (Long.parseLong(fibo) < 0 || Long.parseLong(fibo) > 100000L) {
            return IMPR_NUMBER;
        }
        return "";
    }
}

Testowanie aplikacji

Gdy w Netbeans klikniemy dwukrotnie plik getfibo.jsp i z rozwijanego menu wybierzemy
Run File zostanie uruchomiony serwer Tomcat, a ustawiona przeglądarka wyświetli
formularz (Rys. 141)

Aplikacja serwerowa
Rys.141. Widok formularza

Po wpisaniu liczby np. 30 i kliknięciu przycisku Oblicz wpisana liczba zostanie
przekazana do serwera, serwlet wykona obliczenie, a w przeglądarce, na stronie wynikfibo.jsp pokaże się wynik (Rys 142).

Aplikacja serwerowa
Rys.142. Wynik obliczenia

Jeśli ciągle mamy uruchomiony serwer Tomcat możemy zignorować stronę JSP i używając dowolnej przeglądarki połączyć się bezpośrednio z aplikacja na serwerze. W pasek adresu wpisujemy (Rys. 143)

Aplikacja serwerowa
Rys.143. Pasek adresu

Otrzymamy dokładnie taki sam wynik.

Plik fiboservlet.war

Gdy w oknie aplikacji w Netbeans klikniemy Run/Click and Build Project (fiboservlet) i zmienimy zakładkę Projects na Files w folderze dist zobaczymy plik fiboservlet.war (Rys. 144).

Aplikacja serwerowa
Rys.144. Położenie pliku fiboservlet.war

Użyjemy tego pliku w następnym etapie.

Servlet w akcji możesz obejrzeć i wypróbować tutaj: “http://javer.org/fiboservlet/” – jednak pamiętaj, że mój serwer jest przez większość czasu wyłączony, ze względu na koszty energii elektrycznej :-).

Zajrzyj też Java 11: HTTP Client (Standard)

Kompletną aplikację Apache Netbeans 15 dla Apache 10.0.23 znajdziesz tutaj.

Aplikację umieściłem na własnym serwerze, czynnym okresowo ze względu na koszty energii elektrycznej: fiboserlet