Пример SPRING BOOT приложения в связке с встроенным сервером приложений Tomcat и движком шаблонов JSP в качестве исполняемого WAR-файла.
Технологии:
- Spring Boot 1.5.9.RELEASE
- Spring 4.3.13.RELEASE
- Tomcat Embed 8.5.6
- Maven 3
- Java 8
содержание
1. Структура каталогов
2. Зависимости
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>ru.leodev.examples.springboot</groupId> <artifactId>spring-boot-web-jsp</artifactId> <version>0.0.1</version> <packaging>war</packaging> <name>Spring Boot Web JSP Example</name> <description>Spring Boot Web JSP Example</description> <url>https://www.leodev.ru</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!-- содержит в себе необходимые библиотеки для создания ВЕБ приложения --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <!-- Встроенный Tomcat контейнер --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!-- JSTL для JSP --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!-- Need this to compile JSP --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <!-- Необходим для компиляции JSP, tomcat-embed-jasper версия не работает, решение так и не нашел --> <dependency> <groupId>org.eclipse.jdt.core.compiler</groupId> <artifactId>ecj</artifactId> <version>4.6.1</version> <scope>provided</scope> </dependency> <!-- Не обязательно, нужна для подключения статического CSS от bootstrap и теста статических ресурсов --> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.7</version> </dependency> </dependencies> <build> <plugins> <!-- Делает наш jar/war исполняемым --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> |
3. Spring Boot
3.1 Наследуем наш SpringBootWebJspApplication от SpringBootServletInitializer это позволит нам развертывать наше приложение из классического WAR
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package ru.leodev.examples.springboot.springbootwebjsp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; @SpringBootApplication public class SpringBootWebJspApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(SpringBootWebJspApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(SpringBootWebJspApplication.class); } } |
[stextbox id=’alert’]Как я уже писал в комментариях pom.xml, из под Intellij IDEA после этого шага мне не удалось запустить проект, причину так и не нашел. Но из консоли сервер стартует без проблем используя команды:[/stextbox]
|
1 2 |
mvn clean package mvn spring-boot:run |
3.2 Добавляем простой spring контроллер
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package ru.leodev.examples.springboot.springbootwebjsp.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import java.util.Map; @Controller public class MainController { // внедряем значение из application.properties @Value("${welcome.message:test}") private String message = "Hello World"; // Обычно я использую интерфейс Model, но в целом разницы нет, // т.к. используется реализация LinkedHashMap(Key, Val) @RequestMapping("/") public String welcome(Map<String, Object> model) { model.put("message", this.message); return "index"; } } |
4. JSP + Resources + статические файлы
4.1 Для файлов JSP, создаем каталог src/main/webapp/WEB-INF/jsp/
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<!DOCTYPE html> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ page contentType="text/html; charset=UTF-8" %> <html lang="en"> <head> <!-- Подключаем bootstrap CSS, Spring boot автоматически замапит ресурс благодаря зависимости webjars в pom.xml --> <link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css" /> <!-- <spring:url value="/css/main.css" var="springCss" /> <link href="${springCss}" rel="stylesheet" /> --> <c:url value="/css/main.css" var="jstlCss" /> <link href="${jstlCss}" rel="stylesheet" /> </head> <body> <nav class="navbar navbar-inverse"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="#">Spring Boot JSP</a> </div> <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Главная</a></li> <li><a href="#about">Обо мне</a></li> </ul> </div> </div> </nav> <div class="container"> <div class="starter-template"> <h1>Пример Spring Boot Web JSP</h1> <h2>Сообщение: ${message}</h2> </div> </div> <script type="text/javascript" src="webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script> </body> </html> |
4.2 Статические файлы, такие как стили CSS или Javascript кладем в /src/main/resources/static/
Соответственно в static создаем каталог css и в него кладем тестовый main.css
|
1 2 3 4 5 6 7 |
h1{ color: #3858ff; } h2{ color: #ff801b; } |
4.3 Все properties файлы хранятся в корне директории ресурсов: /src/main/resources/
в моем случае spring сгенерировал его при создании проекта, поэтому мы лишь прописываем параметр для Внедрения зависимости(DI)
|
1 2 3 4 |
spring.mvc.view.prefix: /WEB-INF/jsp/ spring.mvc.view.suffix: .jsp welcome.message: Hello Leodev! |
[stextbox id=’black’]Прочтите эту статью о Spring Boot Serving static content для общего понимания работы с ресурсами в Spring Boot[/stextbox]
5. Запуск приложения
5.1 Запускаем наше spring boot приложение
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
[INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Spring Boot Web JSP Example 0.0.1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] >>> spring-boot-maven-plugin:1.5.9.RELEASE:run (default-cli) > test-compile @ spring-boot-web-jsp >>> [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ spring-boot-web-jsp --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 1 resource [INFO] Copying 1 resource [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ spring-boot-web-jsp --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ spring-boot-web-jsp --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory D:\workspace\JAVA\TESTAPPS\spring-boot-examples-ld\spring-boot-web-jsp\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ spring-boot-web-jsp --- [INFO] No sources to compile [INFO] [INFO] <<< spring-boot-maven-plugin:1.5.9.RELEASE:run (default-cli) < test-compile @ spring-boot-web-jsp <<< [INFO] [INFO] --- spring-boot-maven-plugin:1.5.9.RELEASE:run (default-cli) @ spring-boot-web-jsp --- [INFO] Attaching agents: [] 23:30:52.113 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Included patterns for restart : [] 23:30:52.116 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Excluded patterns for restart : [/spring-boot-starter/target/classes/, /spring-boot-autoconfigure/target/classes/, /spring-boot-starter-[\w-]+/, /spring-boot/target/classes/ , /spring-boot-actuator/target/classes/, /spring-boot-devtools/target/classes/] 23:30:52.116 [main] DEBUG org.springframework.boot.devtools.restart.ChangeableUrls - Matching URLs for reloading : [file:/D:/workspace/JAVA/TESTAPPS/spring-boot-examples-ld/spring-boot-web-jsp/target/classes/] . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.5.9.RELEASE) 2018-01-18 23:30:52.424 INFO 13368 --- [ restartedMain] r.l.e.s.s.SpringBootWebJspApplication : Starting SpringBootWebJspApplication on LEOGAME-PC with PID 13368 (D:\workspace\JAVA\TESTAPPS\spring-boot-examples-ld\spring-boot-web-jsp\target\classes started by LEO in D:\workspace\JAVA\TESTAPPS\spring-boot-examples-ld\spring-boot-web-jsp) 2018-01-18 23:30:52.425 INFO 13368 --- [ restartedMain] r.l.e.s.s.SpringBootWebJspApplication : No active profile set, falling back to default profiles: default 2018-01-18 23:30:52.475 INFO 13368 --- [ restartedMain] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@96da14: startup date [Thu Jan 18 23:30:52 MSK 2018]; root of context hierarchy 2018-01-18 23:30:53.460 INFO 13368 --- [ restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http) 2018-01-18 23:30:53.468 INFO 13368 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2018-01-18 23:30:53.469 INFO 13368 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.23 2018-01-18 23:30:53.602 INFO 13368 --- [ost-startStop-1] org.apache.jasper.servlet.TldScanner : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 2018-01-18 23:30:53.606 INFO 13368 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2018-01-18 23:30:53.606 INFO 13368 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1134 ms 2018-01-18 23:30:53.688 INFO 13368 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] 2018-01-18 23:30:53.690 INFO 13368 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] 2018-01-18 23:30:53.690 INFO 13368 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] 2018-01-18 23:30:53.691 INFO 13368 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] 2018-01-18 23:30:53.691 INFO 13368 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] 2018-01-18 23:30:53.883 INFO 13368 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@96da14: startup date [Thu Jan 18 23:30:52 MSK 2018]; root of context hierarchy 2018-01-18 23:30:53.929 INFO 13368 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String ru.leodev.examples.springboot.springbootwebjsp.controller.MainController.welcome(java.util.Map<java.lang.String, jav a.lang.Object>) 2018-01-18 23:30:53.931 INFO 13368 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigur e.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2018-01-18 23:30:53.932 INFO 13368 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorControlle r.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 2018-01-18 23:30:53.951 INFO 13368 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-01-18 23:30:53.952 INFO 13368 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-01-18 23:30:53.973 INFO 13368 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-01-18 23:30:54.055 INFO 13368 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 2018-01-18 23:30:54.093 INFO 13368 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2018-01-18 23:30:54.145 INFO 13368 --- [ restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 2018-01-18 23:30:54.148 INFO 13368 --- [ restartedMain] r.l.e.s.s.SpringBootWebJspApplication : Started SpringBootWebJspApplication in 2.019 seconds (JVM running for 2.334) |
5.2 Открываем http://localhost:8080
5.3 Maven упакует проект как исполняемый файл WAR. В папке target будет создан файл WAR 20 Мб.
|
1 2 3 4 5 6 7 8 9 10 |
[INFO] Scanning for projects... ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2.990 s [INFO] Finished at: 2018-01-18T23:37:18+03:00 [INFO] Final Memory: 21M/50M [INFO] ------------------------------------------------------------------------ D:\workspace\JAVA\TESTAPPS\spring-boot-examples-ld\spring-boot-web-jsp> |
Запустим и снова проверим http://localhost:8080
|
1 |
java -jar target/spring-boot-web-jsp-0.0.1.war |
[stextbox id=’alert’ caption=’Ограничения JSP’]Вы не можете создать исполняемую jar для запуска встроенного веб-сервера Tomcat + JSP из-за жестко закодированного шаблона файла в Tomcat. Подробности тут Spring Boot – JSP limitation.[/stextbox]
Исходники: spring-boot-web-jsp

