Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
db83e899
Commit
db83e899
authored
Jul 12, 2016
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for Thymeleaf 3 while keeping Thymeleaf 2 as the default
Closes gh-4393
parent
18d99245
Changes
22
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
11596 additions
and
106 deletions
+11596
-106
AbstractTemplateResolverConfiguration.java
...gure/thymeleaf/AbstractTemplateResolverConfiguration.java
+81
-0
AbstractThymeleafViewResolverConfiguration.java
...thymeleaf/AbstractThymeleafViewResolverConfiguration.java
+78
-0
ThymeleafAutoConfiguration.java
...t/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java
+86
-105
howto.adoc
spring-boot-docs/src/main/asciidoc/howto.adoc
+24
-0
pom.xml
spring-boot-samples/pom.xml
+2
-1
pom.xml
...ng-boot-samples/spring-boot-sample-web-thymeleaf3/pom.xml
+42
-0
InMemoryMessageRepository.java
...java/sample/web/thymeleaf3/InMemoryMessageRepository.java
+58
-0
Message.java
...ymeleaf3/src/main/java/sample/web/thymeleaf3/Message.java
+69
-0
MessageRepository.java
...rc/main/java/sample/web/thymeleaf3/MessageRepository.java
+32
-0
SampleWebThymeleaf3Application.java
...sample/web/thymeleaf3/SampleWebThymeleaf3Application.java
+46
-0
MessageController.java
...ain/java/sample/web/thymeleaf3/mvc/MessageController.java
+92
-0
application.properties
...-web-thymeleaf3/src/main/resources/application.properties
+2
-0
bootstrap.min.css
...hymeleaf3/src/main/resources/static/css/bootstrap.min.css
+11
-0
favicon.ico
...mple-web-thymeleaf3/src/main/resources/static/favicon.ico
+0
-0
jquery-1.7.2.js
...b-thymeleaf3/src/main/resources/static/js/jquery-1.7.2.js
+9404
-0
jquery.validate.js
...hymeleaf3/src/main/resources/static/js/jquery.validate.js
+1250
-0
layout.html
...e-web-thymeleaf3/src/main/resources/templates/layout.html
+25
-0
form.html
...hymeleaf3/src/main/resources/templates/messages/form.html
+34
-0
list.html
...hymeleaf3/src/main/resources/templates/messages/list.html
+37
-0
view.html
...hymeleaf3/src/main/resources/templates/messages/view.html
+35
-0
MessageControllerWebTests.java
...java/sample/web/thymeleaf3/MessageControllerWebTests.java
+111
-0
SampleWebThymeleaf3ApplicationTests.java
...e/web/thymeleaf3/SampleWebThymeleaf3ApplicationTests.java
+77
-0
No files found.
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/AbstractTemplateResolverConfiguration.java
0 → 100644
View file @
db83e899
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
autoconfigure
.
thymeleaf
;
import
javax.annotation.PostConstruct
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver
;
import
org.thymeleaf.templateresolver.TemplateResolver
;
import
org.springframework.boot.autoconfigure.template.TemplateLocation
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.annotation.Bean
;
/**
* Abstract base class for the configuration of a Thymeleaf {@link TemplateResolver}.
*
* @author Andy Wilkinson
*/
abstract
class
AbstractTemplateResolverConfiguration
{
private
static
final
Log
logger
=
LogFactory
.
getLog
(
AbstractTemplateResolverConfiguration
.
class
);
private
final
ThymeleafProperties
properties
;
private
final
ApplicationContext
applicationContext
;
AbstractTemplateResolverConfiguration
(
ThymeleafProperties
properties
,
ApplicationContext
applicationContext
)
{
this
.
properties
=
properties
;
this
.
applicationContext
=
applicationContext
;
}
@PostConstruct
public
void
checkTemplateLocationExists
()
{
boolean
checkTemplateLocation
=
this
.
properties
.
isCheckTemplateLocation
();
if
(
checkTemplateLocation
)
{
TemplateLocation
location
=
new
TemplateLocation
(
this
.
properties
.
getPrefix
());
if
(!
location
.
exists
(
this
.
applicationContext
))
{
logger
.
warn
(
"Cannot find template location: "
+
location
+
" (please add some templates or check "
+
"your Thymeleaf configuration)"
);
}
}
}
@Bean
public
SpringResourceTemplateResolver
defaultTemplateResolver
()
{
SpringResourceTemplateResolver
resolver
=
new
SpringResourceTemplateResolver
();
resolver
.
setApplicationContext
(
this
.
applicationContext
);
resolver
.
setPrefix
(
this
.
properties
.
getPrefix
());
resolver
.
setSuffix
(
this
.
properties
.
getSuffix
());
resolver
.
setTemplateMode
(
this
.
properties
.
getMode
());
if
(
this
.
properties
.
getEncoding
()
!=
null
)
{
resolver
.
setCharacterEncoding
(
this
.
properties
.
getEncoding
().
name
());
}
resolver
.
setCacheable
(
this
.
properties
.
isCache
());
Integer
order
=
this
.
properties
.
getTemplateResolverOrder
();
if
(
order
!=
null
)
{
resolver
.
setOrder
(
order
);
}
return
resolver
;
}
}
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/AbstractThymeleafViewResolverConfiguration.java
0 → 100644
View file @
db83e899
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
autoconfigure
.
thymeleaf
;
import
java.util.LinkedHashMap
;
import
org.thymeleaf.spring4.SpringTemplateEngine
;
import
org.thymeleaf.spring4.view.ThymeleafViewResolver
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.core.Ordered
;
import
org.springframework.util.MimeType
;
/**
* Abstract base class for the configuration of a {@link ThymeleafViewResolver}.
*
* @author Andy Wilkinson
*/
abstract
class
AbstractThymeleafViewResolverConfiguration
{
private
final
ThymeleafProperties
properties
;
private
final
SpringTemplateEngine
templateEngine
;
protected
AbstractThymeleafViewResolverConfiguration
(
ThymeleafProperties
properties
,
SpringTemplateEngine
templateEngine
)
{
this
.
properties
=
properties
;
this
.
templateEngine
=
templateEngine
;
}
@Bean
@ConditionalOnMissingBean
(
name
=
"thymeleafViewResolver"
)
@ConditionalOnProperty
(
name
=
"spring.thymeleaf.enabled"
,
matchIfMissing
=
true
)
public
ThymeleafViewResolver
thymeleafViewResolver
()
{
ThymeleafViewResolver
resolver
=
new
ThymeleafViewResolver
();
configureTemplateEngine
(
resolver
,
this
.
templateEngine
);
resolver
.
setCharacterEncoding
(
this
.
properties
.
getEncoding
().
name
());
resolver
.
setContentType
(
appendCharset
(
this
.
properties
.
getContentType
(),
resolver
.
getCharacterEncoding
()));
resolver
.
setExcludedViewNames
(
this
.
properties
.
getExcludedViewNames
());
resolver
.
setViewNames
(
this
.
properties
.
getViewNames
());
// This resolver acts as a fallback resolver (e.g. like a
// InternalResourceViewResolver) so it needs to have low precedence
resolver
.
setOrder
(
Ordered
.
LOWEST_PRECEDENCE
-
5
);
resolver
.
setCache
(
this
.
properties
.
isCache
());
return
resolver
;
}
protected
abstract
void
configureTemplateEngine
(
ThymeleafViewResolver
resolver
,
SpringTemplateEngine
templateEngine
);
private
String
appendCharset
(
MimeType
type
,
String
charset
)
{
if
(
type
.
getCharset
()
!=
null
)
{
return
type
.
toString
();
}
LinkedHashMap
<
String
,
String
>
parameters
=
new
LinkedHashMap
<
String
,
String
>();
parameters
.
put
(
"charset"
,
charset
);
parameters
.
putAll
(
type
.
getParameters
());
return
new
MimeType
(
type
,
parameters
).
toString
();
}
}
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java
View file @
db83e899
...
...
@@ -16,16 +16,13 @@
package
org
.
springframework
.
boot
.
autoconfigure
.
thymeleaf
;
import
java.lang.reflect.Method
;
import
java.util.Collection
;
import
java.util.LinkedHashMap
;
import
javax.annotation.PostConstruct
;
import
javax.servlet.Servlet
;
import
com.github.mxab.thymeleaf.extras.dataattribute.dialect.DataAttributeDialect
;
import
nz.net.ultraq.thymeleaf.LayoutDialect
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.thymeleaf.dialect.IDialect
;
import
org.thymeleaf.extras.conditionalcomments.dialect.ConditionalCommentsDialect
;
import
org.thymeleaf.extras.java8time.dialect.Java8TimeDialect
;
...
...
@@ -34,7 +31,6 @@ import org.thymeleaf.spring4.SpringTemplateEngine;
import
org.thymeleaf.spring4.resourceresolver.SpringResourceResourceResolver
;
import
org.thymeleaf.spring4.view.ThymeleafViewResolver
;
import
org.thymeleaf.templateresolver.ITemplateResolver
;
import
org.thymeleaf.templateresolver.TemplateResolver
;
import
org.springframework.beans.factory.ObjectProvider
;
import
org.springframework.boot.autoconfigure.AutoConfigureAfter
;
...
...
@@ -43,18 +39,15 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnJava
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication
;
import
org.springframework.boot.autoconfigure.template.TemplateLocation
;
import
org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain
;
import
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.core.Ordered
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.util.
MimeType
;
import
org.springframework.util.
ReflectionUtils
;
import
org.springframework.web.servlet.resource.ResourceUrlEncodingFilter
;
/**
...
...
@@ -69,62 +62,107 @@ import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter;
@Configuration
@EnableConfigurationProperties
(
ThymeleafProperties
.
class
)
@ConditionalOnClass
(
SpringTemplateEngine
.
class
)
@ConditionalOnMissingClass
(
"org.thymeleaf.templatemode.TemplateMode"
)
@AutoConfigureAfter
(
WebMvcAutoConfiguration
.
class
)
public
class
ThymeleafAutoConfiguration
{
private
static
final
Log
logger
=
LogFactory
.
getLog
(
ThymeleafAutoConfiguration
.
class
);
@Configuration
@ConditionalOnMissing
Bean
(
name
=
"defaultTemplateResolver
"
)
public
static
class
DefaultTemplateResolver
Configuration
{
@ConditionalOnMissing
Class
(
"org.thymeleaf.templatemode.TemplateMode
"
)
static
class
Thymeleaf2
Configuration
{
private
final
ThymeleafProperties
properties
;
@Configuration
@ConditionalOnMissingBean
(
name
=
"defaultTemplateResolver"
)
static
class
DefaultTemplateResolverConfiguration
extends
AbstractTemplateResolverConfiguration
{
private
final
ApplicationContext
applicationContext
;
DefaultTemplateResolverConfiguration
(
ThymeleafProperties
properties
,
ApplicationContext
applicationContext
)
{
super
(
properties
,
applicationContext
);
}
public
DefaultTemplateResolverConfiguration
(
ThymeleafProperties
properties
,
ApplicationContext
applicationContext
)
{
this
.
properties
=
properties
;
this
.
applicationContext
=
applicationContext
;
@Bean
public
SpringResourceResourceResolver
thymeleafResourceResolver
(
)
{
return
new
SpringResourceResourceResolver
()
;
}
}
@PostConstruct
public
void
checkTemplateLocationExists
()
{
boolean
checkTemplateLocation
=
this
.
properties
.
isCheckTemplateLocation
();
if
(
checkTemplateLocation
)
{
TemplateLocation
location
=
new
TemplateLocation
(
this
.
properties
.
getPrefix
());
if
(!
location
.
exists
(
this
.
applicationContext
))
{
logger
.
warn
(
"Cannot find template location: "
+
location
+
" (please add some templates or check "
+
"your Thymeleaf configuration)"
);
}
@Configuration
@ConditionalOnClass
({
Servlet
.
class
})
@ConditionalOnWebApplication
static
class
Thymeleaf2ViewResolverConfiguration
extends
AbstractThymeleafViewResolverConfiguration
{
Thymeleaf2ViewResolverConfiguration
(
ThymeleafProperties
properties
,
SpringTemplateEngine
templateEngine
)
{
super
(
properties
,
templateEngine
);
}
@Override
protected
void
configureTemplateEngine
(
ThymeleafViewResolver
resolver
,
SpringTemplateEngine
templateEngine
)
{
resolver
.
setTemplateEngine
(
templateEngine
);
}
}
@Bean
public
TemplateResolver
defaultTemplateResolver
()
{
TemplateResolver
resolver
=
new
TemplateResolver
();
resolver
.
setResourceResolver
(
thymeleafResourceResolver
());
resolver
.
setPrefix
(
this
.
properties
.
getPrefix
());
resolver
.
setSuffix
(
this
.
properties
.
getSuffix
());
resolver
.
setTemplateMode
(
this
.
properties
.
getMode
());
if
(
this
.
properties
.
getEncoding
()
!=
null
)
{
resolver
.
setCharacterEncoding
(
this
.
properties
.
getEncoding
().
name
());
@Configuration
@ConditionalOnClass
(
ConditionalCommentsDialect
.
class
)
static
class
ThymeleafConditionalCommentsDialectConfiguration
{
@Bean
@ConditionalOnMissingBean
public
ConditionalCommentsDialect
conditionalCommentsDialect
()
{
return
new
ConditionalCommentsDialect
();
}
resolver
.
setCacheable
(
this
.
properties
.
isCache
());
Integer
order
=
this
.
properties
.
getTemplateResolverOrder
();
if
(
order
!=
null
)
{
resolver
.
setOrder
(
order
);
}
}
@Configuration
@ConditionalOnClass
(
name
=
"org.thymeleaf.templatemode.TemplateMode"
)
static
class
Thymeleaf3Configuration
{
@Configuration
@ConditionalOnMissingBean
(
name
=
"defaultTemplateResolver"
)
static
class
DefaultTemplateResolverConfiguration
extends
AbstractTemplateResolverConfiguration
{
DefaultTemplateResolverConfiguration
(
ThymeleafProperties
properties
,
ApplicationContext
applicationContext
)
{
super
(
properties
,
applicationContext
);
}
return
resolver
;
}
@Bean
public
SpringResourceResourceResolver
thymeleafResourceResolver
()
{
return
new
SpringResourceResourceResolver
();
@Configuration
@ConditionalOnClass
({
Servlet
.
class
})
@ConditionalOnWebApplication
static
class
Thymeleaf3ViewResolverConfiguration
extends
AbstractThymeleafViewResolverConfiguration
{
Thymeleaf3ViewResolverConfiguration
(
ThymeleafProperties
properties
,
SpringTemplateEngine
templateEngine
)
{
super
(
properties
,
templateEngine
);
}
@Override
protected
void
configureTemplateEngine
(
ThymeleafViewResolver
resolver
,
SpringTemplateEngine
templateEngine
)
{
Method
setTemplateEngine
;
try
{
setTemplateEngine
=
ReflectionUtils
.
findMethod
(
resolver
.
getClass
(),
"setTemplateEngine"
,
Class
.
forName
(
"org.thymeleaf.ITemplateEngine"
,
true
,
resolver
.
getClass
().
getClassLoader
()));
}
catch
(
ClassNotFoundException
ex
)
{
throw
new
IllegalStateException
(
ex
);
}
ReflectionUtils
.
invokeMethod
(
setTemplateEngine
,
resolver
,
templateEngine
);
}
}
}
@Configuration
...
...
@@ -194,18 +232,6 @@ public class ThymeleafAutoConfiguration {
}
@Configuration
@ConditionalOnClass
(
ConditionalCommentsDialect
.
class
)
protected
static
class
ThymeleafConditionalCommentsDialectConfiguration
{
@Bean
@ConditionalOnMissingBean
public
ConditionalCommentsDialect
conditionalCommentsDialect
()
{
return
new
ConditionalCommentsDialect
();
}
}
@Configuration
@ConditionalOnJava
(
ConditionalOnJava
.
JavaVersion
.
EIGHT
)
@ConditionalOnClass
(
Java8TimeDialect
.
class
)
...
...
@@ -219,51 +245,6 @@ public class ThymeleafAutoConfiguration {
}
@Configuration
@ConditionalOnClass
({
Servlet
.
class
})
@ConditionalOnWebApplication
protected
static
class
ThymeleafViewResolverConfiguration
{
private
final
ThymeleafProperties
properties
;
private
final
SpringTemplateEngine
templateEngine
;
protected
ThymeleafViewResolverConfiguration
(
ThymeleafProperties
properties
,
SpringTemplateEngine
templateEngine
)
{
this
.
properties
=
properties
;
this
.
templateEngine
=
templateEngine
;
}
@Bean
@ConditionalOnMissingBean
(
name
=
"thymeleafViewResolver"
)
@ConditionalOnProperty
(
name
=
"spring.thymeleaf.enabled"
,
matchIfMissing
=
true
)
public
ThymeleafViewResolver
thymeleafViewResolver
()
{
ThymeleafViewResolver
resolver
=
new
ThymeleafViewResolver
();
resolver
.
setTemplateEngine
(
this
.
templateEngine
);
resolver
.
setCharacterEncoding
(
this
.
properties
.
getEncoding
().
name
());
resolver
.
setContentType
(
appendCharset
(
this
.
properties
.
getContentType
(),
resolver
.
getCharacterEncoding
()));
resolver
.
setExcludedViewNames
(
this
.
properties
.
getExcludedViewNames
());
resolver
.
setViewNames
(
this
.
properties
.
getViewNames
());
// This resolver acts as a fallback resolver (e.g. like a
// InternalResourceViewResolver) so it needs to have low precedence
resolver
.
setOrder
(
Ordered
.
LOWEST_PRECEDENCE
-
5
);
resolver
.
setCache
(
this
.
properties
.
isCache
());
return
resolver
;
}
private
String
appendCharset
(
MimeType
type
,
String
charset
)
{
if
(
type
.
getCharset
()
!=
null
)
{
return
type
.
toString
();
}
LinkedHashMap
<
String
,
String
>
parameters
=
new
LinkedHashMap
<
String
,
String
>();
parameters
.
put
(
"charset"
,
charset
);
parameters
.
putAll
(
type
.
getParameters
());
return
new
MimeType
(
type
,
parameters
).
toString
();
}
}
@Configuration
@ConditionalOnWebApplication
protected
static
class
ThymeleafResourceHandlingConfig
{
...
...
spring-boot-docs/src/main/asciidoc/howto.adoc
View file @
db83e899
...
...
@@ -1395,6 +1395,30 @@ have been applied from the auto-configuration:
[[howto-use-thymeleaf-3]]
=== Use Thymeleaf 3
By default, `spring-boot-starter-thymeleaf` uses Thymeleaf 2.1. You can use Thymeleaf
3 by overriding the `thymeleaf.version` and `thymeleaf-layout-dialect.version` properties,
for example:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<properties>
<thymeleaf.version>3.0.0.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.0.0</thymeleaf-layout-dialect.version>
</dependency>
----
Please refer to the
{github-code}/spring-boot-samples/spring-boot-sample-web-thymeleaf3[Thymeleaf 3 sample] to
see this in action.
If you are using any of the other auto-configured Thymeleaf Extras (Spring Security,
Data Attribute, or Java 8 Time) you should also override each of their versions to one
that is compatible with Thymeleaf 3.0.
[[howto-http-clients]]
== HTTP clients
...
...
spring-boot-samples/pom.xml
View file @
db83e899
...
...
@@ -97,6 +97,7 @@
<module>
spring-boot-sample-war
</module>
<module>
spring-boot-sample-web-freemarker
</module>
<module>
spring-boot-sample-web-groovy-templates
</module>
<module>
spring-boot-sample-web-jsp
</module>
<module>
spring-boot-sample-web-method-security
</module>
<module>
spring-boot-sample-web-mustache
</module>
<module>
spring-boot-sample-web-secure
</module>
...
...
@@ -104,7 +105,7 @@
<module>
spring-boot-sample-web-secure-github
</module>
<module>
spring-boot-sample-web-secure-jdbc
</module>
<module>
spring-boot-sample-web-static
</module>
<module>
spring-boot-sample-web-
jsp
</module>
<module>
spring-boot-sample-web-
thymeleaf3
</module>
<module>
spring-boot-sample-web-ui
</module>
<module>
spring-boot-sample-web-velocity
</module>
<module>
spring-boot-sample-websocket-jetty
</module>
...
...
spring-boot-samples/spring-boot-sample-web-thymeleaf3/pom.xml
0 → 100755
View file @
db83e899
<?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>
<parent>
<!-- Your own application should inherit from spring-boot-starter-parent -->
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-samples
</artifactId>
<version>
1.4.0.BUILD-SNAPSHOT
</version>
</parent>
<artifactId>
spring-boot-sample-web-thymeleaf3
</artifactId>
<name>
Spring Boot Web Thymeleaf 3 Sample
</name>
<description>
Spring Boot Web Thymeleaf 3 Sample
</description>
<url>
http://projects.spring.io/spring-boot/
</url>
<organization>
<name>
Pivotal Software, Inc.
</name>
<url>
http://www.spring.io
</url>
</organization>
<properties>
<main.basedir>
${basedir}/../..
</main.basedir>
<thymeleaf.version>
3.0.0.RELEASE
</thymeleaf.version>
<thymeleaf-layout-dialect.version>
2.0.0
</thymeleaf-layout-dialect.version>
</properties>
<dependencies>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-thymeleaf
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
</plugin>
</plugins>
</build>
</project>
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/java/sample/web/thymeleaf3/InMemoryMessageRepository.java
0 → 100755
View file @
db83e899
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
sample
.
web
.
thymeleaf3
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentMap
;
import
java.util.concurrent.atomic.AtomicLong
;
/**
* @author Dave Syer
*/
public
class
InMemoryMessageRepository
implements
MessageRepository
{
private
static
AtomicLong
counter
=
new
AtomicLong
();
private
final
ConcurrentMap
<
Long
,
Message
>
messages
=
new
ConcurrentHashMap
<
Long
,
Message
>();
@Override
public
Iterable
<
Message
>
findAll
()
{
return
this
.
messages
.
values
();
}
@Override
public
Message
save
(
Message
message
)
{
Long
id
=
message
.
getId
();
if
(
id
==
null
)
{
id
=
counter
.
incrementAndGet
();
message
.
setId
(
id
);
}
this
.
messages
.
put
(
id
,
message
);
return
message
;
}
@Override
public
Message
findMessage
(
Long
id
)
{
return
this
.
messages
.
get
(
id
);
}
@Override
public
void
deleteMessage
(
Long
id
)
{
this
.
messages
.
remove
(
id
);
}
}
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/java/sample/web/thymeleaf3/Message.java
0 → 100644
View file @
db83e899
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
sample
.
web
.
thymeleaf3
;
import
java.util.Calendar
;
import
org.hibernate.validator.constraints.NotEmpty
;
/**
* @author Rob Winch
*/
public
class
Message
{
private
Long
id
;
@NotEmpty
(
message
=
"Message is required."
)
private
String
text
;
@NotEmpty
(
message
=
"Summary is required."
)
private
String
summary
;
private
Calendar
created
=
Calendar
.
getInstance
();
public
Long
getId
()
{
return
this
.
id
;
}
public
void
setId
(
Long
id
)
{
this
.
id
=
id
;
}
public
Calendar
getCreated
()
{
return
this
.
created
;
}
public
void
setCreated
(
Calendar
created
)
{
this
.
created
=
created
;
}
public
String
getText
()
{
return
this
.
text
;
}
public
void
setText
(
String
text
)
{
this
.
text
=
text
;
}
public
String
getSummary
()
{
return
this
.
summary
;
}
public
void
setSummary
(
String
summary
)
{
this
.
summary
=
summary
;
}
}
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/java/sample/web/thymeleaf3/MessageRepository.java
0 → 100755
View file @
db83e899
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
sample
.
web
.
thymeleaf3
;
/**
* @author Rob Winch
*/
public
interface
MessageRepository
{
Iterable
<
Message
>
findAll
();
Message
save
(
Message
message
);
Message
findMessage
(
Long
id
);
void
deleteMessage
(
Long
id
);
}
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/java/sample/web/thymeleaf3/SampleWebThymeleaf3Application.java
0 → 100644
View file @
db83e899
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
sample
.
web
.
thymeleaf3
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.core.convert.converter.Converter
;
@SpringBootApplication
public
class
SampleWebThymeleaf3Application
{
@Bean
public
MessageRepository
messageRepository
()
{
return
new
InMemoryMessageRepository
();
}
@Bean
public
Converter
<
String
,
Message
>
messageConverter
()
{
return
new
Converter
<
String
,
Message
>()
{
@Override
public
Message
convert
(
String
id
)
{
return
messageRepository
().
findMessage
(
Long
.
valueOf
(
id
));
}
};
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
SpringApplication
.
run
(
SampleWebThymeleaf3Application
.
class
,
args
);
}
}
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/java/sample/web/thymeleaf3/mvc/MessageController.java
0 → 100755
View file @
db83e899
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
sample
.
web
.
thymeleaf3
.
mvc
;
import
javax.validation.Valid
;
import
sample.web.thymeleaf3.Message
;
import
sample.web.thymeleaf3.MessageRepository
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.validation.BindingResult
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.ModelAttribute
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.servlet.ModelAndView
;
import
org.springframework.web.servlet.mvc.support.RedirectAttributes
;
/**
* @author Rob Winch
* @author Doo-Hwan Kwak
*/
@Controller
@RequestMapping
(
"/"
)
public
class
MessageController
{
private
final
MessageRepository
messageRepository
;
public
MessageController
(
MessageRepository
messageRepository
)
{
this
.
messageRepository
=
messageRepository
;
}
@GetMapping
public
ModelAndView
list
()
{
Iterable
<
Message
>
messages
=
this
.
messageRepository
.
findAll
();
return
new
ModelAndView
(
"messages/list"
,
"messages"
,
messages
);
}
@GetMapping
(
"{id}"
)
public
ModelAndView
view
(
@PathVariable
(
"id"
)
Message
message
)
{
return
new
ModelAndView
(
"messages/view"
,
"message"
,
message
);
}
@GetMapping
(
params
=
"form"
)
public
String
createForm
(
@ModelAttribute
Message
message
)
{
return
"messages/form"
;
}
@PostMapping
public
ModelAndView
create
(
@Valid
Message
message
,
BindingResult
result
,
RedirectAttributes
redirect
)
{
if
(
result
.
hasErrors
())
{
return
new
ModelAndView
(
"messages/form"
,
"formErrors"
,
result
.
getAllErrors
());
}
message
=
this
.
messageRepository
.
save
(
message
);
redirect
.
addFlashAttribute
(
"globalMessage"
,
"Successfully created a new message"
);
return
new
ModelAndView
(
"redirect:/{message.id}"
,
"message.id"
,
message
.
getId
());
}
@RequestMapping
(
"foo"
)
public
String
foo
()
{
throw
new
RuntimeException
(
"Expected exception in controller"
);
}
@GetMapping
(
value
=
"delete/{id}"
)
public
ModelAndView
delete
(
@PathVariable
(
"id"
)
Long
id
)
{
this
.
messageRepository
.
deleteMessage
(
id
);
Iterable
<
Message
>
messages
=
this
.
messageRepository
.
findAll
();
return
new
ModelAndView
(
"messages/list"
,
"messages"
,
messages
);
}
@GetMapping
(
value
=
"modify/{id}"
)
public
ModelAndView
modifyForm
(
@PathVariable
(
"id"
)
Message
message
)
{
return
new
ModelAndView
(
"messages/form"
,
"message"
,
message
);
}
}
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/resources/application.properties
0 → 100644
View file @
db83e899
# Allow Thymeleaf templates to be reloaded at dev time
spring.thymeleaf.cache
:
false
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/resources/static/css/bootstrap.min.css
0 → 100644
View file @
db83e899
This diff is collapsed.
Click to expand it.
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/resources/static/favicon.ico
0 → 100644
View file @
db83e899
2.79 KB
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/resources/static/js/jquery-1.7.2.js
0 → 100644
View file @
db83e899
This diff is collapsed.
Click to expand it.
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/resources/static/js/jquery.validate.js
0 → 100644
View file @
db83e899
This diff is collapsed.
Click to expand it.
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/resources/templates/layout.html
0 → 100644
View file @
db83e899
<!DOCTYPE html>
<html
xmlns:th=
"http://www.thymeleaf.org"
xmlns:layout=
"http://www.ultraq.net.nz/web/thymeleaf/layout"
>
<head>
<title>
Layout
</title>
<link
rel=
"stylesheet"
th:href=
"@{/css/bootstrap.min.css}"
href=
"../../css/bootstrap.min.css"
/>
</head>
<body>
<div
class=
"container"
>
<div
class=
"navbar"
>
<div
class=
"navbar-inner"
>
<a
class=
"brand"
href=
"https://github.com/ultraq/thymeleaf-layout-dialect"
>
Thymeleaf - Layout
</a>
<ul
class=
"nav"
>
<li><a
th:href=
"@{/}"
href=
"messages.html"
>
Messages
</a></li>
</ul>
</div>
</div>
<h1
layout:fragment=
"header"
>
Layout
</h1>
<div
layout:fragment=
"content"
>
Fake content
</div>
</div>
</body>
</html>
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/resources/templates/messages/form.html
0 → 100644
View file @
db83e899
<!DOCTYPE html>
<html
xmlns:th=
"http://www.thymeleaf.org"
xmlns:layout=
"http://www.ultraq.net.nz/web/thymeleaf/layout"
layout:decorate=
"layout"
>
<head>
<title>
Messages : Create
</title>
</head>
<body>
<h1
layout:fragment=
"header"
>
Messages : Create
</h1>
<div
layout:fragment=
"content"
class=
"container"
>
<form
id=
"messageForm"
th:action=
"@{/(form)}"
th:object=
"${message}"
action=
"#"
method=
"post"
>
<div
th:if=
"${#fields.hasErrors('*')}"
class=
"alert alert-error"
>
<p
th:each=
"error : ${#fields.errors('*')}"
th:text=
"${error}"
>
Validation error
</p>
</div>
<div
class=
"pull-right"
>
<a
th:href=
"@{/}"
href=
"messages.html"
>
Messages
</a>
</div>
<input
type=
"hidden"
th:field=
"*{id}"
th:class=
"${#fields.hasErrors('id')} ? 'field-error'"
/>
<label
for=
"summary"
>
Summary
</label>
<input
type=
"text"
th:field=
"*{summary}"
th:class=
"${#fields.hasErrors('summary')} ? 'field-error'"
/>
<label
for=
"text"
>
Message
</label>
<textarea
th:field=
"*{text}"
th:class=
"${#fields.hasErrors('text')} ? 'field-error'"
></textarea>
<div
class=
"form-actions"
>
<input
type=
"submit"
value=
"Save"
/>
</div>
</form>
</div>
</body>
</html>
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/resources/templates/messages/list.html
0 → 100644
View file @
db83e899
<!DOCTYPE html>
<html
xmlns:th=
"http://www.thymeleaf.org"
xmlns:layout=
"http://www.ultraq.net.nz/web/thymeleaf/layout"
layout:decorate=
"layout"
>
<head>
<title>
Messages : View all
</title>
</head>
<body>
<h1
layout:fragment=
"header"
>
Messages : View all
</h1>
<div
layout:fragment=
"content"
class=
"container"
>
<div
class=
"pull-right"
>
<a
href=
"form.html"
th:href=
"@{/(form)}"
>
Create Message
</a>
</div>
<table
class=
"table table-bordered table-striped"
>
<thead>
<tr>
<td>
ID
</td>
<td>
Created
</td>
<td>
Summary
</td>
</tr>
</thead>
<tbody>
<tr
th:if=
"${messages.empty}"
>
<td
colspan=
"3"
>
No messages
</td>
</tr>
<tr
th:each=
"message : ${messages}"
>
<td
th:text=
"${message.id}"
>
1
</td>
<td
th:text=
"${#calendars.format(message.created)}"
>
July 11,
2012 2:17:16 PM CDT
</td>
<td><a
href=
"view.html"
th:href=
"@{'/' + ${message.id}}"
th:text=
"${message.summary}"
>
The summary
</a></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/main/resources/templates/messages/view.html
0 → 100644
View file @
db83e899
<html
xmlns:th=
"http://www.thymeleaf.org"
xmlns:layout=
"http://www.ultraq.net.nz/web/thymeleaf/layout"
layout:decorate=
"layout"
>
<head>
<title>
Messages : View
</title>
</head>
<body>
<h1
layout:fragment=
"header"
>
Messages : Create
</h1>
<div
layout:fragment=
"content"
class=
"container"
>
<div
class=
"alert alert-success"
th:if=
"${globalMessage}"
th:text=
"${globalMessage}"
>
Some Success message
</div>
<div
class=
"pull-right"
>
<a
th:href=
"@{/}"
href=
"list.html"
>
Messages
</a>
</div>
<dl>
<dt>
ID
</dt>
<dd
id=
"id"
th:text=
"${message.id}"
>
123
</dd>
<dt>
Date
</dt>
<dd
id=
"created"
th:text=
"${#calendars.format(message.created)}"
>
July 11, 2012 2:17:16 PM CDT
</dd>
<dt>
Summary
</dt>
<dd
id=
"summary"
th:text=
"${message.summary}"
>
A short summary...
</dd>
<dt>
Message
</dt>
<dd
id=
"text"
th:text=
"${message.text}"
>
A detailed message that
is longer than the summary.
</dd>
</dl>
<div
class=
"pull-left"
>
<a
href=
"messages"
th:href=
"@{'/delete/' + ${message.id}}"
>
delete
</a>
|
<a
href=
"form.html"
th:href=
"@{'/modify/' + ${message.id}}"
>
modify
</a>
</div>
</div>
</body>
</html>
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/test/java/sample/web/thymeleaf3/MessageControllerWebTests.java
0 → 100644
View file @
db83e899
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
sample
.
web
.
thymeleaf3
;
import
java.util.regex.Pattern
;
import
org.hamcrest.Description
;
import
org.hamcrest.TypeSafeMatcher
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
sample.web.thymeleaf3.SampleWebThymeleaf3Application
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.test.context.ContextConfiguration
;
import
org.springframework.test.context.junit4.SpringRunner
;
import
org.springframework.test.context.web.WebAppConfiguration
;
import
org.springframework.test.web.servlet.MockMvc
;
import
org.springframework.test.web.servlet.setup.MockMvcBuilders
;
import
org.springframework.web.context.WebApplicationContext
;
import
static
org
.
hamcrest
.
Matchers
.
containsString
;
import
static
org
.
springframework
.
test
.
web
.
servlet
.
request
.
MockMvcRequestBuilders
.
get
;
import
static
org
.
springframework
.
test
.
web
.
servlet
.
request
.
MockMvcRequestBuilders
.
post
;
import
static
org
.
springframework
.
test
.
web
.
servlet
.
result
.
MockMvcResultMatchers
.
content
;
import
static
org
.
springframework
.
test
.
web
.
servlet
.
result
.
MockMvcResultMatchers
.
header
;
import
static
org
.
springframework
.
test
.
web
.
servlet
.
result
.
MockMvcResultMatchers
.
status
;
/**
* A Basic Spring MVC Test for the Sample Controller"
*
* @author Biju Kunjummen
* @author Doo-Hwan, Kwak
*/
@RunWith
(
SpringRunner
.
class
)
@WebAppConfiguration
@ContextConfiguration
(
classes
=
SampleWebThymeleaf3Application
.
class
)
public
class
MessageControllerWebTests
{
@Autowired
private
WebApplicationContext
wac
;
private
MockMvc
mockMvc
;
@Before
public
void
setup
()
{
this
.
mockMvc
=
MockMvcBuilders
.
webAppContextSetup
(
this
.
wac
).
build
();
}
@Test
public
void
testHome
()
throws
Exception
{
this
.
mockMvc
.
perform
(
get
(
"/"
)).
andExpect
(
status
().
isOk
())
.
andExpect
(
content
().
string
(
containsString
(
"<title>Messages"
)));
}
@Test
public
void
testCreate
()
throws
Exception
{
this
.
mockMvc
.
perform
(
post
(
"/"
).
param
(
"text"
,
"FOO text"
).
param
(
"summary"
,
"FOO"
))
.
andExpect
(
status
().
isFound
())
.
andExpect
(
header
().
string
(
"location"
,
RegexMatcher
.
matches
(
"/[0-9]+"
)));
}
@Test
public
void
testCreateValidation
()
throws
Exception
{
this
.
mockMvc
.
perform
(
post
(
"/"
).
param
(
"text"
,
""
).
param
(
"summary"
,
""
))
.
andExpect
(
status
().
isOk
())
.
andExpect
(
content
().
string
(
containsString
(
"is required"
)));
}
private
static
class
RegexMatcher
extends
TypeSafeMatcher
<
String
>
{
private
final
String
regex
;
public
RegexMatcher
(
String
regex
)
{
this
.
regex
=
regex
;
}
public
static
org
.
hamcrest
.
Matcher
<
java
.
lang
.
String
>
matches
(
String
regex
)
{
return
new
RegexMatcher
(
regex
);
}
@Override
public
boolean
matchesSafely
(
String
item
)
{
return
Pattern
.
compile
(
this
.
regex
).
matcher
(
item
).
find
();
}
@Override
public
void
describeMismatchSafely
(
String
item
,
Description
mismatchDescription
)
{
mismatchDescription
.
appendText
(
"was \""
).
appendText
(
item
).
appendText
(
"\""
);
}
@Override
public
void
describeTo
(
Description
description
)
{
description
.
appendText
(
"a string that matches regex: "
)
.
appendText
(
this
.
regex
);
}
}
}
spring-boot-samples/spring-boot-sample-web-thymeleaf3/src/test/java/sample/web/thymeleaf3/SampleWebThymeleaf3ApplicationTests.java
0 → 100644
View file @
db83e899
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
sample
.
web
.
thymeleaf3
;
import
java.net.URI
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.boot.context.embedded.LocalServerPort
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.boot.test.context.SpringBootTest.WebEnvironment
;
import
org.springframework.boot.test.web.client.TestRestTemplate
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.test.annotation.DirtiesContext
;
import
org.springframework.test.context.junit4.SpringRunner
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Basic integration tests for {@link SampleWebThymeleaf3Application}.
*
* @author Dave Syer
*/
@RunWith
(
SpringRunner
.
class
)
@SpringBootTest
(
webEnvironment
=
WebEnvironment
.
RANDOM_PORT
)
@DirtiesContext
public
class
SampleWebThymeleaf3ApplicationTests
{
@LocalServerPort
private
int
port
;
@Test
public
void
testHome
()
throws
Exception
{
ResponseEntity
<
String
>
entity
=
new
TestRestTemplate
()
.
getForEntity
(
"http://localhost:"
+
this
.
port
,
String
.
class
);
assertThat
(
entity
.
getStatusCode
()).
isEqualTo
(
HttpStatus
.
OK
);
assertThat
(
entity
.
getBody
()).
contains
(
"<title>Messages"
);
assertThat
(
entity
.
getBody
()).
doesNotContain
(
"layout:fragment"
);
}
@Test
public
void
testCreate
()
throws
Exception
{
MultiValueMap
<
String
,
String
>
map
=
new
LinkedMultiValueMap
<
String
,
String
>();
map
.
set
(
"text"
,
"FOO text"
);
map
.
set
(
"summary"
,
"FOO"
);
URI
location
=
new
TestRestTemplate
()
.
postForLocation
(
"http://localhost:"
+
this
.
port
,
map
);
assertThat
(
location
.
toString
()).
contains
(
"localhost:"
+
this
.
port
);
}
@Test
public
void
testCss
()
throws
Exception
{
ResponseEntity
<
String
>
entity
=
new
TestRestTemplate
().
getForEntity
(
"http://localhost:"
+
this
.
port
+
"/css/bootstrap.min.css"
,
String
.
class
);
assertThat
(
entity
.
getStatusCode
()).
isEqualTo
(
HttpStatus
.
OK
);
assertThat
(
entity
.
getBody
()).
contains
(
"body"
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment