JavaRush /Java Blog /Random-JA /Java での Web アプリケーション
Viacheslav
レベル 3

Java での Web アプリケーション

Random-JA グループに公開済み
Java での Web アプリケーション - 1

導入

かつて、Java は Web アプリケーションを優先事項として選択したという事実により、その地位を強化しました。Java は初期の頃から、その道を見つけるのに苦労してきました。まず、アプレットを提案しました。これにより、開発者は静的な HTML ページ上に動的なコンテンツ (コンテンツ) を作成する機会が数多く提供されました。しかし、アプレットは、セキュリティ、オーバーヘッドなどの多くの理由により期待に応えられませんでした。そこで Java 言語の開発者は、代替となるサーブレット APIを提案しました。そしてそれは正しい決断だったことが判明した。 サーブレット API は、 Web ベースのアプリケーションであっても、要求に応じて情報を返す Web サービスであっても、Java Web アプリケーションを構築するための仕様です。したがって、Java Web アプリケーションがどのように動作するかを理解するための道は、サーブレット API を理解することから始まります。
Java での Web アプリケーション - 2

サーブレットAPI

つまり、サーブレット API は、言語開発者が Java 開発者に提供したものです。サーブレット API は、私たちの主な質問に答える仕様です。これは、「JSR-000340 JavaTM Servlet 3.1 Final Release for Evaluation」で見つけることができます。「 1.1 サーブレットとは?」の章では、サーブレットは動的コンテンツ (コンテンツ) を作成する Java テクノロジに基づくWeb コンポーネントであると述べています。「Java ベース」とは、サーブレットがバイトコードにコンパイルされた Java クラスであることを意味します。サーブレットは、サーブレット コンテナ (サーブレット エンジンとも呼ばれます) によって管理されます。サーブレット コンテナは、サーブレット機能を提供する Web サーバー拡張機能です。次に、サーブレットは、サーブレット コンテナによって実装される要求/応答パラダイムでクライアントとの対話を提供します。「 1.2 サーブレット コンテナとは?」の章では、サーブレット コンテナは、リクエストと応答が送信され、MIME ベースのリクエストと応答が生成および処理されるネットワーク サービスを提供する Web サーバーまたはアプリケーション サーバーの一部であると説明されています。 。さらに、サーブレット コンテナはサーブレットのライフ サイクルを管理します (つまり、サーブレットをいつ作成するか、いつ削除するかを決定します)。すべてのサーブレット コンテナは、リクエストを受信し、応答を送信するために HTTP プロトコルをサポートする必要があります。ここで、MIME は標準であり、インターネット上で送信できるように情報をどのようにエンコードし、メッセージをフォーマットするかを規定する仕様であることを付け加えておきます。
Java での Web アプリケーション - 3

Webサーバー

Web サーバーは、クライアントから HTTP 要求を受け取り、HTTP 応答 (通常は HTML ページ、画像、ファイル、またはその他のデータとともに) をクライアントに提供するサーバーです。要求されたリソースは URL によって識別されます。サーブレット API をサポートする最も人気のある Web サーバーの 1 つは、Apache Tomcatです。ほとんどの Web サーバーは、さまざまなコンポーネントで構成される複雑なマシンであり、それぞれが特定の機能を実行します。例えば:
Java での Web アプリケーション - 4

コネクタ

— 入力には、クライアントからの受信リクエストを受け入れるコネクタ (つまり、コネクタ) があります。Tomcat の HTTP コネクタは、「Coyote」コンポーネントを使用して実装されます。コネクタはクライアントからデータを受信し、それを Tomcat エンジンに渡します。 サーブレット コンテナ- Tomcat エンジンは、サーブレット コンテナである「Catalina」コンポーネントを使用して、クライアントから受信したリクエストを処理します。詳細については、Tomcat のドキュメント「アーキテクチャの概要」を参照してください。サーブレット API 仕様をサポートする Web サーバーは他にもあります。たとえば、「Jetty」や「Undertow」などです。それらのアーキテクチャは似ているため、あるサーブレット コンテナでの作業の原則を理解すれば、別のサーブレット コンテナでの作業に切り替えることができます。
Java での Web アプリケーション - 5

