Spring-Boot + Spring-MVC + Thymeleaf + Apache Tiles
У меня уже есть клиентский модуль с плитками Apache и Thimeleaf, что хорошо работает. Я хотел преобразовать его в весенний загрузчик и хотел сделать это шаг за шагом, но я действительно застрял с этим. Я не хочу меняться на много раз, я был бы рад, когда кто-то может сказать мне, какой шаг я должен сделать в первую очередь и запустить его. Я уже пытался написать сервлеты в javaConfig, но я тоже застрял. Может быть, кто-то может мне помочь, пожалуйста. Если вам нужна дополнительная информация, пожалуйста, не стесняйтесь спрашивать.
Другой вопрос: нужно ли мне перейти с xml на javaconfig? Я бы предпочел самый простой способ. Но как только я добавляю pom-зависимость к pom, приложение больше не работает.
=======
POM:
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>at.compax.bbsng</groupId>
<artifactId>bbsng-client</artifactId>
<version>0.1.0-SNAPSHOT</version>
</parent>
<artifactId>bbsng-client-mvc</artifactId>
<name>bbsng-client-mvc</name>
<packaging>war</packaging>
<properties>
<org.apache.tiles-version>2.2.2</org.apache.tiles-version>
<org.thymeleaf-version>2.0.16</org.thymeleaf-version>
<slf4j-version>1.7.5</slf4j-version>
<jackson.version>1.9.10</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Apache Tiles -->
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-template</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-servlet</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<!-- ThyMeLeaf ... -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${org.thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring3</artifactId>
<version>${org.thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-tiles2</artifactId>
<version>2.0.0</version>
</dependency>
<!-- Jackson JSON Mapper -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- Servlet ... -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- COMMONS ... -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
<additionalBuildcommands>
<buildCommand>
<name>org.springframework.ide.eclipse.core.springbuilder</name>
</buildCommand>
</additionalBuildcommands>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<packagingExcludes>WEB-INF/web.xml</packagingExcludes>
<warName>${project.name}-${project.version}</warName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
</plugin>
</plugins>
</build>
======
Остальные-сервлет-context.xml
<mvc:annotation-driven>
<mvc:async-support default-timeout="120000">
<mvc:callable-interceptors>
<bean class="at.compax.bbsng.client.mvc.TimeoutCallableProcessingInterceptor" />
</mvc:callable-interceptors>
</mvc:async-support>
</mvc:annotation-driven>
<context:component-scan base-package="at.compax.bbsng.client.mvc.rest" />
=====
Приложение-сервлет-context.xml
<!-- **************************************************************** -->
<!-- RESOURCE FOLDERS CONFIGURATION -->
<!-- Dispatcher configuration for serving static resources -->
<!-- **************************************************************** -->
<mvc:resources location="/images/" mapping="/images/**" />
<mvc:resources location="/css/" mapping="/css/**" />
<!-- **************************************************************** -->
<!-- SPRING ANNOTATION PROCESSING -->
<!-- **************************************************************** -->
<mvc:annotation-driven>
<mvc:async-support default-timeout="120000">
<mvc:callable-interceptors>
<bean class="at.compax.bbsng.client.mvc.TimeoutCallableProcessingInterceptor" />
</mvc:callable-interceptors>
</mvc:async-support>
</mvc:annotation-driven>
<context:component-scan base-package="at.compax.bbsng.client.mvc.web" />
<!-- **************************************************************** -->
<!-- MESSAGE EXTERNALIZATION/INTERNATIONALIZATION -->
<!-- Standard Spring MessageSource implementation -->
<!-- **************************************************************** -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="Messages" />
</bean>
<!-- **************************************************************** -->
<!-- THYMELEAF-SPECIFIC ARTIFACTS -->
<!-- TemplateResolver <- TemplateEngine <- ViewResolver -->
<!-- **************************************************************** -->
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="org.thymeleaf.extras.tiles2.dialect.TilesDialect"/>
</set>
</property>
</bean>
<!-- Configures the Tiles layout system using a specific thymeleaf-enabled Tiles Configurer -->
<bean id="tilesConfigurer" class="org.thymeleaf.extras.tiles2.spring.web.configurer.ThymeleafTilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/**/views.xml</value>
</list>
</property>
</bean>
<!-- Resolves view names returned by Controllers as names of Tiles definitions -->
<bean id="tilesViewResolver" class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
<property name="viewClass" value="org.thymeleaf.extras.tiles2.spring.web.view.ThymeleafTilesView"/>
<property name="templateEngine" ref="templateEngine"/>
</bean>
<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
</bean>
=========
ВТОРОЙ ШАГ РЕДАКТИРОВАТЬ:
Я сделал несколько шагов, чтобы теперь я мог запустить свое приложение, запустив applicationClass из ECLIPSE.
Что я делал до сих пор:
====
ПОМ: Пожалуйста, имейте ввиду, что я удалил тимелист-стартер из класса, потому что я не начал его с тимелист-стартера
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- <dependency> -->
<!-- <groupId>org.springframework.boot</groupId> -->
<!-- <artifactId>spring-boot-starter-thymeleaf</artifactId> -->
<!-- </dependency> -->
<!-- Apache Tiles -->
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-template</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-servlet</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<!-- ThyMeLeaf ... -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-tiles2-spring4</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
====
WebMvcConfig для настройки ThyMeLeaf
@Configuration
@ComponentScan
public class WebMvcConfig {
@Bean
public ThymeleafTilesConfigurer tilesConfigurer() {
final ThymeleafTilesConfigurer configurer = new ThymeleafTilesConfigurer();
configurer.setDefinitions("/WEB-INF/**/views.xml");
return configurer;
}
@Bean
public ThymeleafViewResolver viewResolver() {
final ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setViewClass(ThymeleafTilesView.class);
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding(UTF_8);
return resolver;
}
private SpringTemplateEngine templateEngine() {
final SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
engine.setAdditionalDialects(dialects());
return engine;
}
private ServletContextTemplateResolver templateResolver() {
final ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setCharacterEncoding(UTF_8);
return resolver;
}
private Set<IDialect> dialects() {
final Set<IDialect> set = new HashSet<IDialect>();
set.add(new TilesDialect());
return set;
}
}
=====
Spring Boot Starter Class Автоконфигурация ThyMeLeaf была деактивирована, потому что я не получил ее работать с Apache тайлами
@Configuration
@Import({ ServiceConfig.class, RestMvcConfig.class, WebMvcConfig.class })
@EnableAutoConfiguration(exclude = { ThymeleafAutoConfiguration.class })
public class ApplicationClientMvc implements WebApplicationInitializer {
public static void main(final String[] args) {
SpringApplication.run(ApplicationClientMvc.class, args);
}
@Bean
public ServletRegistrationBean applicationDispatcherRegistration(final DispatcherServlet dispatcherServlet) {
final ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
registration.setName("applicationServlet");
registration.addUrlMappings("/app/*");
registration.setAsyncSupported(true);
registration.setLoadOnStartup(1);
registration.addInitParameter("contextConfigLocation", "at.compax.bbsng.client.mvc.web.WebMvcConfig");
registration.setOrder(1);
return registration;
}
@Bean
public ServletRegistrationBean restDispatcherRegistration(final DispatcherServlet dispatcherServlet) {
final ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
registration.setName("restServlet");
registration.addUrlMappings("/rest/*");
registration.setAsyncSupported(true);
registration.setLoadOnStartup(0);
registration.addInitParameter("contextConfigLocation", "at.compax.bbsng.client.mvc.rest.RestMvcConfig");
registration.setOrder(0);
return registration;
}
@Override
public void onStartup(final ServletContext servletContext) throws ServletException {
final FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("encoding-filter", new CharacterEncodingFilter());
encodingFilter.setInitParameter("encoding", UTF_8);
encodingFilter.setInitParameter("forceEncoding", "true");
encodingFilter.addMappingForUrlPatterns(null, true, "/*");
}
}
====
Когда я запускаю это приложение через Eclipse, запуская класс Spring-Boot Start, приложение работает.
2 ответа
Ладно ребята
Я получил это, и я надеюсь, что это поможет другим разработчикам с подобными проблемами.
В POM я удалил все Spring-Dependencies и использую только Spring-Starter-Dependencies, например, следующий фрагмент:
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Apache Tiles -->
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-template</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-servlet</artifactId>
<version>${org.apache.tiles-version}</version>
</dependency>
<!-- Thymeleaf ... -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-tiles2-spring4</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
....
В моем начальном классе я снова активировал автоконфигурацию Thymeleaf, мой полный класс выглядит следующим образом. Примите участие, я использую два разных сервлета, один для REST, один для Thymeleaf.
@Configuration
@Import({ ServiceConfig.class, RestMvcConfig.class, WebMvcConfig.class })
@EnableAutoConfiguration
public class ApplicationClientMvc {
public static void main(final String[] args) {
SpringApplication.run(ApplicationClientMvc.class, args);
}
@Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
@Bean
public ServletRegistrationBean applicationDispatcherRegistration(final DispatcherServlet dispatcherServlet) {
final ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
registration.setName("applicationServlet");
registration.addUrlMappings("/app/*");
registration.setAsyncSupported(true);
registration.setLoadOnStartup(1);
registration.addInitParameter("contextConfigLocation", "a.c.b.c.m.w.WebMvcConfig");
registration.setOrder(1);
return registration;
}
@Bean
public ServletRegistrationBean restDispatcherRegistration(final DispatcherServlet dispatcherServlet) {
final ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
registration.setName("restServlet");
registration.addUrlMappings("/rest/*");
registration.setAsyncSupported(true);
registration.setLoadOnStartup(0);
registration.addInitParameter("contextConfigLocation", "a.c.b.c.m.r.RestMvcConfig");
registration.setOrder(0);
return registration;
}
}
====
Мой класс WebMVCConfig выглядит следующим образом, находится в упаковке ....mvc.rest
:
@Configuration
@ComponentScan
public class WebMvcConfig extends WebMvcAutoConfigurationAdapter {
@Autowired public SpringTemplateEngine templateEngine;
@Bean
public ThymeleafTilesConfigurer tilesConfigurer() {
final ThymeleafTilesConfigurer configurer = new ThymeleafTilesConfigurer();
configurer.setDefinitions(ThymeleafAutoConfiguration.DEFAULT_PREFIX + "**/views.xml");
return configurer;
}
@Bean
public ThymeleafViewResolver thymeleafViewResolver() {
final ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setViewClass(ThymeleafTilesView.class);
resolver.setTemplateEngine(templateEngine);
resolver.setCharacterEncoding(UTF_8);
return resolver;
}
@Bean
public TilesDialect tilesDialect() {
return new TilesDialect();
}
//
@Value("${server.session-timeout}") private Long sessionTimeOut;
@Override
public void configureAsyncSupport(final AsyncSupportConfigurer configurer) {
configurer.setDefaultTimeout(sessionTimeOut * 1000L);
configurer.registerCallableInterceptors(timeoutInterceptor());
}
@Bean
public TimeoutCallableProcessingInterceptor timeoutInterceptor() {
return new TimeoutCallableProcessingInterceptor();
}
}
===
Мой класс RestConfig довольно прост
@Configuration
@ComponentScan
public class RestMvcConfig {}
===
Я переместил все мои html-файлы или тимилиф-шаблоны в папку template в папке src/main/resources. Также в той же папке вы можете поместить все ресурсы клиента, такие как изображения, js и css, в папку static. Папка static и шаблоны являются ключевыми словами и будут автоматически найдены Spring-Boot. В файле application.properties нет специальных конфигураций, которые потребуются для плиток тимила и апача.
====
Чтобы ваше приложение могло найти ресурсы, вы можете настроить путь следующим образом:
<link rel="stylesheet" type="text/css" media="screen, projection"
href="/static/css/bootstrap.css"
th:href="@{/css/bootstrap.css}" />
<link rel="stylesheet" type="text/css" media="screen, projection"
href="/static/css/bootstrap-responsive.css"
th:href="@{/css/bootstrap-responsive.css}" />
===
скоросшиватель java/src/webapp
больше не нужно!!!
====
Если это поможет вам, не стесняйтесь голосовать;-). Если вам нужна дополнительная информация, просто прокомментируйте, я постараюсь ответить в течение нескольких дней.
======
ВТОРОЙ ШАГ
Хорошо, до сих пор это работает только под Eclipse. Когда я делаю исполняемый файл jar, я получаю сообщение об ошибке. Может быть, кто-то хочет помочь;-)
Stacktrace - это:
org.thymeleaf.exceptions.TemplateInputException: Error resolving template "/layout/login", template might not exist or might not be accessible by any of the configured Template Resolvers
at org.thymeleaf.TemplateRepository.getTemplate(TemplateRepository.java:245)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1104)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1060)
at org.thymeleaf.extras.tiles2.renderer.ThymeleafAttributeRenderer.write(ThymeleafAttributeRenderer.java:155)
at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
at org.thymeleaf.extras.tiles2.renderer.MetadataCleaningAttributeRendererWrapper.render(MetadataCleaningAttributeRendererWrapper.java:111)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:690)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:644)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:627)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:321)
at org.thymeleaf.extras.tiles2.spring4.web.view.ThymeleafTilesView.render(ThymeleafTilesView.java:125)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1221)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1005)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:952)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:280)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration$MetricsFilter.doFilterInternal(MetricFilterAutoConfiguration.java:90)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1736)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1695)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Структура моего JAR выглядит так:
======
РЕШЕНИЕ:
Я не знаю точно, почему, но, кроме того, мне нужно исправить URL-пути для моих шаблонов, что работает как в Eclipse, но не как исполняемый файл jar. Чтобы запустить его в обеих средах, мне пришлось исправить все URL-адреса шаблонов, как показано ниже, и посмотреть на значение атрибута:
ДО:
<definition name="home" extends="standard1ColLayout">
<put-attribute name="title" value="/home/title :: content" type="thymeleaf" />
<put-attribute name="body" value="/home/body :: content" type="thymeleaf" />
</definition>
ПОСЛЕ:
<definition name="home" extends="standard1ColLayout">
<put-attribute name="title" value="./home/title :: content" type="thymeleaf" />
<put-attribute name="body" value="./home/body :: content" type="thymeleaf" />
</definition>
Наконец, он работает под Eclipse и как исполняемые файлы. Переход от обычного Spring-Project к Spring-Boot Project не был действительно легким, я надеюсь, что это поможет другим разработчикам, и я надеюсь, что этот пост стоит проголосовать.;-)
Этот пример демонстрирует, как настроить Thymeleaf с плитками Apache, но он позволяет весенней загрузке автоматически настроить Thymeleaf. Таким образом, вы по-прежнему можете использовать все предопределенные переменные среды spring-boot, такие как spring.thymeleaf.* В вашем application.properties
@Configuration
@AutoConfigureAfter(ThymeleafAutoConfiguration.class)//tweak autoconfiguration for apache tiles after spring boot
@EnableConfigurationProperties(ThymeleafProperties.class)
public class ThymeleafTilesConfig {
@Autowired//this bean is autoconfigured with spring-boot-thymeleaf
private ThymeleafViewResolver thymeleafViewResolver;
@Autowired
private ThymeleafProperties properties;
@PostConstruct
public void setThymeleafTilesViewClass() {
//just set view class for thymeleaf-tiles
thymeleafViewResolver.setViewClass(ThymeleafTilesView.class);
}
@Bean
TilesDialect tilesDialect() {
// This bean will be auto picked-up by spring-boot and will be autoconfigured :)
return new TilesDialect();
}
@Bean//create tiles configurer for your needs
ThymeleafTilesConfigurer tilesConfigurer() {
final ThymeleafTilesConfigurer configurer = new ThymeleafTilesConfigurer();
configurer.setDefinitions("classpath:/templates/**/views.xml");
configurer.setCheckRefresh(!properties.isCache());
return configurer;
}
}