2021-01-03

学习小结

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

org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-devtools true 说明:Spring boot的项目必须要将parent设置为spring boot的parent,该parent包含了大量默认的配置,大大简化了我们的开发。

点开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

配置Tomcat编码

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 #页面不加载缓存,修改即时生效

开放所有的 Web endpoints

management:
endpoints:
web:
exposure:
include: *

输出 mybatis SQL日志

logging:
level:
root: INFO
com.lanqiao.springboot.tutorials.mapper: DEBUG

日志文件

path: /Users/jamesmac/projects/SpringBootProjects/springboot-tutorials

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即可

  1. springboot条件注解
    条件依赖注解有:

@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的依赖

org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.0

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的核心配置文件

jdbc_config datasource

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

Hikari will use the above plus the following to setup connection pooling

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

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 HikariCP

4.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依赖

net.sf.ehcache 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 可以用的一些元数据:

  1. springboot整合redis
    6.1.添加依赖
org.springframework.boot spring-boot-starter-data-redis

6.2.修改application.yml

Redis 数据库索引,默认有15个数据库:db0, db1, …

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成功

  1. springboot redis Session共享
    当同一个web application分布式布暑在多个应用服务器上运行时,在这种场景中才需要Session共享。分布式一致性 Session 的问题,主流解决方案有四种:

总结:
• 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-redis

7.2 修改application.yml
在application.properties属性文件中加入以下redis配置。

Redis 数据库索引(默认为0)

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);
}

}

  1. thymeleaf模板
    文档参考:https://waylau.gitbooks.io/thymeleaf-tutorial/content/

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:

you can see me only before Thymeleaf processes me!
you can see me only before Thymeleaf processes me!

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: ~{…}:
片段引用表达式


Literals(字面量)
Text literals: ‘one text’ , ‘Another one!’ ,…
Number literals: 0 , 34 , 3.0 , 12.3 ,…
Boolean literals: true , false
Null literal: null
Literal tokens: one , sometext , main ,…
Text operations:(文本操作)
String concatenation: +
Literal substitutions: |The name is ${name}|
Arithmetic operations:(数学运算)
Binary operators: + , - , * , / , %
Minus sign (unary operator): -
Boolean operations:(布尔运算)
Binary operators: and , or
Boolean negation (unary operator): ! , not
Comparisons and equality:(比较运算)
Comparators: > , < , >= , <= ( gt , lt , ge , le )
Equality operators: == , != ( eq , ne )
Conditional operators: 条件运算(三元运算符)
If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)
Special tokens:
No-Operation: _

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-thymeleaf

8.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

1 Mark Otto @mdo index

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:object
... ... ...
6、声明变量th:with

The name of the first person is Julius Caesar.

当th:with被处理,firstPer变量创建一个局部变量和变量添加到map自上下文,以便它是用于评估和其他上下文中声明的变量从开始,但只有包含< div >标记的范围内。
...

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标签的一个属性存起来

上海
其中的 cityId是我们要保存起来的数据,然后就可以在js里面使用了。 使用方式为: var cityId = $("#cityBtn").data("cityid");

如果是有多个属性要hidden,只需要用逗号隔开就可以了:

8.9模板(template fragments)
定义和引用模板
日常开发中,我们经常会将导航栏,页尾,菜单等部分提取成模板供其它页面使用。
在Thymeleaf 中,我们可以使用th:fragment属性来定义一个模板。
我们可以新建一个简单的页尾模板,如:/resources/templates/footer.html,内容如下:

© 2016 xxx
上面定义了一个叫做copyright的片段,接着我们可以使用th:include或者th:replace属性来使用它: ...

其中th:include中的参数格式为templatename::[domselector],
其中templatename是模板名(如footer),domselector是可选的dom选择器。如果只写templatename,不写domselector,则会加载整个模板。
当然,这里我们也可以写表达式:

