1.什么是SpringBoot、为什么用SpringBoot
Spring Boot 是一个轻量级框架,它基于Spring4.0设计,可以完成基于 Spring 的应用程序的大部分配置工作。Spring Boot 的目的是提供一组工具,以便快速构建容易配置的 Spring 应用程序。
问题:Spring 很难配置!
如果您编写过基于 Spring 的应用程序,就会知道只是完成 “Hello, World” 就需要大量配置工作。这不是一件坏事:Spring 是一个优雅的框架集合,需要小心协调配置才能正确工作。但这种优雅的代价是配置变得很复杂(别跟我提 XML)。
解决方案:Spring Boot
Spring Boot 官方简介:
“Spring Boot 使您能轻松地创建独立的、生产级的、基于 Spring 且能直接运行的应用程序。我们对 Spring 平台和第三方库有自己的看法,所以您从一开始只会遇到极少的麻烦。”
基本上讲,这意味着您只需极少的配置,就可以快速获得一个正常运行的 Spring 应用程序。这些极少的配置采用了注释的形式,所以没有 XML。
SpringBoot所具备的特征有:
(1)可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
(2)内嵌Tomcat或Jetty等Servlet容器;
(3)提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;
(4)尽可能自动配置Spring容器;
(5)提供准备好的特性,如指标、健康检查和外部化配置;端点服务。
(6)绝对没有代码生成,不需要XML配置。
官网:https://spring.io/projects
2.开始SpringBoot程序
2.1 创建SpringBoot程序
方式1: 从官网创建工程并下载
https://start.spring.io/
然后点击Generate the project 按钮把生成的工程导入到MyEclipse中即可
方式2:新建Maven工程
通过 IDEA中新建 Module 的向导,如下图:
第1步:
第2步:
第3步:
第4步:
完成模块的创建。
在pom文件中添加父工程和依赖
org.springframework.boot
spring-boot-starter-parent
2.3.3.RELEASE
com.lanqiao.springboot
tutorials
0.0.1
tutorials
tutorials project for Spring Boot
点开maven依赖的jar包查看spring版本,如果是spring5 一定要把jdk改成8及以上。
如果你使用 JSP做视图(springboot 应用推荐使用 Thymeleaf 模板)那么需要添加以下依赖:
javax.servlet jstl org.apache.tomcat.embed tomcat-embed-jasper provided org.springframework.boot spring-boot-starter-tomcat provided修改application.yml
#如果按照一般web工程将页面放在src/main/webapp/WEB-INF/jsp/,则配置前缀
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
server:
port: 8080
tomcat:
uri-encoding: UTF-8
servlet:
context-path: /boot
2.2 引导类
模块创建完成后会在com.lanqiao.springboot.tutorials包下产生一个TutorialsApplication类,该类为启动应用程序的引导类。
//该注解表明当前类是springboot的引导类
@SpringBootApplication
public class TutorialsApplication {
public static void main(String[] args) {
SpringApplication.run(TutorialsApplication.class, args);
}
}
运行启动类,springboot默认扫描启动类所在的包下的主类与子类的所有组件。
使用浏览器访问:localhost:8080
看到这个白页说明web服务器已经启动成功,只不过目前没有找到控制器处理 spring boot默认返回一个白页。
2.3 @SpringBootApplication注解分析
@SpringBootConfiguration 表示该类是一个配置类。
@EnableAutoConfiguration 启用自动配置。借助@Import的支持,收集和注册依赖包中相关的bean定义。例如添加了spring-boot-starter-web依赖,会自动添加Tomcat和SpringMVC的依赖, SpringBoot会对Tomcat和SpringMVC进行自动配置。
@ComponentScan 能扫描当前包及其子包中的类,即com.lanqiao.springboot.tutorials包及其子包下的所有的组件类。比如@Controller和@Service等,最终将这些bean定义加载到spring容器中。
不是说用了springboot以前的就不用写了,只是springboot帮我们封装好了 一个注解就代替了以前几个注解 再加上配置文件才能解决的问题。
springboot不仅让我们的编码是轻量级的,而且也把我们的配置变成了轻量级。
2.4 springboot启动原理
2.5 控制器
2.5.1 传统的springmvc 麻烦
以前使用SpringMVC,需要配置springmvc-servlet.xml文件 在里面加入如下代码
mvc:annotation-driven
还要在web.xml中配置前端控制器
contextConfigLocation
classpath:applicationContext.xml
org.springframework.web.context.ContextLoaderListener
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc-servlet.xml
springmvc
/
接着还要编写Controller, 同时Controller上面还需要加注解 太麻烦!
2.5.2 现在”零配置”
现在在com.lanqiao.springboot.tutorials下新建一个controller包
在controller包下新建第一个程序UserController
/**
@author 张建平 on 2019-08-20 10:47
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService userService;
@GetMapping("/list")
@ResponseBody
public List list() {
List list = userService.select();
return list;
}
}
@RestController注解,它组合了@Controlle和 @ResponseBody两个注解的功能。
@ResponseBody把返回结果直接加入到http的响应体中,不会转发了,会直接响应JSON类型的数据
重新运行TutorialsApplication引导类,在浏览器访问该类结果如下
去除启动控制台Spring Boot的图标
@SpringBootApplication //该注解表明当前类是spring boot的引导类
@ServletComponentScan(basePackages = {“com.lanqiao.springboot.tutorials.servlet”})
@MapperScan(basePackages = {“com.lanqiao.springboot.tutorials.mapper”})
// @EnableCaching // 开启springboot对缓存的支持
public class TutorialsApplication {
public static void main(String[] args) {
// 启动方式 1
// SpringApplication.run(TutorialsApplication.class, args);
// 启动方式 2
// new SpringApplicationBuilder(TutorialsApplication.class)
// .web(WebApplicationType.SERVLET)
// .bannerMode(Banner.Mode.OFF)
// .run(args);
// 启动方式 3
SpringApplication springApplication = new SpringApplication(TutorialsApplication.class);
// 去除启动控制台Spring Boot的图标
springApplication.setBannerMode(Banner.Mode.OFF);
springApplication.run(args);
}
}
重新运行启动类发现图标已经没有了
2.6 修改application.yml默认配置
Springboot使用一个全局的配置文件application.properties 或application.yml放置在src/main/resources目录或者类路径的/config下。
配置文件优先级:
默认读取的配置文件必须以application开头,例如:application.yaml 和application.properties
• 优先级1:项目根路径下的 config 文件夹配置文件
• 优先级2:项目根路径下配置文件
• 优先级3:资源路径resources下的config文件夹配置文件
• 优先级4:资源路径 resources 下配置文件
在src/main/resources下新建application.yml 全局配置文件。
建议使用 yml 文件进行配置。
devtools:
restart:
enabled: true #设置开启热部署
additional-paths: src/main/java #重启目录
exclude: WEB-INF/**
freemarker:
cache: false #页面不加载缓存,修改即时生效
management:
endpoints:
web:
exposure:
include: *
logging:
level:
root: INFO
com.lanqiao.springboot.tutorials.mapper: DEBUG
file: tutorials.log
pattern:
file: %d{yyyy-MMM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{15} - %msg%n
console: %d{yyyy-MMM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{15} - %msg%n
修改控制器,在类上加入@RequestMapping("/test")
全部代码如下
@RestController
public class IndexController {
@GetMapping("/")
@ResponseBody
public String home() {
return "Hello SpringBoot!";
}
}
保存后重启启动类
使用浏览器访问http://localhost:8888/test/hello即可
@ConditionalOnBean:仅在当前容器中存在某个bean时,才会实例化这个Bean。
@ConditionalOnClass:某个class位于类路径上,才会实例化这个Bean。
@ConditionalOnExpression:基于springEL当表达式为true的时候,才会实例化这个Bean。
@ConditionalOnMissingBean:仅在当前上下文中不存在某个bean时,才会实例化这个Bean。
@ConditionalOnMissingClass:某个class在类路径上不存在的时候,才会实例化这个Bean。
@ConditionalOnNotWebApplication:不是web应用时才会实例化这个Bean。
@ConditionalOnWebApplication: 当前项目是 WEB 项目的条件下。
@ConditionalOnNotWebApplication: 当前项目不是 WEB 项目的条件下。
@AutoConfigureAfter:在某个bean完成自动配置后实例化这个bean。
@AutoConfigureBefore:在某个bean完成自动配置前实例化这个bean。
4. springboot整合Mybatis
4.1 加入对mybatis的依赖
4.2 创建表和初始化数据
create table tutorials_users
(
user_id int(255) auto_increment
primary key,
user_name varchar(20) not null,
password varchar(20) not null
);
INSERT INTO tutorials_users VALUES(‘jmaes’,‘12345’);
INSERT INTO tutorials_users VALUES(‘donna’,‘12345’);
INSERT INTO tutorials_users VALUES(‘harvey’,‘12345’);
INSERT INTO tutorials_users VALUES(‘rebort’,‘12345’);
INSERT INTO tutorials_users VALUES(‘jessica’,‘12345’);
4.3 实体类
public class User implements Serializable {
private Integer userId;
private String username;
private String password;
}
4.4 配置springboot的核心配置文件
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/tutorials?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=TutorialsHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
mybatis.type-aliases-package=com.lanqiao.springboot.tutorials.model
4.5 在pom.xml中加入对mysql的依赖
org.springframework.boot spring-boot-starter-jdbc org.apache.tomcat tomcat-jdbc mysql mysql-connector-java 5.1.47 com.zaxxer HikariCP4.6 创建Mapper
创建com.lanqiao.springboot.tutorials.mapper包,在包内创建UserMapper映射器接口 与 SQL XML文件;
使用@Mapper注解标
/**
@author 张建平 on 2019-09-02 10:36
*/
@Mapper
public interface UserMapper {
public List select();
}
SQL XML文件:
在com.lanqiao.springboot.tutorials.TutorialsApplication 引导中加上@MapperScan注解
@SpringBootApplication //该注解表明当前类是spring boot的引导类
//@ServletComponentScan(basePackages = {“com.lanqiao.springboot.tutorials.servlet”})
@MapperScan(basePackages = {“com.lanqiao.springboot.tutorials.mapper”})
public class TutorialsApplication {
public static void main(String[] args) {
// SpringApplication.run(TutorialsApplication.class, args);
SpringApplication springApplication = new SpringApplication(TutorialsApplication.class);
springApplication.setBannerMode(Banner.Mode.OFF); // 去除启动控制台Spring Boot的图标
springApplication.run(args);
}
}
4.7 业务逻辑层
接口与实现
此处省略接口声明的代码。
@Service(“userService”)
@Transactional(rollbackFor = {Exception.class})
public class UserServiceImpl implements IUserService {
@Autowired
UserMapper userMapper;
@Override
public List select() {
System.out.println("执行业务方法select去查询数据库");
return userMapper.select();
}
}
注类上我们使用一个新的注解@Transactional 来实现 AOP 数据库事务的控制,@Transactional 默认情况下所有的操作方法都开启事务。
注入Bean可以用:
@Autowired: Spring提供的注解
@Inject: JSR-330提供的注解
@Resource: JSR-250提供的注解
JSR是Java Specification Requests的缩写,意思是Java 规范提案。
4.8 测试业务逻辑层
@RunWith(SpringRunner.class) // SpringJUnit4ClassRunner.class
@SpringBootTest // @ContextConfiguration({“classpath:*.xml”})
public class UserServiceImplTest {
@Autowired
IUserService userService;
@Test
public void testSelectAll() {
List userList = userService.selectAll();
for (User user : userList) {
System.out.println(user);
}
}
}
4.9 控制器
/**
@author 张建平 on 2019-08-20 10:47
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService userService;
@GetMapping("/list")
@ResponseBody
public List list() {
System.out.println(“UserController#list() 查询用户列表数据。”);
List list = userService.select();
return list;
}
}
4.10 HTML页面
页面必须要放到resource下的static文件夹里,在static文件夹中新建userMain.html页面
ID | Name | Password |
---|
5.springboot整合ehcache缓存
5.1 在pom.xml中加入ehcache依赖
5.2 在 application.yml 中添加配置
spring:
cache:
type: ehcache
ehcache:
config: classpath:ehcache.xml
5.3 配置ehcache缓存
新增ehcache.xml文件并将其放到resources目录中,ehcache.xml的内容如下:
5.4 启用ehcache缓存
(1) 这里需要注意的是缓存的实体类必须实现java.io.Serializable接口。
(2) 在Spring Boot启动引导类上加上 @EnableCaching启动缓存注解(也就是说使项目内部的缓存相关的注解生效)
// 启用缓存注解
@EnableCaching
public class ZzyPortalsApplication {
public static void main(String[] args) {
SpringApplication.run(ZzyPortalsApplication.class, args);
}
}
5.5 使用缓存注解
@Service(“userService”)
@Transactional(rollbackFor = {Exception.class})
// cacheNames为ehcache.xml配置文件内的配置名称
@CacheConfig(cacheNames = {“UsersCache”})
public class UserServiceImpl implements IUserService {
@Autowired
UserMapper userMapper;
@Override
@Transactional(propagation=Propagation.SUPPORTS,readOnly=true)
//Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。
// key 指的是缓存的标识,同时可以用 # 来引用参数。key可以使用SpEL表达式, unless不缓存的条件,result为表示结果的内部关键字
@Cacheable(key = “#id”, unless = “#result.userType==1”)
public User selectById(Integer id) {
return userMapper.selectById(id);
}
}
注意:
1)@CacheConfig( cacheNames = {“userCache”})设置了ehcache的名称,这个名称就是ehcache.xml内的名称;
2)@Cacheable:应用到读取数据的方法上,即可缓存的方法,如查找方法:先从缓存中读取,如果没有再调 用方法获取数据,然后把数据添加到缓存中,适用于查找;
3)@CachePut:主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用。适用于更新和插入;
4)@CacheEvict:主要针对方法配置,能够根据一定的条件对缓存进行清空。适用于删除。
spEL 编写 key
前面说过,缓存的 key 支持使用 spEL 表达式去编写,下面总结一下使用 spEL 去编写 key 可以用的一些元数据:
6.2.修改application.yml
spring:
redis:
port: 6379 # Redis 端口号
database: 0
host: localhost # Redis 主机地址或IP
password: myredis # Redis 连接密码
6.3.在引导类开启springboot对redis的支持
在com.lanqiao.springboot.tutorials.TutorialsApplication 引导中加上@MapperScan注解。
@SpringBootApplication //该注解表明当前类是spring boot的引导类
//@ServletComponentScan(basePackages = {“com.lanqiao.springboot.tutorials.servlet”})
@MapperScan(basePackages = {“com.lanqiao.springboot.tutorials.mapper”})
@EnableCaching // 开启springbootw使用redis缓存的支持
public class TutorialsApplication {
}
6.4.业务层方法标注@Cacheable注解
@Service(“userService”)
@Transactional(rollbackFor = {Exception.class})
public class UserServiceImpl implements IUserService {
@Autowired
UserMapper userMapper;
//Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。
//value属性是redis缓存的名称(key); 方法的返回值是value(List)
//key 指的是缓存的标识,同时可以用 # 来引用参数。key可以使用SpEL表达式: #method_parameter_name
@Cacheable(value = {“allUsers”})
@Override
public List select() {
System.out.println(“执行业务方法select去查询数据库”);
return userMapper.select();
}
@Override
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
// value: 缓存的名称,无value属性会报异常, key缓存的key(cacheName + key),unless不缓存的条件,result为表示结果的内部关键字
@Cacheable(value = “selectById”, key = “#empno”, unless = “#result.comm==null”)
public Employee selectById(Integer empno) {
return employeeMapper.selectById(empno);
}
}
注意:同时需要被缓存的实体实现implements Serializable 序列化接口。
@Cacheable注解有三个参数,value是必须的,还有key和condition。第一个参数,也就是value指明了缓存将被存到什么地方。
任何存储在缓存中的数据为了高速访问都需要一个key。Spring默认使用被@Cacheable注解的方法的签名来作为key,当然你可以重写key,自定义key可以使用SpEL表达式。
@Cacheable(value = {“user”}, key= “#username”)
public Person findByUsername(String username) {
return new Person(username);
}
注解中"#username"是一个SpEL表达式,他将使用findByUsername(String username)方法中的username参数作为key。
最后总结一下流程,当执行到一个被@Cacheable注解的方法时,Spring首先检查condition条件是否满足,如果不满足,执行方法,返回;如果满足,在value所命名的缓存空间中查找使用key存储的对象,如果找到,将找到的结果返回,如果没有找到执行方法,将方法的返回值以key-对象的方式存入value缓存中,然后方法返回。
6.4 访问并测试
http://localhost:8888/user-list.html
观察控制台的输出的日志发现没有查询数据库了。
6.5 检验redis数据库中是否有数据
使用redis客户端查看
使用redis desktop manager查
springboot 整合redis成功
总结:
• Session 复制:利用 Tomcat 等 Web 容器同步复制
• Session 前端存储:利用用户浏览器中 Cookie 保存 Session 信息
• Session 粘滞方案:利用 Nginx 可以做四层 Hash 或七层 Hash 的特性,保证用户的请求都落在同一台机器上,nginx 负载均衡策略采用IP HASH算法。
• Session 后端集中存储方案:利用 Redis 集中存储 Session,Web 应用重启或扩容,Session 也无需丢失。
上面四种方案,优先推荐第四种。
7.1.添加依赖
org.springframework.session spring-session-data-redis org.springframework.boot spring-boot-starter-data-redis7.2 修改application.yml
在application.properties属性文件中加入以下redis配置。
spring:
redis:
port: 6379 # Redis 端口号
database: 0
host: localhost # Redis 主机地址或IP
password: myredis # Redis 连接密码
7.2 在引导类开启session共享
在引导类上加上以下注解即可。
…
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)//启用spring redis session共享
public class TutorialsApplication {
public static void main(String[] args) {
SpringApplication.run(TutorialsApplication.class, args);
}
}
Thymeleaf 是面向 Web 和独立环境的现代服务器端 Java 模板引擎,能够处理 HTML、XML、JavaScript、CSS 甚至纯文本。
Thymeleaf 的主要目标是提供一个优雅和高度可维护的创建模板的方式。 为了实现这一点,它建立在自然模板( Natural Templates)的概念上,将其逻辑注入到模板文件中,不会影响模板被用作设计原型。 这改善了设计的沟通,弥合了设计和开发团队之间的差距。
Thymeleaf 的设计从一开始就遵从 Web 标准,特别是 HTML5,这样就能创建完全符合验证的模板
Thymeleaf 也是 Spring Boot 官方推荐使用的模版引擎。同时 Spring Boot 也为 Thymeleaf 提供了完整的自动化配置解决方案。
8.1 处理模版
Thymeleaf 能处理以下 6 种类型的模版,我们称之为模版模式(Template Mode):
• HTML
• XML
• TEXT
• JAVASCRIPT
• CSS
• RAW
其中包含有两种标记模板模式(HTML和XML),三种文本模板模式(TEXT、JAVASCRIPT和CSS)和一个无操作模板模式(RAW)。
8.2 语法规则
8.3 注释
(1) 标准 HTML/XML 注释 可以在 Thymeleaf 模板中的任何地⽅使⽤,这些注释中的所有内容都不会被 Thymeleaf 处理,并将逐字复制到结果中。
(2) Thymeleaf 解析器级注释块被解析时,Thymeleaf 直接将它们从模板中删除。也就说是通过 ThymeLeaf 渲染时,在浏览器 F12 也将无法再看到被注释内容。
格式1:
格式2:
1)格式1 中 显然就是在 html 注释的基础上加了 /* 与 */ ,这意味着使用 Thymeleaf 渲染访问时,浏览器 F12 无法看到被注释的内容,但是如果不通过 Thyneleaf 渲染,而是以原型访问时,浏览器 F12 可以看到被注释的内容。
2)格式2 中,使用 Thymeleaf 渲染访问时,浏览器不显示被注释的内容(因为被删除了),F12 也无法看到被注释的内容,但是如果不通过 Thyneleaf 渲染,而是以原型访问时,浏览器会直接显然被注释的内容。
8.4 表达式
Simple expressions:(表达式语法)
Variable Expressions: ${…}:获取变量值;OGNL;
1)获取对象的属性、调用方法
2)使用内置的基本对象:
#ctx : the context object.
#vars: the context variables.
#locale : the context locale.
#request : (only in Web Contexts) the HttpServletRequest object. ${request.xxx}
#response : (only in Web Contexts) the HttpServletResponse object.
#session : (only in Web Contexts) the HttpSession object. ${session.xxx}
#servletContext : (only in Web Contexts) the ServletContext object.
3)内置的一些工具对象:
#execInfo : information about the template being processed.
#messages : methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{…} syntax.
#uris : methods for escaping parts of URLs/URIs
#conversions : methods for executing the configured conversion service (if any).
#dates : methods for java.util.Date objects: formatting, component extraction, etc.
#calendars : analogous to #dates , but for java.util.Calendar objects.
#numbers : methods for formatting numeric objects.
#strings : methods for String objects: contains, startsWith, prepending/appending, etc.
#objects : methods for objects in general.
#bools : methods for boolean evaluation.
#arrays : methods for arrays.
#lists : methods for lists.
#sets : methods for sets.
#maps : methods for maps.
#aggregates : methods for creating aggregates on arrays or collections.
#ids : methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).
Selection Variable Expressions: *{…}:
选择表达式:和 在 功 能 上 是 一 样 ; 补 充 : 配 合 t h : o b j e c t = " { } 在功能上是一样; 补充:配合 th:object=" 在功能上是一样;补充:配合th:object="{session.user}:
Name: Sebastian.
Surname: Pepper.
Nationality: Saturn.
Message Expressions: #{…}:
获取国际化内容
Link URL Expressions: @{…}:
定义URL;
@{/order/process(execId=${execId},execType=‘FAST’)}
注意这里( )内的语法为 url 参数。
Fragment Expressions: ~{…}:
片段引用表达式
8.5 常用的语法
(1)常用表达式
a) ${…}:变量表达式。
b) *{…}:选择表达式。
c) #{…}:消息文字表达式。
d) @{…}:链接 url 表达式。
e) #maps:工具对象表达式。
(2)常用标签
a) th:action:定义后台控制器路径。
b) th:each:循环语句。
c) th:field:表单字段绑定。
d) th:href:定义超链接。
e) th:id:div 标签中的 ID 声明,类似 HTML 标签中的id属性。
f) th:if:条件判断语句。
g) th:include:布局标签,替换内容到引入文件。
h) th:fragment:布局标签,定义一个代码片段,方便其他地方引用。
i) th:object:替换对象。
j) th:src:图片类地址引入。
k) th:text:显示文本。
l) th:value:属性赋值。
(3)常用函数
a) #dates:日期函数。
b) #lists:列表函数。
c) #arrays:数组函数。
d) #strings:字符串函数。
e) #numbers:数字函数。
f) #calendars:日历函数。
g) #objects:对象函数。
h) #bools:逻辑函数。
8.6 添加 thymeleaf依赖
org.springframework.boot spring-boot-starter-thymeleaf8.7 修改 application.yml配置
spring:
profiles:
active: production
thymeleaf:
mode: HTML
cache: true
prefix: classpath:/templates/
check-template-location: true
suffix: .html
encoding: utf-8
servlet:
content-type: text/html
8.8 几种常用的使用方法
1、赋值、字符串拼接
description
简洁的写法
2、条件判断 th:if / th:unless
Thymeleaf中使用th:if和th:unless属性进行条件判断
Login
3、for 循环 th:each
iterStat称作状态变量,属性有:
• index:当前迭代对象的 index(从0开始计算)
• count: 当前迭代对象的 index(从1开始计算)
• size:被迭代对象的大小
• current:当前迭代变量
• even/odd:布尔值,当前循环是否是偶数/奇数(从0开始计算)
• first:布尔值,当前循环是否是第一个
• last:布尔值,当前循环是否是最后一个
4、URL: @{ }
URL 在 Web 应用模板中占据着十分重要的地位,需要特别注意的是 Thymeleaf 对于 URL 的处理是通过语法 @{…} 来处理的。
如果需要 Thymeleaf 对 URL 进行渲染,那么务必使用 th:href,th:src 等属性
t y p e , x x = {type},xx= type,xx={xx}
view
设置背景
5、选择表达式th:objectThe name of the first person is Julius Caesar.
7、分支结构th:switch
User is an administrator
User is a manager
User is some other thing
默认属性default可以用*表示:不建议使用。
8、多属性th:attr
使用thymeleafa时候如果要hidden某些数据,我们可以使用th:attr 将数据作为html标签的一个属性存起来
如果是有多个属性要hidden,只需要用逗号隔开就可以了:
8.9模板(template fragments)
定义和引用模板
日常开发中,我们经常会将导航栏,页尾,菜单等部分提取成模板供其它页面使用。
在Thymeleaf 中,我们可以使用th:fragment属性来定义一个模板。
我们可以新建一个简单的页尾模板,如:/resources/templates/footer.html,内容如下:
其中th:include中的参数格式为templatename::[domselector],
其中templatename是模板名(如footer),domselector是可选的dom选择器。如果只写templatename,不写domselector,则会加载整个模板。
当然,这里我们也可以写表达式:
我们通过th:include 和 th:replace来加载模板
返回的HTML如下:
...
此外,定义模板的时候签名也可以不包括参数:
这种方式调用模板。这其实和
th:assert 断言
我们可以通过th:assert来方便的验证模板参数
NAME | PRICE | IN STOCK | COMMENTS |
---|---|---|---|
Onions | 2.41 | yes | 2 comment/s view |
Blue Lettuce | 9.55 | no | 0 comment/s |
Mild Cinnamon | 1.99 | yes | 3 comment/sview |
http://localhost:8080/actuator/configprops
ID 路径 请求方式 说明
1 /autoconfig GET 自动配置报告,记录哪些自动配置条件是否通过
2 /configprops GET 描述配置属性(包括默认值)如何注入的
3 /beans GET 描述上下文所有bean,以及它们之间的关系
4 /dump GET 获取线程活动快照
5 /env GET 获取全部环境属性
6 /env/{name} GET 获取特点环境属性
7 /health GET (默认开启)应用程序健康指标,由HealthIndicator的实现类提供
8 /info GET (默认开启)获取应用程序定制信息,这些信息有info打头的属性提供
9 /mappings GET 描述全部URL路径,及它们和控制器(包括Actuator端点)的映射关系
10 /metrics GET 报告各种应用程序度量信息,比如内存用量和http请求计算
11 /metrics/{name} GET 报告指定名称的应用程序度量值
12 /shutdown GET 关闭应用程序,要求endpoints.shutdown.enabled设值为true
13 /trace GET 提供基本的HTTP请求跟踪信息,时间戳,HTTP头等
例如请求在https://www.lanqiao.cn域名下请求失败的信息如下:
在前后端分离开发的项目中解决跨域请求是常见的问题,在使springboot处理跨域请求时变得非常简单。
解决方案1
这种方案使整个应用都支持跨域。
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
//registry.addMapping("/open/**") // 部分接口跨域
registry.addMapping("/**") // 整个应用都支持跨域
.allowedOrigins("*") //允许跨域的域名,可以用*表示允许任何域名使用
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true) //带上cookie信息
.maxAge(3600)
.allowedHeaders("*"); //允许任何请求头
}
}
解决方案2
这种方案需每个支持跨域的控制器都添加 @CrossOrigin 注解。
@RestController
@CrossOrigin
public class CrossController {
@RequestMapping("/docross")
public Map doCross() {
Map map = new HashMap<>();
map.put("name", "james");
map.put("age", "22");
return map;
}
}
直接在webstorm中运行 Vue项目时,在 Vue组件中直接请求后端 API 接口,而不需要在nginx 中配置反向代理了。但其缺点也很明显,前端 UI 组件只能请求某一特定的后端 API服务器,不能实现多服务器的负载均衡、高可用、高并发。
import axios from ‘axios’
axios.get(‘http://localhost:8081/docross’) //这里 springboot 运行的端口:8081
.then( res => {
// this.user = res.data
console.log( res.data )
})
.catch( err => {
console.log( err )
})
解决方案3 ( Servlet过滤器实现)
过实现Fiter接口在请求中添加一些Header来解决跨域的问题
@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Credentials", "true");
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {
response.getWriter().println("ok");
return;
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
热加载与热布暑
打开IDEA设置勾选自动编译选项
按两次Shift键在打开的窗口中选择“Action”,输入registry(没有Help那项)打开,勾选compiler.automake.allow.when.app.ruanning这个选项即可。