# 热部署

# 启动热部署

# 开启开发者工具

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

# 激活热部署

# 关于热部署

# 重启(Restart)

自定义开发代码,包括类,页面,配置文件等,加载位置 restart 类加载器

# 重载(ReLoad)

jar 包,加载位置 base 类加载器

# 自动启动热部署

# 热部署的范围控制

# 默认不触发重启的目录列表

  1. /META-INF/maven
  2. /META-INF/resources
  3. /resources
  4. /static
  5. /public
  6. /templates

# 自定义参数排除项

spring:
	devtools:
		restart: 
			exclude: public/**,static/**

# 关闭热部署

# 配置文件中配置

spring:
	devtools:
		restart: 
			enabled: false
			# 关闭热部署

# 设置优先级属性禁用热部署

public static void main(String[] args) {
        // 关闭热部署
        System.setProperty("spring.devtools.restart.enabled","false");
        SpringApplication.run(Springboot08SsmpApplication.class, args);
}

# 配置高级

# 使用 @ConfigurationProperties 第三方绑定属性

@Bean
@Configruation(prefix = "datasource")
public DruidDataSource dataSource() {
    DruidDatasource ds = new DruidDataSource();
    return ds;
}
datasource:
    driverClassName: com.mysql.jdbc.Driver

# @EnableConfigurationProperties

@EnableConfigurationProperties 注解可以使用 @ConfigurationProperties 注解对应的类加入 Spring 容器

@SpringBootApplication
@EnableConfigurationProperties({ServerConfig.class})
public class DemoApplication {
}
//@Component  防止定义两个 Bean 对象
@Data
@ConfigurationProperties(prefix = "servers")
public class ServerConfig {
}

注意:@EnableConfigurationProperties 与 @Component 不能同时使用(防止定义两个 Bean 对象)

# 宽松绑定

# @ConfigurationProperties 绑定属性支持属性名宽松绑定

public class ServerConfig {
    private String ipAddress;
    private int port;
    private long timeout;
}
servers:
#  配置文件中支持以下四种格式
#  IP_ADDRESS: 192.168.0.1 常量
#  ip_address: 192.168.0.1 unline
#  ip-adddress: 192.168.0.1 烤肉串模式
  ipAddress: 192.168.0.1  # 驼峰
  port: 2345
  timeout: -1
@Bean
// 绑定前缀名命名规范:仅能使用纯小写字母,数字,下划线作为合法的字符
@ConfigurationProperties(prefix = "datasource")
public DruidDataSource dataSource() {
     DruidDataSource ds = new DruidDataSource();
     return ds;
}

# 常用计量单位

# SpringBoot 支持 jdk8 提供的时间与计量单位

@Component
@Data
@ConfigurationProperties(prefix = "servers")
public class ServerConfig {
    private String ipAddress;
    private int port;
    private long timeout;
    @DurationUnit(ChronoUnit.HOURS)
    private Duration serverTimeout;
    @DataSizeUnit(DataUnit.MeGABYTES)
    private DataSize dataSize;
}

# Bean 数据校验

# 开启 Bean 数据校验

<!--JSR303 规范坐标 -->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>
<!--Hibernate 校验坐标 -->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>

# 对 Bean 开启校验功能

@Component
@Data
@ConfigurationProperties(prefix = "servers")
@Validated    // 开启校验功能
public class ServerConfig {
}

# 设置校验规则

@Component
@Data
@ConfigurationProperties(prefix = "servers")
@Validated    // 开启校验功能
public class ServerConfig {
    @Max(value = 400,message = "最大值不超过400")
    private int port;
}

# 进制数据转换规则

# yml 语法规则

boolean: TRUE                            # TRUE,true,True,FALSE,false,False均可
float: 3.14                              # 6.852315e+5 支持科学计数法
int: 123                                 # 支持二进制,八进制,十六进制
null: ~                                  # 使用~代表null
string: HelloWorld                       # 字符串可以直接书写
string2: "HelloWorld"                    # 可以使用双引号包裹特殊字符
date: 2018-02-17                         # 日期必须使用yyyy-MM-dd格式
datetime: 2018-02-17T15:02:31+08:00      # 时间和日期之间使用T连接,最后使用+代表时区

** 注意:** 如果写 password: 0314 会把 0314 解读为八进制,解决办法 "0314"

# 测试

# 加载测试专用属性

# 通过 properties 参数设置测试专用属性

@SpringBootTest(properties = {"test.prop=testValue01"})
public class PropertiesAndArgsTest {
    @Value("${test.prop}")
    private String msg;
    @Test
    void testProperties(){
        System.out.println(msg);    
    }
}

** 优势:** 比多环境开发中的测试环境影响范围小,仅对当前测试类有效

# 通过 args 参数设置测试专用属性

@SpringBootTest(args = {"--test.prop=testValue02"})
public class PropertiesAndArgsTest {
    @Value("${test.prop}")
    private String msg;
    @Test
    void testProperties(){
        System.out.println(msg);    
    }
}

# 加载测试专用配置

# 使用 @import 注解加载当前测试类专用配置

@SpringBootTest
@Import({MsgConfig.class})
public class ConfigurationTest() {
    @Autowired
    private String msg;
    @Test
    void testConfiguration(){
        System.out.println(msg);
    }
}

# web 开发模拟测试

# 模拟端口

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class WebTest {
    @Test
    void test(){
    }
}

# 模拟端口的类型

# 启动随机端口进行模拟
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
# 启动默认端口进行模拟
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
# 不启动端口进行模拟
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
# 启动端口进行模拟 只关注测试本身,不关注 service 层以及 dao 层
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)

# 虚拟测试请求

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
// 开启虚拟 MVC 调用
@AutoConfigureMockMvc
public class WebTest {
    @Test
    // 注入 mvc 虚拟对象
    void testWeb(@Autowired MockMvc mvc) throws Exception {
        // 创建虚拟请求,当前访问 /books
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
        // 执行请求
        mvc.perform(builder);
    }
}

# 虚拟请求状态匹配

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
// 开启虚拟 MVC 调用
@AutoConfigureMockMvc
public class WebTest {
    @Test
    void testStatus(@Autowired MockMvc mvc) throws Exception {
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
        ResultActions action = mvc.perform(builder);
        // 定义本次调用的预期值
        // 设置预期值,与真实值比较,成功测试通过,失败测试失败
        StatusResultMatchers status = MockMvcResultMatchers.status();
        // 预计本次调用时成功的状态 200
        ResultMatcher ok = status.isOk();
        // 添加预计值到本次调用中进行匹配
        action.andExpect(ok);
    }
}

# 匹配响应体

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
// 开启虚拟 MVC 调用
@AutoConfigureMockMvc
public class WebTest {
    @Test
    void testBody(@Autowired MockMvc mvc) throws Exception {
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
        ResultActions action = mvc.perform(builder);
        // 设置预期值,与真实值比较,成功测试通过,失败测试失败
        // 定义本次调用的预期值
        ContentResultMatchers content = MockMvcResultMatchers.content();
        ResultMatcher resule = content.string("springboot");
        // 添加预计值到本次调用中进行匹配
        action.andExpect(resule);
    }
}

# 匹配响应体

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
// 开启虚拟 MVC 调用
@AutoConfigureMockMvc
public class WebTest {
    @Test
    void testJson(@Autowired MockMvc mvc) throws Exception {
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
        ResultActions action = mvc.perform(builder);
        // 设置预期值,与真实值比较,成功测试通过,失败测试失败
        // 定义本次调用的预期值
        ContentResultMatchers content = MockMvcResultMatchers.content();
        ResultMatcher result = content.json("{\"id\":1,\"name\":\"Java\",\"type\":\"Java\",\"description\":\"Java学习\"}");
        // 添加预计值到本次调用中进行匹配
        action.andExpect(result);
    }
}

# 完整测试方法

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
// 开启虚拟 MVC 调用
@AutoConfigureMockMvc
public class WebTest {
    @Test
    void testContentType(@Autowired MockMvc mvc) throws Exception {
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
        ResultActions action = mvc.perform(builder);
        // 测试请求状态是否成功通过
        StatusResultMatchers status = MockMvcResultMatchers.status();
        ResultMatcher ok = status.isOk();
        action.andExpect(ok);
        // 测试 json 数据是否正确
        ContentResultMatchers content = MockMvcResultMatchers.content();
        ResultMatcher result = content.json("{\"id\":1,\"name\":\"Java\",\"type\":\"Java\",\"description\":\"Java学习\"}");
        action.andExpect(result);
        // 测试虚拟请求头是否正确
        HeaderResultMatchers header = MockMvcResultMatchers.header();
        ResultMatcher contentType = header.string("Content-type","application/json");
        action.andExpect(contentType);
    }
}

# 业务层测试

# 数据层测试事务回滚

为了测试添加事务,SpringBoot 会对测试用例对应的事务提交操作进行回滚

@SpringBootTest
@Transactional
public class ServiceTest {
    @Autowired
    private BookService bookService;
}

如果想测试用例中提交事务,可以通过 @RollBack 注解配置

@SpringBootTest
@Transactional
@Rollback(value = false)
public class ServiceTest {
}

# 测试用例设置随机数据

测试用例数据通常采用随机值进行测试,使用 SpringBoot 提供的随机数进行赋值

testcase:
  book:
    id: ${random.int}            # 表示随机整数
    id2: ${random.int(10)}       # 10 以内随机数
    type: ${random.int(5,10)}    # 5 到 10 随机数
    name: 包子${random.value}    # 随机字符串
    uuid: ${random.uuid}         # 随机 uuid
    publishTime: ${random.long}  # 随机整数 long 类型

# 数据层解决方案

# 内置数据源

  1. HiKariCP
  2. Tomcat 提供 DataSource
  3. .Commons DBCP

# 内置持久化解决方案 ——jdbcTemplate

# 用法

@Test
void testJdbcTemplate() {
    String sql = "select * from tal_book where id = 1";
    RowMapper<Book> rm = new RowMapper<Book>() {
        @Override
        public Book mapRow(ResultSet rs, int rowNum) throws SQLException {
            Book temp = new Book();
            temp.setId(rs.getInt("id"));
            temp.setName(rs.getString("name"));
            temp.setType(rs.getString("type"));
            temp.setDescription( rs.getString("description"));
            return temp;
        }
    };
    List<Book> list = jdbcTemplate.query(sql, rm);
    System.out.println(list);
}

# 导入依赖 jdbc

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

# 内嵌数据库

# 内嵌数据库(H2)

# 设置当前项目为 web 工程,配置 H2 管理控制台参数

server:
  port: 80
spring:
  h2:
    console:
      path: /h2
      enabled: true

访问用户名 sa,默认密码 123456

# 设置访问权限

server:
  port: 80
spring:
  h2:
    console:
      path: /h2
      enabled: true
  datasource:
    url: jdbc:h2:~/test
    driver-class-name: org.h2.Driver
    username: sa
    password: 123456

# Redis

# 概念

Redis 是一款 key-value 存储结构的内存级 NoSQL 数据库

  1. 支持多种数据库存储格式
  2. 支持持久化
  3. 支持集群

# Redis 下载

官网:https://github.com/tporadowski/redis/releases

# Redis 安装启动

# 服务端启动

redis-server.exe redis.windows.conf

# 客户端启动命令

redis-cli.exe

# SpringBoot 整合 Redis

# 导入 SpringBoot 整合 Redis 坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

# 配置 Redis

spring:
  redis:
    host: localhost
    port: 6379

# RedisTemplate(操作接口)

@SpringBootTest
class Springboot15RedisApplicationTests {
    // 注入 RedisTemplate
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void set() {
        ValueOperations ops = redisTemplate.opsForValue();
        ops.set("age",41);
    }
    @Test
    void get() {
        ValueOperations ops = redisTemplate.opsForValue();
        Object age = ops.get("age");
        System.out.println(age);
    }
}

# SpringBoot 读写 Redis 客户端

StringRedisTemplate 以字符串作为 key 和 value,与 Redis 客户端操作等效

@SpringBootTest
public class StringRedisTemplateTest {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Test
    void get() {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        String name = ops.get("name");
        System.out.println(name);
    }
}

# Redis 客户端实现技术切换(jedis)

spring:
  redis:
    host: localhost
    port: 6379
    client-type: jedis
    jedis:
      pool:
        max-active: 16
    lettuce:
      pool:
        max-active: 16

# Mongodb

# 概念

MongdDB 是一个开源,高性能,无模式文档型数据库。NoSQL 数据库产品中的一种,是最像关系数据库的非关系型数据库

# 下载

官网:https://www.mongodb.com/try/download

# Mongodb 启动

  1. 服务器端启动: mongod --dapath=..\data\db
  2. 客户端启动: mongo --host=127.0.0.1 --port=27017

# Mongodb(CRUD)

# 新增

db.集合名称.insert/save/insertOne

# 修改

db.集合名称.update(条件,{操作种类:{文档}})

# 删除

db.集合名称.remove(条件)

# 查询

db.集合.find({})

# SpringBoot 整合 Mongodb

# 导入驱动

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

# 配置客户端

spring:
  data:
    mongodb:
      uri: mongodb://localhost/itheima

# 客户端读写 Mongodb

@SpringBootTest
class Springboot16MongodbApplicationTests {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Test
    void contextLoads() {
        Book book = new Book();
        book.setId(2);
        book.setName("springboot111");
        book.setType("Java11");
        book.setDescription("study");
        mongoTemplate.save(book);
    }
    @Test
    void find() {
        List<Book> bookList = mongoTemplate.findAll(Book.class);
        System.out.println(bookList);
    }
}

# Elasticsearch(ES)

# 概念

Elasticsearch 是一个分布式全文搜索引擎(倒排索引 有信息查 id 再查数据)

# 下载

官网:https://www.elastic.co/cn/download/elasticsearch

# 安装与启动

elasticsearch.bat

# ES 索引操作

# 创建

PUT http://localhost:9200/books

# 2)查询

GET http://localhost:9200/books

# 3)删除

DELETE http://localhost:9200/books

# 4)索引创建规则

{
    "mappings": {
            "properties": {
                "all": {
                    "type": "text",
                    "analyzer": "ik_max_word"
                },
                "description": {
                    "type": "text",
                    "copy_to": [
                        "all"
                    ],
                    "analyzer": "ik_max_word"
                },
                "id": {
                    "type": "keyword"
                },
                "name": {
                    "type": "text",
                    "copy_to": [
                        "all"
                    ],
                    "analyzer": "ik_max_word"
                },
                "type": {
                    "type": "keyword"
                }
            }
     }
}

# 文档操作

创建文档

POST    http://localhost:9200/books/_doc        # 使用系统生成id
POST    http://localhost:9200/books/_create/1        # 使用指定id
POST    http://localhost:9200/books/_doc/1        # 使用指定id,不存在创建,存在更新
{
    "name":"springboot"
    "type":"springboot"
    "description":"springboot"
}

查询文档

GET    http://localhost:9200/books/_doc/1        # 查询单个文档
GET    http://localhost:9200/books/_search        # 查询全部文档

条件查询

GET    http://localhost:9200/books/_search?q=name:springboot

删除文档

DELETE    http://localhost:9200/books/_doc/1

修改(全部)

PUT    http://localhost:9200/books/_doc/1
{
    "name":"springboot"
    "type":"springboot"
    "description":"springboot"
}

修改(部分)

POST    http://localhost:9200/books/_update/1
{
    "doc":{
        "name":"springboot"    
    }
}

# SpringBoot 整合 ES

# 导入依赖

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>

# 配置

spring:
    elesticsearch:
        rest:
            uris:http://localhost:9200

# 客户端

@SpringBootTest
class Springboot17EsApplicationTests {
    @BeforeEach
    void setUp() {
        HttpHost host = HttpHost.create("http://localhost:9200");
        RestClientBuilder builder = RestClient.builder(host);
        client = new RestHighLevelClient(builder);
    }
    @AfterEach
    void tearDown() throws IOException {
        client.close();
    }
    private RestHighLevelClient client;
    @Test
    void testCreateIndex() throws IOException {
        CreateIndexRequest request = new CreateIndexRequest("books");
        client.indices().create(request, RequestOptions.DEFAULT);
    }
}

# 添加文档(单个)

@Test
void testCreateDoc() throws IOException {
    Book book = bookDao.selectById(1);
    IndexRequest request = new IndexRequest("books").id(book.getId().toString());
    String json = JSON.toJSONString(book);
    request.source(json, XContentType.JSON);
    client.index(request,RequestOptions.DEFAULT);
}

# 添加文档(批量添加)

@Test
void testCreateDocAll() throws IOException {
    List<Book> bookList = bookDao.selectList(null);
    BulkRequest bulk = new BulkRequest();
    for (Book book : bookList) {
        IndexRequest request = new IndexRequest("books").id(book.getId().toString());
        String json = JSON.toJSONString(book);
        request.source(json,XContentType.JSON);
        bulk.add(request);
    }
    client.bulk(bulk,RequestOptions.DEFAULT);
}

# 查询文档(单个)

@Test
void testGet() throws IOException {
    GetRequest request = new GetRequest("books","1");
    GetResponse response = client.get(request, RequestOptions.DEFAULT);
    String json = response.getSourceAsString();
    System.out.println(json);
}

# 查询文档(条件)

@Test
void testSearch() throws IOException {
    SearchRequest request = new SearchRequest("books");
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.termQuery("name","java"));
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    SearchHits hits = response.getHits();
    for (SearchHit hit : hits) {
        String json = hit.getSourceAsString();
        Book book = JSON.parseObject(json, Book.class);
        System.out.println(book);
    }
}

# 整合第三方技术

# 缓存

# 概述

  1. 缓存时一种介于数据永久存储与数据应用之间得数据临时存储介质
  2. 使用缓存可以有效减少低速数据读取过程中的次数,提高系统性能
  3. 缓存不仅可以使用提高永久性存储介质的数据读取效率,还可以提供临时的数据存储空间

# SpringBoot 提供缓存技术

# 导入缓存技术 starter

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

# 启动缓存 @EnableCaching

@SpringBootApplication
// 启动缓存
@EnableCaching
public class Springboot18CacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot18CacheApplication.class, args);
    }
}

# 设置当前操作结果数据进入缓存 @Cacheable

@Override
// 第一个值为空间 第二个值根据 key 缓存
@Cacheable(value = "cacheSpace",key = "#id")
public Book getById(Integer id) {
    return bookDao.selectById(id);
}

# 整合 Ehcache

# 导入坐标

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

# 缓存设定为使用 Ehcache

spring:
    cache:
        type: ehcache
        ehcache:
            config: ehcache.xml

# ehcache 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <!--
       diskStore:为缓存路径,ehcache 分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
       user.home – 用户主目录
       user.dir  – 用户当前工作目录
       java.io.tmpdir – 默认临时文件路径
     -->
    <diskStore path="java.io.tmpdir/Tmp_EhCache"/>
    <!--
       defaultCache:默认缓存策略,当 ehcache 找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
     -->
    <!--
      name: 缓存名称。
      maxElementsInMemory: 缓存最大数目
      maxElementsOnDisk:硬盘最大缓存个数。
      eternal: 对象是否永久有效,一但设置了,timeout 将不起作用。
      overflowToDisk: 是否保存到磁盘,当系统当机时
      timeToIdleSeconds: 设置对象在失效前的允许闲置时间(单位:秒)。仅当 eternal=false 对象不是永久有效时使用,可选属性,默认值是 0,也就是可闲置时间无穷大。
      timeToLiveSeconds: 设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当 eternal=false 对象不是永久有效时使用,默认是 0.,也就是对象存活时间无穷大。
      diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
      diskSpoolBufferSizeMB:这个参数设置 DiskStore(磁盘缓存)的缓存区大小。默认是 30MB。每个 Cache 都应该有自己的一个缓冲区。
      diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是 120 秒。
      memoryStoreEvictionPolicy:当达到 maxElementsInMemory 限制时,Ehcache 将会根据指定的策略去清理内存。默认策略是 LRU(最近最少使用)。你可以设置为 FIFO(先进先出)或是 LFU(较少使用)。
      clearOnFlush:内存数量最大时是否清除。
      memoryStoreEvictionPolicy: 可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
      FIFO,first in first out,这个是大家最熟的,先进先出。
      LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个 hit 属性,hit 值最小的将会被清出缓存。
      LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
   -->
    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>
    <cache
            name="smsCode"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="10"
            timeToLiveSeconds="10"
            memoryStoreEvictionPolicy="LRU"/>
</ehcache>

# 数据淘汰策略

  1. LRU:淘汰距离上次使用时间长的
  2. LFU:淘汰最近使用次数少的

# Redis 整合

# 导入 Redis 坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

# 配置 Redis 服务器

spring:
    redis:
        host: localhost
        port: 6379
    cache:
        type: redis

# jetCache

# 加入坐标

<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>2.6.2</version>
</dependency>

# 配置

jetcache:
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson
  remote:
    default:
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50
    sms:
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50

# 开启 jetcache 注解支持

@SpringBootApplication
//jetcache 启动缓存主开关
@EnableCreateCacheAnnotation
public class Springboot19JetcacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot19JetcacheApplication.class, args);
    }
}

# 声明缓存对象

@Service
public class SMSCodeServiceImpl implements SMSCodeService {
//    remote
//    @CreateCache(area = "sms",name = "jetCache",expire = 3600,timeUnit = TimeUnit.SECONDS)
    @CreateCache(name = "jetCache",expire = 3600,timeUnit = TimeUnit.SECONDS,cacheType = CacheType.LOCAL)
    private Cache<String,String> jetCache;
    @Override
    public String sendCodeToSMS(String tele) {
        String code = codeUtils.generator(tele);
        jetCache.put(tele,code);
        return code;
    }
    @Override
    public boolean checkCode(SMSCode smsCode) {
        String code = jetCache.get(smsCode.getTele());
        return smsCode.getCode().equals(code);
    }
}

# 声明方法缓存,启动注解

@SpringBootApplication
//jetcache 启动缓存主开关
@EnableCreateCacheAnnotation
@EnableMethodCache(basePackages = "com.baozi")
public class Springboot19JetcacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot19JetcacheApplication.class, args);
    }
}

# 使用注解操作缓存

@Service
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;
    @Override
    @Cached(name = "book",key = "#id",expire = 1000)
//    @CacheRefresh(refresh = 5)
    public Book getById(Integer id) {
        return bookDao.selectById(id);
    }
}

# j2cache

# 概述

j2cache 是一个缓存整合框架,可以提供缓存整合方案,使用各种缓存搭配使用,自身不提供缓存功能

# 任务

# SpringBoot 整合 Quartz

# 相关概念

  1. 工作(Job):用于定义具体执行的工作
  2. 工作明细(JobDetail):用于描述定时工作相关的信息
  3. 触发器(Trigger):用于描述触发工作的规则,通常使用 cron 表达式定义调度规则
  4. 调度器(Scheduler):描述了工作明细与触发器的对应关系

# 导入整合 quartz 坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

# 定义具体执行的任务

public class MyQuartz extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        System.out.println("quartz task running ...");
    }
}

# 定义工作明细与触发器,并绑定对应关系

@Configuration
public class QuartzConfig {
    @Bean
    public JobDetail printJobDetaile(){
        return JobBuilder.newJob(MyQuartz.class).storeDurably().build();
    }
    @Bean
    public Trigger printJobTrigger(){
        ScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/3 * * * * ?");
        return TriggerBuilder.newTrigger().forJob(printJobDetaile()).withSchedule(scheduleBuilder).build();
    }
}

# Spring Task

# 开启定时任务功能

@SpringBootApplication
// 开启定时任务功能
@EnableScheduling
public class Springboot20TaskApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot20TaskApplication.class, args);
    }
}

# 设置定时任务,并设定执行周期

@Component
public class MyBean {
    @Scheduled(cron = "0/3 * * * * ?")
    public void print(){
        System.out.println("spring task running...");
    }
}

# 配置文件

spring:
  task:
    execution:
      thread-name-prefix: spring_task_

# Mail 邮件

# SpringBoot 整合 JavaMail

# 邮件协议

  1. SMTP:发送电子邮件传输协议
  2. POP3:用于接收电子邮件标准协议
  3. IMAP:互联网信息协议,是 POP3 的替代协议

# 导入坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

# 配置 JavaMail

spring:
  mail:
    username: 2072626886@qq.com
    password: bjh0314
    host: smtp.qq.com

# 消息

# ActiveMQ

# RabbitMQ

# RocketMQ

# Kafka

# 监控

# 监控意义

  1. 监控服务状态是否宕机
  2. 监控服务运行指标
  3. 监控日志
  4. 管理服务

# 可视化监控平台

# Admin 客户端

<properties>
    <java.version>1.8</java.version>
    <spring-boot-admin.version>2.7.4</spring-boot-admin.version>
</properties>
<dependencies>
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-dependencies</artifactId>
            <version>${spring-boot-admin.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.5.4</version>
</dependency>
spring:
  boot:
    admin:
      client:
        url: http://localhost:8080
server:
  port: 80
management:
  endpoint:
    health:
      show-details: always
  endpoints:
    web:
      exposure:
        include: "*"

# Admin 服务端

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-server</artifactId>
    <version>2.5.4</version>
</dependency>
server.port
// 设置启动 Spring-Admin
@SpringBootApplication
@EnableAdminServer
public class SpringBoot25ActuatorServerApplication {
    piblic static void main(String[] args){
        SpringApplication.run(Springboot25ActuatorServerApplication.class,args);    
    }
}

# 监控原理

  1. Actuator 提供了 SpringBoot 生产就绪功能,通过端点的配置与访问,获取端点信息
  2. 端点描述了一组监控信息,SpringBoot 提供了多个内置端点,也可以根据需要自定义端点信息
  3. 访问当前应用所有端点信息:/actuator
  4. 访问端点详细消息:/actuator/ 端点名称

# 自定义监控指标

# 为 info 端点添加自定义指标

@Component
public class infoConfig implements InfoContributor {
    @Override
    public void contribute(Info.Builder builder) {
        builder.withDetail("runTime",System.currentTimeMillis());
        Map infoMap = new HashMap();
        infoMap.put("buildeTine","2006");
        builder.withDetails(infoMap);
    }
}

# 自定义端点

@Component
@Endpoiont(id = "pay")
public class PayEndPoint {
    @ReadOperation
    public Object getPay(){
        Map payMap = new HashMap();
        payMap.put("1",103);    
        payMap.put("2",104);    
        payMap.put("3",105);    
        return payMap;
    }
}
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

Baozi 微信支付

微信支付

Baozi 支付宝

支付宝

Baozi 微信

微信