模板片段可以被包含在任意th:*属性中,并且可以使用目标页面中的上下文变量。 不通过th:fragment引用模板 通过强大的dom选择器,我们可以在不添加任何Thymeleaf属性的情况下定义模板: ...
© xxxxxx
... 通过dom选择器来加载模板,如id为copy-section ...
th:include 和 th:replace区别 th:include 是加载模板的内容,而th:replace则会替换当前标签为模板中的标签 例如如下模板:
© 2016

我们通过th:include 和 th:replace来加载模板

返回的HTML如下:

© 2016
© 2016
模板参数配置 th:fragment定义模板的时候可以定义参数:

...

在 th:include 和 th:replace中我们可以这样传参:
...
..

此外,定义模板的时候签名也可以不包括参数:

,我们任然可以通过

...

这种方式调用模板。这其实和

起到一样的效果

th:assert 断言
我们可以通过th:assert来方便的验证模板参数

...
th:remove 删除代码 这时一个很常规的模板,但是,当我们直接在浏览器里面打开它(不(不使用Thymeleaf ),它实在不是一个很好的原型。因为它的表格中只有一行,而我们的原型需要更饱满的表格。 如果我们直接添加了多行,原型是没有问题了,但通过Thymeleaf输出的HTML又包含了这些事例行。 这时通过th:remove属性,可以帮我们解决这个两难的处境,
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
其中th:remove的参数有如下几种: • all 删除当前标签和其内容和子标签 • body 不删除当前标签,但是删除其内容和子标签 • tag 删除当前标签,但不删除子标签 • all-but-first 删除除第一个子标签外的其他子标签 • none 啥也不干 9. Spring Boot Actuator端点服务 在Spring Boot的众多Starter POMs中有一个特殊的模块,它不同于其他模块那样大多用于开发业务功能或是连接一些其他外部资源。它完全是一个用于暴露自身信息的模块,所以很明显,它的主要作用是用于监控与管理,它就是:spring-boot-starter-actuator。 spring-boot-starter-actuator模块的实现对于实施微服务的中小团队来说,可以有效地减少监控系统在采集应用指标时的开发量。当然,它也并不是万能的,有时候我们也需要对其做一些简单的扩展来帮助我们实现自身系统个性化的监控需求。 Spring Actuator提供了13个REST端点:/autoconfig,/configprops,/beans,/dump,/env,/env/{name} ,/health,/info,/mappings,/metrics,/metrics/{name},/shutdown,/trace:

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头等

  1. springboot处理跨域请求
    CORS全称为Cross Origin Resource Sharing(跨域资源共享), 每一个页面需要返回一个名为Access-Control-Allow-Origin的http头来允许外域的站点访问,你可以仅仅暴露有限的资源和有限的外域站点访问。
    比如说,域名A ( http://domaina.example ) 的某 Web 应用程序中通过< img>标签引入了域名B( http://domainb.foo ) 站点的某图片资源(http://domainb.foo/image.jpg),域名A的那 Web 应用就会导致浏览器发起一个跨站 HTTP 请求。出于安全考虑,浏览器会限制脚本中发起的跨站请求。比如,使用 XMLHttpRequest 对象发起 HTTP 请求就必须遵守同源策略。跨域并非浏览器限制了发起跨站请求,而是跨站请求可以正常发起,但是返回结果被浏览器拦截了。最好的例子是CSRF跨站攻击原理。
    在当今的 Web 开发中,使用跨站 HTTP 请求加载各类资源(包括CSS、图片、JavaScript 脚本以及其它类资源),已经成为了一种普遍且流行的方式。
    可以理解为:如果一个请求需要允许跨域访问,则需要在http头中设置Access-Control-Allow-Origin来决定需要允许哪些站点来访问。如假设需要允许https://www.lanqiao.cn这个站点的请求跨域,则可以设置:
    Access-Control-Allow-Origin:https://www.lanqiao.cn

例如请求在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 {
}

}

  1. 热加载与热布暑

  2. 打开IDEA设置勾选自动编译选项

  3. 按两次Shift键在打开的窗口中选择“Action”,输入registry(没有Help那项)打开,勾选compiler.automake.allow.when.app.ruanning这个选项即可。

你可能感兴趣的:(2021-01-03)