ウェブアプリケーション

したがって、Web アプリケーションを実行するには、サーブレット API をサポートする Web サーバー (つまり、Web サーバーのサーブレット API サポートを実装する拡張コンポーネントを持つ Web サーバー) が必要です。大丈夫。そもそも Web アプリケーションとは何ですか? サーブレット API 仕様の「 10 Web アプリケーション」の章 によれば、 Web アプリケーションは、 Web サーバー上の最終アプリケーションを構成するサーブレット、HTML ページ、クラス、およびその他のリソースのコレクションです。「 10.6 Web アプリケーション アーカイブ ファイル」の章によれば、Web アプリケーションは Web ARchive (WAR 拡張子を持つアーカイブ) にパッケージ化できます。「用語集-219」ページに記載されているとおり:
Java での Web アプリケーション - 6
つまり、これが Web アプリケーションであることを示すために、JAR の代わりに WAR が作成されます。次に重要な事実は、WAR アーカイブ内に特定のディレクトリ構造が必要であるということです。サーブレット API 仕様の「 10.5 ディレクトリ構造」の章。この章では、「WEB-INF」という特別なディレクトリがあると述べています。このディレクトリは、クライアントには見えず、クライアントに直接表示されないという点で特殊ですが、サーブレット コードからはアクセスできます。また、WEB-INF ディレクトリに何を含めることができるかについても説明します。
Java での Web アプリケーション - 7
このリスト全体から、デプロイメント記述子と呼ばれるweb.xmlファイルに関する項目がわかりません。それは何ですか?「 14. デプロイメント記述子」の章では、デプロイメント記述子について説明します。つまり、デプロイメント記述子は、 Web アプリケーションを Web サーバーにデプロイ (つまり、実行) する方法を記述する XML ファイルです。たとえば、デプロイメント記述子は、アプリケーションにアクセスするためにどの URL を使用する必要があるかを示し、アプリケーションに関連するセキュリティ設定などが示されます。「 14.2 デプロイメントを処理するためのルール」の章には、アプリケーションが構成されて起動される前に web.xml のスキーマが検証されると記載されています (つまり、web.xml の内容がスキーマに従って正しく書き込まれているかどうかのチェックが行われます)。 。そして、「 14.3 デプロイメント記述子」の章では、図がここにあることが示されています。 ファイルの内容を見ると、次のことがわかります。 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd
Java での Web アプリケーション - 8
XML ファイルに使用されるスキーマとは何ですか? スキーマは、XML ドキュメントに正しく記入する方法、つまり使用できる要素、要素に指定できるデータの種類、要素の順序、必須の要素などを示します。Java のスキーマは、特定のインターフェイスを満たす (つまり、特定のインターフェイスを実装する) クラスの記述方法も指定するため、XML ドキュメントのスキーマを Java のインターフェイスと比較できます。したがって、秘密の知識を身につけて、最初の Web アプリケーションを作成する準備が整いました。
Java での Web アプリケーション - 9

Web アプリケーションの作成

