Рубрики
Без рубрики

Весенняя Загрузка Со Страницами JavaServer (JSP)

Автор оригинала: baeldung.

1. введение

При создании веб-приложений JavaServer Pages (JSP) является одним из вариантов, который мы можем использовать в качестве механизма шаблонов для наших HTML-страниц . С другой стороны, Spring Boot – это популярный фреймворк, который мы можем использовать для загрузки нашего веб-приложения .

В этом уроке мы увидим, как мы можем использовать JSP вместе с Spring Boot для создания веб-приложения. Сначала мы рассмотрим, как настроить наше приложение для работы в различных сценариях развертывания. Затем мы перейдем к рассмотрению некоторых распространенных способов использования JSP. Наконец, мы рассмотрим различные варианты, которые у нас есть при упаковке нашего приложения.

Краткое примечание здесь заключается в том, что JSP имеет ограничения сам по себе и тем более в сочетании с Spring Boot . Следовательно, мы должны рассмотреть Thymeleaf или FreeMarker в качестве лучшей альтернативы JSP.

2. Зависимости Maven

Давайте посмотрим, какие зависимости нам нужны для поддержки Spring Boot с помощью JSP.

Мы также отметим тонкости между запуском нашего приложения как отдельного приложения и запуском в веб-контейнере.

2.1. Запуск в качестве автономного приложения

Прежде всего, давайте включим зависимость spring-boot-starter-web . Эта зависимость обеспечивает все основные требования для запуска веб-приложения с Spring Boot вместе со встроенным контейнером сервлетов Tomcat по умолчанию:


    org.springframework.boot
    spring-boot-starter-web
    2.4.4

Ознакомьтесь с нашей статьей о сравнении встроенных контейнеров сервлетов в Spring Boot для получения дополнительной информации о том, как настроить встроенный контейнер сервлетов, отличный от Tomcat.

Следует особо отметить, что Undertow не поддерживает JSP при использовании в качестве встроенного контейнера сервлетов .

Затем нам нужно включить зависимость tomcat-embed-jasper , чтобы наше приложение могло компилировать и отображать страницы JSP:


    org.apache.tomcat.embed
    tomcat-embed-jasper
    9.0.44

Хотя вышеупомянутые две зависимости могут быть предоставлены вручную, обычно лучше позволить Spring Boot управлять этими версиями зависимостей, в то время как мы просто управляем версией Spring Boot.

Это управление версиями может быть выполнено либо с помощью родительского POM Spring Boot, как показано в нашей статье Spring Boot Tutorial – Bootstrap простое приложение , либо с помощью управления зависимостями, как показано в нашей статье Spring Boot Dependency Management с настраиваемым родителем .

Наконец, нам нужно включить библиотеку jstl , которая обеспечит поддержку тегов JSTL, необходимую на наших страницах JSP:


    javax.servlet
    jstl
    1.2

2.2. Запуск в веб-контейнере (Tomcat)

Нам все еще нужны вышеуказанные зависимости при работе в веб-контейнере Tomcat.

Однако, чтобы избежать столкновения зависимостей, предоставляемых нашим приложением, с зависимостями, предоставляемыми средой выполнения Tomcat, нам нужно установить две зависимости с предоставленной областью действия :


    org.apache.tomcat.embed
    tomcat-embed-jasper
    9.0.44
    provided



    org.springframework.boot
    spring-boot-starter-tomcat
    2.4.4
    provided

Обратите внимание, что мы должны были явно определить spring-boot-starter-tomcat и пометить его предоставленной областью действия. Это связано с тем, что это уже была транзитивная зависимость, предоставляемая spring-boot-starter-web .

3. Просмотр Конфигурации распознавателя

В соответствии с соглашением мы помещаем наши файлы JSP в каталог ${project.basedir}/main/webapp/WEB-INF/jsp/ . Нам нужно сообщить Spring, где найти эти файлы JSP, настроив два свойства в файле application.properties :

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

При компиляции Maven гарантирует, что результирующий файл WAR будет иметь вышеупомянутый каталог jsp , помещенный в каталог WEB-INF , который затем будет обслуживаться нашим приложением.

4. Загрузка Нашего Приложения

Наш основной класс приложений будет зависеть от того, планируем ли мы работать как отдельное приложение или в веб-контейнере.

При запуске в качестве автономного приложения наш класс приложения будет простым @SpringBootApplication аннотированным классом вместе с основным методом :

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

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

Однако, если нам нужно развернуть в веб-контейнере, нам нужно расширить 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. Обслуживание простой веб-страницы

Страницы JSP полагаются на стандартную библиотеку тегов JavaServer Pages (JSTL) для обеспечения общих функций шаблонов, таких как ветвление, итерация и форматирование, и даже предоставляют набор предопределенных функций.

Давайте создадим простую веб-страницу, на которой будет показан список книг, сохраненных в нашем приложении.

Скажем, у нас есть Книжный сервис , который помогает нам искать все Книги объекты:

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

    //getters, setters, constructors and toString
}

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

Мы можем написать контроллер Spring MVC, чтобы представить его в виде веб-страницы:

@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";
    }
}

Обратите внимание выше, что BookController вернет шаблон представления с именем view-books. Согласно нашей предыдущей конфигурации в application.properties, Spring MVC будет искать view-books.jsp внутри каталога /WEB-INF/jsp/|/.

