Spring Boot提供了spring-boot-starter-web(嵌入tomcat和Spring MVC的依赖)为Web开发做支持。
Thymeleaf基础知识
Thymeleaf是一个java类库,是一个xml/xhtml/html5的模板引擎,可以作为MVC的Web应用的View层。提供了额外的模块与Spring MVC集成,可以使用Thymeleaf完全替代jsp。
Thymeleaf网站:
http://www.thymelead.org
1.引入Thymeleaf,代码:
<
html
xmlns:
th
=
"http://www.thymeleaf.org"
>
<!--通过xmlns:th="http://www.thymeleaf.org"命名空间,将镜头页面转换为动态的视图,需要进行动态处理的元素将使用“th:”为前缀-->
<
head
>
<
meta
content=
"text/html;charset=UTF-8"
/>
<
link
th
:src=
"@{bootstrap/css/bootstrap.min.css}"
rel=
"stylesheet"
/>
<
link
th
:src=
"@{bootstrap/css/bootstrap-theme.min.css}"
rel=
"stylesheet"
/>
</
head
>
<
body
>
<
script
th
:src=
"@{jquery-1.10.2.min.js}"
type=
"text/javascript"
></
script
>
<!--通过“@{}”引用Web静态资源,这在jsp极易出错-->
<
script
th
:src=
"@{bootstrap/js/bootstrap.min.js}"
></
script
>
</
body
>
</
html
>
2.访问Model的数据
<
div
class=
"panel panel-primary"
>
<
div
class=
"panel-heading"
>
<
h3
class=
"panel-title"
></
h3
>
</
div
>
<
div
class=
"panel-body"
>
<
span
th
:text=
"${singlePerson.name}}"
></
span
>
<!--使用<span th:text="${singlePerson.name}}"></span>访问model中的singlePerson的name属性-->
<!--注意:需要处理的动态内容需要加上“th:”前缀-->
</
div
>
</
div
>
3.model中的数据迭代
<
div
class=
"panel panel-primary"
>
<
div
class=
"panel-heading"
>
<
h3
class=
"panel-title"
>
列表
</
h3
>
</
div
>
<
div
class=
"panel-body"
>
<
ul
class=
"list-group"
>
<
li
class=
"list-group-item"
th
:each=
"person:${people}"
>
<
span
th
:text=
"${person.name}"
></
span
>
</
li
>
</
ul
>
<!--使用th:each来做循环迭代th:each="person:${people}",person作为迭代元素来使用-->
</
div
>
</
div
>
4.数据判断
<
div
th
:if=
"${not #lists.isEmpty(people)}"
>
<!--通过使用${not #lists.isEmpty(people)}表达式判断peoples是否为空。
Thymeleaf支持>、<、>=、<=、==、!=作为比较条件,同时也支持将SpringEL表达式语言用于条件中-->
<
div
class=
"panel panel-primary"
>
<
div
class=
"panel-heading"
>
<
h3
class=
"panel-title"
>
列表
</
h3
>
</
div
>
<
div
class=
"panel-body"
>
<
ul
class=
"list-group"
>
<
li
class=
"list-group-item"
th
:each=
"person:${people}"
>
<
span
th
:text=
"${person.name}"
></
span
>
</
li
>
</
ul
>
</
div
>
</
div
>
</
div
>
5.在javascript中访问Model
<
script
th
:inline=
"javascript"
>
//通过th:inline="javascript"添加到script标签,这样Javascript代码即可访问model属性
//通过[[${}}]]格式获取实际的值
var
single
=[[${singlePerson}]];
console
.
log
(
single
.name+
"/"
+
single
.age)
</
script
>
html通过按钮获得model的值
<
li
class=
"list-group-item"
th
:each=
"person:${people}"
>
<
span
th
:text=
"${person.name}"
></
span
>
<
button
class=
"btn"
th
:οnclick=
"'getName(\''+${person.name}+'\');'"
></
button
>
</
li
>
与Spring MVC集成
在Spring MVC中,集成模板引擎需要定义ViewResolver,而ViewResolver需要定义一个View
例如:
@Bean//映射路径和实际页面的位置
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/classes/views/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
return viewResolver;
}
Thymeleaf定义了org.thymeleaf.spring4.view.ThymeleafView和org.thymeleaf.spring4.view.ThymeleafViewResolver(默认使用ThymeleafView作为View)
Thymeleaf提供了SpringTemplateEngine类,用来驱动在Spring MVC下使用Thymeleaf模板引擎,提供了TemplateResolver用来设置通用的模板引擎(包含前后缀)
@Bean
public
TemplateResolver templateResolver(){
TemplateResolver templateResolver=
new
ServletContextTemplateResolver();
templateResolver.setPrefix(
"/WEB-INF/templates"
);
templateResolver.setSuffix(
".html"
);
templateResolver.setTemplateMode(
"HTML5"
);
return
templateResolver;
}
@Bean
public
SpringTemplateEngine templateEngine(){
SpringTemplateEngine templateEngine=
new
SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
return
templateEngine;
}
@Bean
public
ThymeleafViewResolver thymeleafViewResolver(){
ThymeleafViewResolver thymeleafViewResolver=
new
ThymeleafViewResolver();
thymeleafViewResolver.setTemplateEngine(templateEngine());
return
thymeleafViewResolver;
}
Spring Boot的Thymeleaf支持
Spring Boot通过org.springframework.boot.autoconfigure.thymeleaf包对Thymeleaf进行了自动配置
实战
1.新建Spring Boot项目,选择Thymeleaf依赖
2.javaBean示例
package
com.hand;
/**
* Created by lqy on 2017-11-26.
*/
public class
Person {
private
String
name
;
private int
age
;
public
Person(){
super
();
}
public
Person(String name,
int
age){
super
();
this
.
name
=name;
this
.
age
=age;
}
public
String getName(){
return
name
;
}
public int
getAge(){
return
age
;
}
public void
setName(){
this
.
name
=
name
;
}
public void
setAge(){
this
.
age
=
age
;
}
}
3.脚本样式静态文件
4.演示页面
代码如下:
<
html
xmlns:
th
=
"http://www.thymeleaf.org"
>
<
head
>
<
meta
content=
"text/html;charset=UTF-8"
/>
<
meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge"
/>
<
meta
name=
"viewport"
content=
"width=device-width, initial-scale=1"
/>
<
link
th
:href=
"@{bootstrap/css/bootstrap.min.css}"
rel=
"stylesheet"
/>
<
link
th
:href=
"@{bootstrap/css/bootstrap-theme.min.css}"
rel=
"stylesheet"
/>
</
head
>
<
body
>
<
div
class=
"panel panel-primary"
>
<
div
class=
"panel-heading"
>
<
h3
class=
"panel-title"
>
访问model
</
h3
>
</
div
>
<
div
class=
"panel-body"
>
<
span
th
:text=
"${singlePerson.name}"
></
span
>
</
div
>
</
div
>
<
div
th
:if=
"${not #lists.isEmpty(people)}"
>
<
div
class=
"panel panel-primary"
>
<
div
class=
"panel-heading"
>
<
h3
class=
"panel-title"
>
列表
</
h3
>
</
div
>
<
div
class=
"panel-body"
>
<
ul
class=
"list-group"
>
<
li
class=
"list-group-item"
th
:each=
"person:${people}"
>
<
span
th
:text=
"${person.name}"
></
span
>
<
span
th
:text=
"${person.age}"
></
span
>
<
button
class=
"btn"
th
:οnclick=
"'getName(\'' + ${person.name} + '\');'"
>
获得名字
</
button
>
</
li
>
</
ul
>
</
div
>
</
div
>
</
div
>
<
script
th
:src=
"@{jquery-1.10.2.min.js}"
type=
"text/javascript"
></
script
>
<!-- 2 -->
<
script
th
:src=
"@{bootstrap/js/bootstrap.min.js}"
></
script
>
<!-- 2 -->
<
script
th
:inline=
"javascript"
>
var
single
= [[${singlePerson}]];
console
.
log
(
single
.name+
"/"
+
single
.age)
function
getName
(name){
console
.
log
(name);
}
</
script
>
</
body
>
</
html
>
5.数据准备
做一个控制器
package
com.hand;
import
org.springframework.stereotype.
Controller
;
import
org.springframework.ui.Model;
import
org.springframework.web.bind.annotation.
RequestMapping
;
import
java.util.ArrayList;
import
java.util.List;
/**
* Created by lqy on 2017-11-26.
*/
@Controller
public class
PerService {
@RequestMapping
(
"/"
)
public
String index(Model model){
Person single =
new
Person(
"aa"
,
11
);
List<Person> people =
new
ArrayList<Person>();
Person p1 =
new
Person(
"xx"
,
11
);
Person p2 =
new
Person(
"yy"
,
22
);
Person p3 =
new
Person(
"zz"
,
33
);
people.add(p1);
people.add(p2);
people.add(p3);
model.addAttribute(
"singlePerson"
, single);
model.addAttribute(
"people"
, people);
return
"index"
;
}
}
入口类
package
com.hand;
import
org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.
SpringBootApplication
;
@SpringBootApplication
public class
SpringThymeleafApplication {
public static void
main(String[] args) {
SpringApplication.
run
(SpringThymeleafApplication.
class
, args);
}
}
最终访问效果
单击zz可以得到名字
Web相关配置
1.Spring提供的自动配置
1.自动配置的ViewResolver
(1)ContentNegotiatingViewResolver
Spring MVC提供的特殊ViewResolver,ContentNegotiatingViewResolver不是自己处理View,而是代理给不同的ViewResolver来处理不同的View,具备很高的优先级。
(2)BeanNameViewResolver
在控制器(@Controller)中的一个方法返回值的字符串(即视图名)会根据BeanNameViewResolver去查找Bean的名称为返回字符串的View渲染视图。
举例:
定义BeanNameViewResolver的Bean
@Bean
public
BeanNameViewResolver beanNameViewResolver(){
BeanNameViewResolver resolver=
new
BeanNameViewResolver();
return
resolver;
}
定义一个View的Bean
@Bean
public
MappingJackson2JsonView jsonView(){
MappingJackson2JsonView jsonView=
new
MappingJackson2JsonView();
return
jsonView;
}
在控制器中返回值字符串为jsonView,它会找Bean名字为jsonView的视图渲染
@RequestMapping
(value =
"/json"
,produces ={MediaType.
APPLICATION_JSON_VALUE
} )
public
String json(Model model){
Person single=
new
Person(
"aa"
,
11
);
model.addAttribute(
"single"
,single);
return
"jsonView"
;
}
(3)
InternalResourceViewResolver
这是极为常用的ViewResolver,主要通过设置前后缀以及控制器中方法返回视图名的字符串,得到实际页面
@Bean
@ConditionalOnMissingBean
(InternalResourceViewResolver.
class
)
public
InternalResourceViewResolver defaultViewResolver(){
InternalResourceViewResolver resolver=
new
InternalResourceViewResolver();
resolver.setPrefix(
this
.prefix);
resolver.setSuffix(
this
.suffix);
return
resolver;
}
2.自动配置的静态资源
在自动配置类的addResourceHandlers方法中定义了以下静态资源的自动配置
(1)类路径文件
把类路径下的/static、/public、/resources和/MEAT-INF/resources文件夹下的静态文件直接映射成/**,通过http://localhost:8080/**直接访问
(2)webjar(将我们脚本框架封装在Jar包中的jar包)
把webjar的/META-INF/resources/webjars/下的静态文件映射为/webjar/**,可以通过http://localhost:8080/webjar/**直接访问
3.自动配置的Formatter和Converter(具体查看
WebMvcAutoConfiguration类addFormatters方法
)
只要定义了Converter、GenericConverter和Formatter接口的实现类的Bean,这些Bean就自动注册到Spring MVC中
4.自动配置的HttpMessageConverters(具体查看
WebMvcAutoConfiguration类
)
5.静态首页的支持
把静态index.html文件放置在如下目录:
classpath:/META-INF/resources/index.html
classpath:/resources/index.html
classpath:/static/index.html
classpath:/public/index.html
2.接管Spring Boot的Web配置
如果Spring Boot提供的Spring MVC不满足要求,可以通过定义一个(含有@Configuratioon和@EnableWebMvc注解)配置类来实现完全自己控制的MVC配置。
当需要在Spring Boot提供的基础上额外加自己的配置时,可以定义一个配置类继承
WebMvcConfigurerAdapter,无须使用@EnableWebMvc注解。
例如:
@Configuration
public class
testssss
extends
WebMvcConfigurerAdapter{
@Override
public void
addViewControllers(ViewControllerRegistry registry){
registry.addViewController(
"/xx"
).setViewName(
"/xx"
);
}
}
提醒:再次重写的addViewControllers方法不会覆盖WebMvcConfigurerAdapter中的方法。我们的配置和Spring Boot自动配置可以同时生效
3.注册Servlet、Filter、Listener
使用嵌入式的Servlet容器(Tomcat、Jetty)时,通过将Servlet、Filter、Listener声明为Spring Bean而达到注册效果。或者注册
ServletRegistrationBean、FilterRegistrationBean 和ServletListenerRegistrationBean的Bean
(1)直接注册Bean:
@Bean
public
XxServlet xxServlet(){
return new
XxServlet();
}
@Bean
public
YyFilter yyFilter(){
return new
YyFilter();
}
@Bean
public
ZzListener zzListener(){
return new
ZzListener();
}
(2)通过
RegistrationBean
@Bean
public
ServletRegistrationBean servletRegistrationBean(){
return new
ServletRegistrationBean(
new
XxServlet(),
"/xx/*"
);
}
@Bean
public
FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean registrationBean=
new
FilterRegistrationBean();
registrationBean.setFilter(
new
YyFilter());
registrationBean.setOrder(
2
);
return
registrationBean;
}
@Bean
public
ServletListenerRegistrationBean<ZzListener> zzListenerServletListenerRegistrationBean(){
return new
ServletListenerRegistrationBean<ZzListener>(
new
ZzListener())
}