自動プロジェクト ビルド システムを使用せずに最新の Java アプリケーションを操作することを想像するのは困難です。最も人気のあるシステムには、Maven と Gradleがあります。このレビューでは Gradle を使用します。Gradleのインストール方法は公式サイトに記載されています。新しいアプリケーションを作成するには、Gradle に組み込まれたプラグイン「Build Init Plugin」が必要です。Java アプリケーションを作成するには、次のコマンドを実行する必要があります。 gradle init --type java-application
Java での Web アプリケーション - 10
プロジェクトを作成した後、build.gradleファイルを編集する必要があります。これはいわゆるビルド スクリプトです (詳細については、Gradle ドキュメントの「ビルド スクリプトの作成」を参照してください)。このファイルには、プロジェクトのアセンブル方法と、Java プロジェクトの操作に関するその他の側面が記述されています。プラグイン ブロックでは、現在の Gradle プロジェクトにどの「 Gradle プラグイン」を使用する必要があるかを説明します。プラグインはプロジェクトの機能を拡張します。たとえば、デフォルトのプラグインは「java」です。このプラグインは、Java サポートが必要な場合に常に使用されます。ただし、 「 application 」プラグインは必要ありません。なぜなら... その説明には、「実行可能な JVM アプリケーション」を作成するために使用されると記載されています。JVM アプリケーションを実行しています。WAR アーカイブの形式で Web アプリケーションを作成する必要があります。Gradle ドキュメントで WAR という単語を検索すると、「War Plugin」が見つかります。したがって、次のプラグインを指定します。
plugins {
    id 'java'
    id 'war'
}
また、「War Plugin のデフォルト設定」では、Web アプリケーションのすべてのコンテンツが含まれるディレクトリは「src/main/webapp」である必要があり、web.xml が存在するのと同じ WEB-INF ディレクトリが存在する必要があると言われています。位置した。このようなファイルを作成してみましょう。もう少し後で記入します。これについてはまだ十分な情報がありません。「依存関係」ブロックでは、プロジェクトの依存関係、つまりアプリケーションがそれなしでは動作できないライブラリ/フレームワークを示します。この場合、Web アプリケーションを作成しています。つまり、サーブレット API なしでは作業できません。
dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    testCompile 'junit:junit:4.12'
}
providedCompile は、依存関係を Web アプリケーションの WAR アーカイブに含める必要がないことを意味します。依存関係はコンパイルの場合にのみ必要です。そして、実行されると、この依存関係は他の誰か (つまり、Web サーバー) によって提供されます。さて、どの依存関係リポジトリを使用するかについての情報をビルド スクリプトに残しておきます。指定されたすべての依存関係はそこからダウンロードされます。
repositories {
    jcenter()
}
ビルド スクリプト ファイルからその他のものをすべて削除します。次に、クラス src\main\java\App.java を編集しましょう。それからサーブレットを作成しましょう。「第 2 章 サーブレット インターフェイス」の章のサーブレット API 仕様では、サーブレット インターフェイスにはHttpServlet の基本実装があると記載されており、ほとんどの場合これで十分であり、開発者はそれを継承するだけで済みます。「 2.1.1 HTTP 固有のリクエスト処理メソッド」の章では、受信リクエストを処理する主なメソッドが示されています。したがって、App.java クラスを書き直してみましょう。
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.IOException;

public class App extends HttpServlet {
    public String getGreeting() {
        return "Hello world.";
    }

    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 		// https://www.oracle.com/technetwork/java/servlet-142430.html
 		PrintWriter out = resp.getWriter();
 		out.println(this.getGreeting());
 		out.close();
 	}
}
それで、すべての準備ができたようです。残っているのは、デプロイメント記述子を正しく記述することだけです。図から、次のテキストを web.xml にコピーします。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="..."
      version="3.1">
      ...
</web-app>
また、そこに示されているスキーマへのパスも示されています。 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd 次に、サーブレット API 仕様で web.xml がどのように見えるべきかの例を見てみましょう。この例は、「 14.5.1 基本的な例」の章で説明されています。図に示されている内容と仕様に示されている例を組み合わせてみましょう。以下の結果が得られます。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
      version="3.1">
      <display-name>A Simple Web Application</display-name>
      <servlet>
		<servlet-name>app</servlet-name>
		<servlet-class>App</servlet-class>
	  </servlet>
	  <servlet-mapping>
		<servlet-name>app</servlet-name>
		<url-pattern>/app</url-pattern>
	  </servlet-mapping>
</web-app>
ご覧のとおり、前に指定したスキーマと schemaLocation を使用しました。また、要素自体の説明は、14.5.1 章の例から引用したものです。すべてが正しく行われた場合、エラーなしで gradle war タスクが実行されます。
Java での Web アプリケーション - 11
Java での Web アプリケーション - 12