Нам нужно будет создать этот файл в этом месте:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

    
        View Books
        " rel="stylesheet" type="text/css">
    
    
        
                    
ISBN Name Author
${book.isbn} ${book.name} ${book.author}

В приведенном выше примере показано, как использовать тег JSTL для ссылки на внешние ресурсы, такие как JavaScript и CSS. Обычно мы помещаем их в каталог ${project.basedir}/main/resources/static/ .

Мы также можем увидеть, как тег JSTL можно использовать для перебора атрибута books model, предоставленного нашим 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" %>

    
        Add Book
    
    
        
            
Successfully added Book with ISBN: ${savedBook.isbn}
ISBN: Book Name: Author Name:

Мы используем параметр ModelAttribute , предоставленный тегом , чтобы привязать атрибут book , добавленный в метод addBookView() в BookController к форме, которая, в свою очередь, будет заполнена при отправке формы.

В результате использования этого тега нам нужно отдельно определить URL-адрес действия формы (так как мы не можем помещать теги внутри тегов). Мы также используем атрибут path , найденный в теге , чтобы привязать каждое поле ввода к атрибуту в объекте Book .

Пожалуйста, ознакомьтесь с нашей статьей о начале работы с формами в Spring MVC для получения более подробной информации о том, как обрабатывать отправку форм.

7. Обработка Ошибок

Из-за существующих ограничений на использование Spring Boot с JSP мы не можем предоставить пользовательский error.html для настройки по умолчанию /ошибка отображение . Вместо этого нам нужно создать пользовательские страницы ошибок для обработки различных ошибок.

7.1. Страницы со Статическими Ошибками

Мы можем предоставить статическую страницу ошибок, если хотим отобразить пользовательскую страницу ошибок для различных ошибок HTTP.

Допустим, нам нужно предоставить страницу ошибок для всех ошибок 4xx, вызванных нашим приложением. Мы можем просто поместить файл с именем 4xx.html в каталоге ${project.basedir}/main/resources/static/error/|/.

Если ваше приложение выдает ошибку HTTP 4xx, Spring устранит эту ошибку и вернет предоставленный 4xx.html страница.

7.2. Страницы с Динамическими Ошибками

Существует несколько способов обработки исключений, чтобы предоставить настраиваемую страницу ошибок вместе с контекстуализированной информацией. Давайте посмотрим, как Spring MVC предоставляет нам эту поддержку, используя аннотации @ControllerAdvice и @ExceptionHandler .

Допустим, наше приложение определяет исключение Дубликата книги :

public class DuplicateBookException extends RuntimeException {
    private final Book book;

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

    // getter methods
}

Кроме того, предположим, что наш класс BookServiceImpl выдаст вышеупомянутое исключение Duplicate Book , если мы попытаемся добавить две книги с одним и тем же ISBN:

@Service
public class BookServiceImpl implements BookService {

    private final BookRepository bookRepository;

    // constructors, other override methods

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

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

    // conversion logic
}

Затем наш класс Library ControllerAdvice определит, какие ошибки мы хотим обработать, а также то, как мы будем обрабатывать каждую ошибку:

@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 , чтобы вышеприведенная ошибка была устранена здесь. Обязательно поместите это в каталог ${project.basedir}/main/webapp/WEB-INF/jsp/ , так как это уже не статический HTML, а шаблон JSP, который необходимо скомпилировать.

8. Создание исполняемого файла

Если мы планируем развернуть наше приложение в веб-контейнере, таком как Tomcat, то выбор прост, и мы будем использовать war packaging для достижения этой цели.

Однако мы должны помнить, что мы не можем использовать jar packaging, если мы используем JSP и Spring Boot со встроенным контейнером сервлетов. Следовательно, наш единственный вариант – war packaging, если он работает как автономное приложение.

Наши pom.xml в любом случае потребуется, чтобы директива по упаковке была установлена в war :

war

В случае, если мы не использовали родительский POM Spring Boot для управления зависимостями, нам нужно будет включить spring-boot-maven-плагин , чтобы убедиться, что полученный файл war может работать как автономное приложение .

Теперь мы можем запустить наше автономное приложение со встроенным контейнером сервлетов или просто поместить полученный файл war в Tomcat и позволить ему обслуживать наше приложение.

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

В этом уроке мы затронули различные темы. Давайте кратко остановимся на некоторых ключевых соображениях:

  • JSP содержит некоторые неотъемлемые ограничения. Вместо этого рассмотрим Thymeleaf или FreeMarker
  • Не забудьте отметить необходимые зависимости как предоставленные при развертывании в веб-контейнере
  • Undertow не будет поддерживать JSP, если он используется в качестве встроенного контейнера сервлетов
  • При развертывании в веб-контейнере наш @SpringBootApplication аннотированный класс должен расширяться SpringBootServletInitializer и предоставлять необходимые параметры конфигурации
  • Мы не можем переопределить страницу по умолчанию /error с помощью JSP. Вместо этого нам нужно предоставить пользовательские страницы ошибок
  • Упаковка банок не является для нас вариантом, если мы используем JSP с пружинной загрузкой

Как всегда, полный исходный код с нашими примерами доступен на GitHub .