1. 概要

Webアプリケーションを構築する場合、 JavaServer Pages(JSP)は、HTMLページのテンプレートメカニズムとして使用できるオプションの1つです。

一方、 Spring Bootは、Webアプリケーションをブートストラップするために使用できる人気のあるフレームワークです。

このチュートリアルでは、JSPをSpring Bootと一緒に使用してWebアプリケーションを構築する方法を見ていきます。

最初に、さまざまなデプロイメントシナリオで機能するようにアプリケーションを設定する方法を説明します。 次に、JSPの一般的な使用法をいくつか見ていきます。 最後に、アプリケーションをパッケージ化するときに使用できるさまざまなオプションについて説明します。

ここでの簡単な注意点は、 JSPにはそれ自体に制限があり、Spring Bootと組み合わせるとさらに制限があります。したがって、ThymeleafまたはFreeMarkerを検討する必要があります。 JSPのより良い代替手段として。

2. Mavenの依存関係

JSPでSpring Bootをサポートするために必要な依存関係を見てみましょう。

また、アプリケーションをスタンドアロンアプリケーションとして実行することと、Webコンテナで実行することの微妙な点についても説明します。

2.1. スタンドアロンアプリケーションとして実行

まず、 spring-boot-starter-webの依存関係を含めましょう。

この依存関係は、デフォルトの組み込みTomcatサーブレットコンテナとともにSpringBootでWebアプリケーションを実行するためのすべてのコア要件を提供します。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.4.4</version>
</dependency>

Tomcat以外の組み込みサーブレットコンテナを構成する方法の詳細については、記事Spring Bootの組み込みサーブレットコンテナの比較を確認してください。

Undertowは、組み込みサーブレットコンテナとして使用する場合、JSPをサポートしないことに特に注意する必要があります。

次に、 tomcat-embed-jasper 依存関係を含めて、アプリケーションがJSPページをコンパイルおよびレンダリングできるようにする必要があります。

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <version>9.0.44</version>
</dependency>

上記の2つの依存関係は手動で提供できますが、通常は、Spring Bootバージョンを管理するだけで、Spring Bootにこれらの依存関係バージョンを管理させる方が適切です。

このバージョン管理は、記事 Spring Bootチュートリアル–単純なアプリケーションのブートストラップに示されているようにSpring Boot親POMを使用するか、記事に示されている依存関係管理を使用して行うことができます。 Spring Bootカスタム親を使用した依存関係管理

最後に、 jstl ライブラリを含める必要があります。これにより、JSPページで必要なJSTLタグのサポートが提供されます。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

2.2. Webコンテナでの実行(Tomcat)

Tomcat Webコンテナーで実行する場合でも、上記の依存関係が必要です。

ただし、アプリケーションによって提供される依存関係がTomcatランタイムによって提供される依存関係と衝突しないようにするには、提供されるスコープで2つの依存関係を設定する必要があります。

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <version>9.0.44</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <version>2.4.4</version>
    <scope>provided</scope>
</dependency>

spring-boot-starter-tomcat を明示的に定義し、提供されたスコープでマークする必要があることに注意してください。 これは、spring-boot-starter-webによってすでに提供されている推移的な依存関係であったためです。

3. リゾルバー構成の表示

慣例に従い、JSPファイルを $ {project.basedir} / main / webapp / WEB-INF / jsp/ディレクトリに配置します。

application.properties ファイルで2つのプロパティを構成して、これらのJSPファイルの場所をSpringに通知する必要があります。

spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp

コンパイルすると、Mavenは、結果のWARファイルに上記のjspディレクトリがWEB-INFディレクトリ内に配置されるようにします。このディレクトリは、アプリケーションによって提供されます。

4. アプリケーションのブートストラップ

メインのアプリケーションクラスは、スタンドアロンアプリケーションとして実行するか、Webコンテナで実行するかによって影響を受けます。

スタンドアロンアプリケーションとして実行する場合、アプリケーションクラスは、メインメソッドとともに単純な@SpringBootApplication注釈付きクラスになります。

@SpringBootApplication(scanBasePackages = "com.baeldung.boot.jsp")
public class SpringBootJspApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootJspApplication.class);
    }
}

ただし、必要な場合 Webコンテナにデプロイするには、SpringBootServletInitializerを拡張する必要があります。

これにより、アプリケーションのサーブレット、フィルター、およびServletContextInitializerがランタイムサーバーにバインドされます。これは、アプリケーションの実行に必要です。

@SpringBootApplication(scanBasePackages = "com.baeldung.boot.jsp")
public class SpringBootJspApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(SpringBootJspApplication.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringBootJspApplication.class);
    }
}

5. シンプルなWebページの提供

JSPページは、JavaServer Pages標準タグライブラリ(JSTL)に依存して、分岐、反復、書式設定などの一般的なテンプレート機能を提供し、事前定義された関数のセットも提供します。

アプリケーションに保存されている本のリストを表示する簡単なWebページを作成しましょう。

すべてのBookオブジェクトを検索するのに役立つBookServiceがあるとします。

public class Book {
    private String isbn;
    private String name;
    private String author;

    //getters, setters, constructors and toString
}

public interface BookService {
    Collection<Book> getBooks();
    Book addBook(Book book);
}

これをWebページとして公開するSpringMVCコントローラーを作成できます。

@Controller
@RequestMapping("/book")
public class BookController {

    private final BookService bookService;

    public BookController(BookService bookService) {
        this.bookService = bookService;
    }

    @GetMapping("/viewBooks")
    public String viewBooks(Model model) {
        model.addAttribute("books", bookService.getBooks());
        return "view-books";
    }
}

上記のBookControllerview-booksというビューテンプレートを返すことに注意してください。 application.properties の以前の構成によると、SpringMVCは/ WEB-INF / jsp/ディレクトリ内でview-books.jspを検索します。

その場所にこのファイルを作成する必要があります。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
    <head>
        <title>View Books</title>
        <link href="<c:url value="/css/common.css"/>" rel="stylesheet" type="text/css">
    </head>
    <body>
        <table>
            <thead>
                <tr>
                    <th>ISBN</th>
                    <th>Name</th>
                    <th>Author</th>
                </tr>
            </thead>
            <tbody>
                <c:forEach items="${books}" var="book">
                    <tr>
                        <td>${book.isbn}</td>
                        <td>${book.name}</td>
                        <td>${book.author}</td>
                    </tr>
                </c:forEach>
            </tbody>
        </table>
    </body>
</html>

上記の例は、JSTLの使用方法を示しています JavaScriptやCSSなどの外部リソースにリンクするタグ。 通常、これらは $ {project.basedir} / main / resources / static/ディレクトリに配置されます。

JSTLがどのようにタグを使用して、私たちが提供するモデル属性 BookController

6. フォーム提出の処理

ここで、JSPを使用してフォーム送信を処理する方法を見てみましょう。

BookController は、書籍を追加するためのフォームを提供し、フォームの送信を処理するためにMVCエンドポイントを提供する必要があります。

public class BookController {

    //already existing code

    @GetMapping("/addBook")
    public String addBookView(Model model) {
        model.addAttribute("book", new Book());
        return "add-book";
    }

    @PostMapping("/addBook")
    public RedirectView addBook(@ModelAttribute("book") Book book, RedirectAttributes redirectAttributes) {
        final RedirectView redirectView = new RedirectView("/book/addBook", true);
        Book savedBook = bookService.addBook(book);
        redirectAttributes.addFlashAttribute("savedBook", savedBook);
        redirectAttributes.addFlashAttribute("addBookSuccess", true);
        return redirectView;
    } 
}

次のadd-book.jspファイルを作成します(適切なディレクトリに配置することを忘れないでください)。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Add Book</title>
    </head>
    <body>
        <c:if test="${addBookSuccess}">
            <div>Successfully added Book with ISBN: ${savedBook.isbn}</div>
        </c:if>
    
        <c:url var="add_book_url" value="/book/addBook"/>
        <form:form action="${add_book_url}" method="post" modelAttribute="book">
            <form:label path="isbn">ISBN: </form:label> <form:input type="text" path="isbn"/>
            <form:label path="name">Book Name: </form:label> <form:input type="text" path="name"/>
            <form:label path="author">Author Name: </form:label> <form:input path="author"/>
            <input type="submit" value="submit"/>
        </form:form>
    </body>
</html>

を使用します modelAttribute によって提供されるパラメータバインドするタグに追加された属性 addBookView() の方法 BookController フォームに送信します。フォームは、フォームを送信するときに入力されます。

このタグを使用した結果、タグ内にタグを配置できないため、フォームアクションURLを個別に定義する必要があります。 また、にある属性各入力フィールドをの属性にバインドするタグ物体。

フォーム送信の処理方法の詳細については、記事 SpringMVCのフォーム入門を参照してください。

7. エラーの処理

がJSPでSpring Bootを使用する際の既存の制限により、デフォルトの/ errorマッピングをカスタマイズするためのカスタムerror.htmlを提供することはできません。代わりに、さまざまなエラーを処理するためのカスタムエラーページを作成する必要があります。

7.1. 静的エラーページ

さまざまなHTTPエラーのカスタムエラーページを表示する場合は、静的エラーページを提供できます。

アプリケーションによってスローされたすべての4xxエラーのエラーページを提供する必要があるとしましょう。 4xx.htmlというファイルを${project.basedir} / main / resources / static / error/ディレクトリに配置するだけです。

アプリケーションが4xxHTTPエラーをスローした場合、Springはこのエラーを解決し、提供された4xx.htmlページを返します。

7.2. 動的エラーページ

例外を処理して、コンテキスト化された情報とともにカスタマイズされたエラーページを提供する方法は複数あります。 SpringMVCが@ControllerAdviceおよび@ExceptionHandlerアノテーションを使用して、このサポートをどのように提供するかを見てみましょう。

アプリケーションがDuplicateBookExceptionを定義しているとしましょう。

public class DuplicateBookException extends RuntimeException {
    private final Book book;

    public DuplicateBookException(Book book) {
        this.book = book;
    }

    // getter methods
}

また、同じISBNで2冊の本を追加しようとすると、BookServiceImplクラスが上記のDuplicateBookExceptionをスローするとします。

@Service
public class BookServiceImpl implements BookService {

    private final BookRepository bookRepository;

    // constructors, other override methods

    @Override
    public Book addBook(Book book) {
        final Optional<BookData> existingBook = bookRepository.findById(book.getIsbn());
        if (existingBook.isPresent()) {
            throw new DuplicateBookException(book);
        }

        final BookData savedBook = bookRepository.add(convertBook(book));
        return convertBookData(savedBook);
    }

    // conversion logic
}

次に、 LibraryControllerAdvice クラスは、処理するエラーと、各エラーの処理方法を定義します。

@ControllerAdvice
public class LibraryControllerAdvice {

    @ExceptionHandler(value = DuplicateBookException.class)
    public ModelAndView duplicateBookException(DuplicateBookException e) {
        final ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("ref", e.getBook().getIsbn());
        modelAndView.addObject("object", e.getBook());
        modelAndView.addObject("message", "Cannot add an already existing book");
        modelAndView.setViewName("error-book");
        return modelAndView;
    }
}

上記のエラーがここで解決されるように、error-book.jspファイルを定義する必要があります。 これは静的HTMLではなくコンパイルが必要なJSPテンプレートであるため、必ず $ {project.basedir} / main / webapp / WEB-INF / jsp/ディレクトリに配置してください。

8. 実行可能ファイルの作成

アプリケーションをTomcatなどのWebコンテナにデプロイすることを計画している場合、選択は簡単であり、これを実現するためにwarパッケージングを使用します。

ただし、JSPとSpring Bootを組み込みサーブレットコンテナで使用している場合は、jarパッケージを使用できないことに注意してください。 したがって、スタンドアロンアプリケーションとして実行している場合、唯一のオプションはwarパッケージングです。

pom.xml は、いずれの場合も、パッケージ化ディレクティブをwarに設定する必要があります。

<packaging>war</packaging>

依存関係の管理にSpring Boot親POMを使用しなかった場合は、 spring -boot-maven-pluginを含めて、結果のwarファイルがスタンドアロンとして実行できるようにする必要があります。アプリケーション。

これで、組み込みサーブレットコンテナを使用してスタンドアロンアプリケーションを実行するか、結果の war ファイルをTomcatにドロップして、アプリケーションに提供させることができます。

9. 結論

このチュートリアルでは、さまざまなトピックに触れました。 いくつかの重要な考慮事項を要約してみましょう。

  • JSPにはいくつかの固有の制限があります。 代わりにThymeleafまたはFreeMarkerを検討してください。
  • Webコンテナにデプロイする場合は、必要な依存関係を提供としてマークすることを忘れないでください。
  • Undertowは、組み込みサーブレットコンテナとして使用される場合、JSPをサポートしません。
  • Webコンテナにデプロイする場合、 @SpringBootApplication アノテーション付きクラスは、 SpringBootServletInitializer を拡張し、必要な構成オプションを提供する必要があります。
  • デフォルトの/errorページをJSPでオーバーライドすることはできません。 代わりに、カスタムエラーページを提供する必要があります。
  • Spring BootでJSPを使用している場合、JARパッケージはオプションではありません。

いつものように、私たちの例を含む完全なソースコードは、GitHubから入手できます。