Web アプリケーションの起動

Web アプリケーションはどのように起動するのでしょうか? 最初に、より複雑なオプションを扱いましょう。以前、サーブレット API をサポートする Apache Tomcat Web サーバーがあると述べました。これは、収集した戦争アーカイブをこのサーバーにデプロイ (「デプロイ」とも言います) できることを意味します。「Download Tomcat」ページの「Binary Distributions」セクションから、配信タイプ「Core」を zip 形式でダウンロードします。そして、ダウンロードしたアーカイブを何らかのディレクトリ (たとえば、C:\apache-tomcat-9.0.14) に解凍します。サーバーを起動する前に、編集用にファイルを開いてconf\tomcat-users.xml次の行を追加しましょう。 <user username="tomcat" password="tomcat" roles="tomcat,manager-gui,admin-gui"/> 次に、コマンド ラインで bin ディレクトリに移動し、 を実行しますcatalina.bat start。デフォルトでは、サーバー コンソールは で利用可能になりますhttp://localhost:8080/manager。ログインとパスワードは、tomcat-users.xml で指定したものと同じです。Tomcat には、Web アプリケーションを含む「webapps」ディレクトリがあります。独自のものを配備したい場合は、戦争アーカイブをそこにコピーする必要があります。以前に gradle war コマンドを実行したとき、\build\libs\war アーカイブがディレクトリに作成されました。これをコピーする必要があります。コピーした後、ページを更新するhttp://localhost:8080/managerと、以下が表示されます。
Java での Web アプリケーション - 13
を完了したらhttp://localhost:8080/javaweb/app、サーブレットに移ります。以前に /app リクエストを App サーブレットに「マッピング」しました (つまり、マッピングしました)。アプリケーションがどのように動作するかをより迅速に確認する方法があります。そして、アセンブリ システムがこれにも役立ちます。Gradle プロジェクトのビルド スクリプトで、新しいプラグイン「 Gretty」をプラグイン セクションに 追加できます。id "org.gretty" version "2.3.1" これで、アプリケーションを実行するための Gradle タスクを実行できるようになります。gradle appRun
Java での Web アプリケーション - 14
詳細については、 「gretty プラグインを追加してアプリを実行する」を参照してください。
Java での Web アプリケーション - 15

Spring とサーブレット API

サーブレットはすべての基礎です。そして、現在人気のある Spring Framework でさえ、サーブレット API へのアドオンにすぎません。まず、Spring Framework はプロジェクトの新しい依存関係です。したがって、これを依存関係ブロックのビルド スクリプトに追加しましょう。 compile 'org.springframework:spring-webmvc:5.1.3.RELEASE' Spring Framework ドキュメントには「1.1. DispatcherServlet」という章があります。Spring Framework は「フロント コントローラー」パターンに基づいて構築されていると述べています。これは、「 DispatcherServlet」と呼ばれる中央サーブレットがある場合です。すべてのリクエストはこのサーブレットに届き、必要なコンポーネントへの呼び出しを委任します。ほら、ここにもサーブレットがあります。デプロイメント記述子にリスナーを追加する必要があります。
<listener>
	&ltlistener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
これはサーブレット コンテキスト イベント リスナーです。つまり、サーブレット コンテキストが起動すると、Spring コンテキスト (WebApplicationContext) も起動します。サーブレットコンテキストとは何ですか? これについては、Servle API 仕様の「第 4 章 サーブレット コンテキスト」の章で説明されています。サーブレット コンテキストは、サーブレットが実行されている Web アプリケーションのサーブレットの「ビュー」です。各 Web アプリケーションには独自のサーブレット コンテキストがあります。次に、Spring Framework を有効にするには、サーブレット コンテキストの初期化パラメータである context-param を指定する必要があります。
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/app-context.xml</param-value>
</context-param>
そして、DispatcherServlet定義により構成が完了します。
<servlet>
	<servlet-name>app</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
 		<param-value></param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
	<servlet-name>app</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>
あとは、contextConfigLocation で指定されたファイルに入力するだけです。これを行う方法は、Spring Framework ドキュメントの「1.3.1. 宣言」の章で説明されています。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="ru.javarush.javaweb"/>
    <mvc:annotation-driven/>
</beans>
ここでは、どのパッケージをスキャンするかを指定するだけでなく、アノテーション駆動型にすること、つまり Spring がどのように動作するかに関するアノテーションを制御することも重要です。残っているのは、ru.javarush.javaweb パッケージを作成し、その中に Spring コントローラー クラスを配置することだけです。
package ru.javarush.javaweb;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class SpringController {

    @GetMapping("/app")
    @ResponseBody
    public String getGreeting() {
        return "Hello world.";
    }
}
ここで gradle appRun を実行し、アドレスに移動すると、http://127.0.0.1:8080/javaweb/app同じ Hello World が得られます。ご覧のとおり、Spring Framework はサーブレット API と密接に絡み合っており、サーブレット API を使用してその上で動作します。
Java での Web アプリケーション - 16

注釈

これまで見てきたように、注釈は便利です。そう思ったのは私たちだけではありませんでした。したがって、バージョン 3.0 以降のサーブレット API 仕様では、「第 8 章 アノテーションとプラグ可能性」という章が登場し、サーブレット コンテナは、デプロイメント記述子で以前に指定されたものをアノテーションを通じて指定する機能をサポートする必要があると規定しています。したがって、web.xml をプロジェクトから完全に削除でき、サーブレット クラスの上に@WebServletアノテーションを指定して、サーブレットをマップするパスを指定できます。ここではすべてが明確に見えます。しかし、より複雑な設定が必要な Spring をプロジェクトに接続した場合はどうなるでしょうか? ここではすべてがもう少し複雑です。まず、Spring のドキュメントには、web.xml を使用せずに Spring を構成するには、WebApplicationInitializer を実装する独自のクラスを使用する必要があると記載されています。詳細については、「1.1. DispatcherServlet」の章を参照してください。これは春のクラスであることがわかりました。では、ここでサーブレット API はどのように使用されるのでしょうか? 実際、ServletContainerInitializer はServlet API 3.0 に追加されました。Java の特別なメカニズム ( SPIと呼ばれる) を使用して、Spring は と呼ばれるサーブレット コンテナ初期化子を指定しますSpringServletContainerInitializer。次に、WebApplicationInitializer の実装をすでに検索し、必要なメソッドを呼び出して必要な設定を実行します。詳細については、「サーブレット コンテナが WebApplicationInitializer 実装を見つける方法」を参照してください。上記の設定は次のように行うことができます。
package ru.javarush.javaweb.config;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

public class AppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        // регистрируем конфигурацию созданую высше
        ctx.register(AppConfig.class);
        // добавляем в контекст слушателя с нашей конфигурацией
        servletContext.addListener(new ContextLoaderListener(ctx));

        ctx.setServletContext(servletContext);

        // настраиваем маппинг Dispatcher Servlet-а
        ServletRegistration.Dynamic servlet =
                servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);
    }
}
次に、「Java ベースの構成」を使用して、スキャンするパッケージを指定し、注釈を有効にします。
package ru.javarush.javaweb.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "ru.javarush.javaweb.controllers")
public class AppConfig {
}
また、SpringController 自体は に移動されたru.javarush.javaweb.controllersため、スキャン時に構成はそれ自体を検出せず、コントローラーのみを検索するようになりました。
Java での Web アプリケーション - 17

要約する

この概要が Java で Web アプリケーションがどのように動作するかに少しでも光を当てられれば幸いです。これは氷山の一角ですが、基礎を理解していないと、その基礎に基づいたテクノロジーがどのように機能するかを理解することは困難です。サーブレット API は Java Web アプリケーションの中心部分であり、他のフレームワークがどのようにそれに適合するかを調べてきました。続行するには、次の資料をご覧ください。 #ヴィアチェスラフ
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION