SpringBoot教程:基本涵盖日常开发所有知识点

定义

spring boot 特性:
1、创建一个独立的spring 应用;
2、内嵌Tomcat
3、提供 starter 依赖
4、提供第三方配置
5、提供生产就绪的特性
6、配置更简单

第一个SpringBoot应用

http://c.biancheng.net/spring_boot/example.html

SpringBoot注解

@RestController

在Spring中@RestController的作用等同于@Controller + @ResponseBody。

@GetMapping/@PostMapping

在Spring中@GetMapping()/@PostMapping等同于传统的@RequestMapping来编写应该是@RequestMapping(value = “”}, method = RequestMethod.GET/POST)

SpringBoot启动器starter

Spring Boot 将日常企业应用研发中的各种场景都抽取出来,做成一个个的 starter(启动器),starter 中整合了该场景下各种可能用到的依赖,用户只需要在 Maven 中引入 starter 依赖,SpringBoot 就能自动扫描到要加载的信息并启动相应的默认配置。starter 提供了大量的自动配置,让用户摆脱了处理各种依赖和配置的困扰。所有这些 starter 都遵循着约定成俗的默认配置,并允许用户调整这些配置,即遵循“约定大于配置”的原则。
可以看看:http://c.biancheng.net/spring_boot/starter.html

SpringBoot的yml配置文件

http://c.biancheng.net/spring_boot/yaml.html

bootstrap.yml配置文件

bootstrap.yml和application.yml差不多
区别:

  • bootstrap.yml的优先级大于application.yml
  • spplication.yml主要用于项目的配置
  • bootstrap.yml用于:
    • SpringCloud
    • 加密解密
    • 固定参数

devtools自动重启实现

springboot通过devtools实现了可以不用重启,自动的执行了更新后的java代码,不包括配置信息。
实现步骤:

  1. 引入依赖:
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-devtools</artifactId>
   <optional>true</optional>
</dependency>
  1. 更改内容后,点击ctrl+F9

propertis配置

在springBoot里面,一般的常量配置都使用properties配置
使用步骤:

  1. 新建一个properties文件放在resource里面MyConfig.properties
user.userName=叼毛
user.age=20
  1. 在需要用的地方写入注解
package org.example.pojo;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties("user")
@PropertySource(value = "classpath:MyConfig.properties", encoding = "utf-8")
public class MyConfig {

    private String userName;
    private Integer age;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

3 引入依赖

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

SpringBoot-整合redis

配置步骤:

1.引入依赖

<!-- 引入 redis 依赖 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
	<!--<version>2.1.5.RELEASE</version>-->
</dependency>

<dependency>
	<groupId>com.squareup.okhttp3</groupId>
	<artifactId>okhttp</artifactId>
</dependency>

2.配置yml

spring:
  redis:
    database: 0
    host: 192.168.1.201
    port: 6379
    password: 123456

3.拷贝RedisOperator

4.controller测试redis中set和get

@Autowired
private RedisOperator redis;
    
@GetMapping("/redis")
public Object redis() {
    redis.set("name", "国产凌凌漆");
    return redis.get("name");
}

自定义启动logo

启动logo设置为图片

spring
	banner:
	    image:
	      location: classpath:img/cat.png
	      pixelmode: block

启动logo设置为文本

spring:
  banner:
    location: classpath:banner/banner.txt

web请求静态资源

springboot里面的静态资源默认路径是

classpath:/static
classpath:/public
classpath:/resources
classpath:/META-INF/resources

请求静态资源执行路径默认到static,可以直接访问,例如:http://localhost:8080/cat.png
可以通过yml设置更改默认路径
自定义请求路径配置

spring:
  mvc:
    static-path-pattern: /abc/**   # 示例:http://localhost:8080/abc/cat.png

自定义静态资源配置路径

spring.web.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/webapp/

Restfull接口请求风格

Restfull请求规范
实际指接口请求注解
强规范
get(查询) post(新增) put:修改 Delete:删
弱规范
get(查询) post(新增 ,修改 ,修改 )
示例:

package org.example.controller;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("stu")
public class RestfulController {

    @GetMapping("query")
    public String query(){
        return "query";
    }

    @PostMapping("create")
    public String create(){
        return "create";
    }

    @PutMapping("update")
    public String update(){
        return "update";
    }

    @DeleteMapping
    public String delete(){
        return "delete";
    }
}

接口参数常用注解

  • @PathVariable:用于获取路径里面的参数
  • @RequestParam:用于获取URL中的请求参数,如果参数变量名保持一致,该注解可以省略
  • @RequestBody:用于获取body里面的信息
  • @RequestHeader:用于获取请求头里面的数据
  • @CookieValue:用于获取cookie里面的信息
package org.example.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@Slf4j
@RestController
@RequestMapping("param")
public class ParamsController {

    @GetMapping("{stuId}/query")
    public String query(@PathVariable("stuId") String stuId,
                        @RequestParam String name,
                        @RequestParam String age){
        /**
         * @PathVariable:用于获取路径里面的参数,根据如上去使用
         * @RequestParam:用于获取URL中的请求参数,如果参数变量名保持一致,该注解可以省略
         */
        log.error("stuId:" + stuId);
        log.info("name:" + name);
        log.info("age:" + age);
        return "query";
    }

    @PostMapping("create")
    public String create(@RequestBody Map<String, Object> map,
                         @RequestHeader("token") String token,
                         @CookieValue("clientId") String clientId){

        /**
         * @RequestBody:用于获取body里面的信息
         * @RequestHeader:用于获取请求头里面的数据
         * @CookieValue:用于获取cookie里面的信息
         */
        log.info(map.toString());
        log.info(token);
        log.info(clientId);
        return "create";
    }
}

返回值

一般封装成一个对象

package com.imooc.utils;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 
 * @Title: JSONResult.java
 * @Package com.imooc.utils
 * @Description: 自定义响应数据结构
 * 				本类可提供给 H5/ios/安卓/公众号/小程序 使用
 * 				前端接受此类数据(json object)后,可自行根据业务去实现相关功能
 * 
 * 				200:表示成功
 * 				500:表示错误,错误信息在msg字段中
 * 				501:bean验证错误,不管多少个错误都以map形式返回
 * 				502:拦截器拦截到用户token出错
 * 				555:异常抛出信息
 * 				556: 用户qq校验异常
 * @Copyright: Copyright (c) 2020
 * @Company: www.imooc.com
 * @author liutianyu 
 * @version V1.0
 */
public class JSONResult {

    // 定义jackson对象
    private static final ObjectMapper MAPPER = new ObjectMapper();

    // 响应业务状态
    private Integer status;

    // 响应消息
    private String msg;

    // 响应中的数据
    private Object data;
    
    @JsonIgnore
    private String ok;	// 不使用

    public static JSONResult build(Integer status, String msg, Object data) {
        return new JSONResult(status, msg, data);
    }

    public static JSONResult build(Integer status, String msg, Object data, String ok) {
        return new JSONResult(status, msg, data, ok);
    }
    
    public static JSONResult ok(Object data) {
        return new JSONResult(data);
    }

    public static JSONResult ok() {
        return new JSONResult(null);
    }
    
    public static JSONResult errorMsg(String msg) {
        return new JSONResult(500, msg, null);
    }
    
    public static JSONResult errorMap(Object data) {
        return new JSONResult(501, "error", data);
    }
    
    public static JSONResult errorTokenMsg(String msg) {
        return new JSONResult(502, msg, null);
    }
    
    public static JSONResult errorException(String msg) {
        return new JSONResult(555, msg, null);
    }
    
    public static JSONResult errorUserQQ(String msg) {
        return new JSONResult(556, msg, null);
    }

    public JSONResult() {

    }

    public JSONResult(Integer status, String msg, Object data) {
        this.status = status;
        this.msg = msg;
        this.data = data;
    }
    
    public JSONResult(Integer status, String msg, Object data, String ok) {
        this.status = status;
        this.msg = msg;
        this.data = data;
        this.ok = ok;
    }

    public JSONResult(Object data) {
        this.status = 200;
        this.msg = "OK";
        this.data = data;
    }

    public Boolean isOK() {
        return this.status == 200;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

	public String getOk() {
		return ok;
	}

	public void setOk(String ok) {
		this.ok = ok;
	}

}

文件上传

文件上传大小限制

spring:
  servlet:
    multipart:
      max-file-size: 600KB  
      max-request-size: 2MB

在这里插入图片描述

在这里插入图片描述

自定义异常界面

自定义封装异常

package org.example.exception;

public class MyCustomException extends RuntimeException {
    public MyCustomException(String message) {
        super(message);
    }
}

拦截器

1.创建拦截器

package org.example.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.example.exception.GraceException;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
public class UserInfoInterceptor implements HandlerInterceptor {

    /**
     * @Description: 拦截请求,访问controller之前
     * @param: [request, response, handler]
     * @return: boolean
     * @author: liuyong
     * @date: 2022/8/3
     * @time: 16:05
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String userId = request.getHeader("userId");
        String userToken = request.getHeader("userToken");
        if(userId == null || userId.isEmpty() || userToken == null || userToken.isEmpty()) {
           log.error("用户校验不通过,信息不完整");
            GraceException.display("用户校验不通过,信息不完整");
           return false;
        }
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("interceptor...");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion");
    }
}

2.注册拦截器

package org.example.config;

import org.example.interceptor.UserInfoInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Bean
    public UserInfoInterceptor userInfoInterceptor() {
        return new UserInfoInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(userInfoInterceptor()).addPathPatterns("/upload");
    }
}

定时任务

package com.imooc.config;

import com.imooc.service.OrderService;
import com.imooc.utils.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class OrderJob {

    @Autowired
    private OrderService orderService;

    /**
     * 使用定时任务关闭超期未支付订单,会存在的弊端:
     * 1. 会有时间差,程序不严谨
     *      10:39下单,11:00检查不足1小时,12:00检查,超过1小时多余39分钟
     * 2. 不支持集群
     *      单机没毛病,使用集群后,就会有多个定时任务
     *      解决方案:只使用一台计算机节点,单独用来运行所有的定时任务
     * 3. 会对数据库全表搜索,及其影响数据库性能:select * from order where orderStatus = 10;
     * 定时任务,仅仅只适用于小型轻量级项目,传统项目
     *
     */

//    @Scheduled(cron = "0/3 * * * * ?")
    @Scheduled(cron = "0 0 0/1 * * ?")
    public void autoCloseOrder() {
        orderService.closeOrder();
        System.out.println("执行定时任务,当前时间为:"
                + DateUtil.getCurrentDateString(DateUtil.DATETIME_PATTERN));
    }
}

整合高性能HicarICP数据源

1.引入依赖pom

<!--        jdbc启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

<!--        mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

2.数据源配置

spring:
  datasource:                                              # 数据库的相关配置节点
    type: com.zaxxer.hikari.HikariDataSource               # 指定数据源类型
    driver-class-name: com.mysql.cj.jdbc.Driver            # mysql驱动
    url: jdbc:mysql://localhost:3306/springboot-demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true    # 数据库地址
    username: root                                         # 用户名
    password: root                                         # 密码
    hikari:
      connection-timeout: 30000                   # 等待连接池分配的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException,默认:30秒
      minimum-idle: 5                             # 最小连接数
      maximum-pool-size: 20                       # 最大连接数
      auto-commit: true                           # 自动提交
      idle-timeout: 600000                        # 连接超时的最大时长(毫秒),超时则被释放(retired),默认:10分钟
      pool-name: DataSourceHikariCP               # 连接池名称
      max-lifetime: 1800000                       # 连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟
      connection-test-query: SELECT 1

springboot整合mybatis配置

1.引入依赖
默认第一个依赖就行了,第二个依赖可以调整mapper接口继承通用mapper

<!--        mybatis启动器-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>

<!--        mapper启动器:myMapper还封装了常用查询语句-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>

2.mybatis配置

# myBatis相关配置
mybatis:
  type-aliases-package: org.example.pojo          # mapper逆向生成工具后实体包存放的位置
  mapper-locations: classpath:mapper/*.xml        # 所有mapper映射的文件所在目录
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl    # 开启mybatis日志实现
# 通用mapper配置
mapper:
  mappers: org.example.my.mapper.MyMapper         # 所有mapper都需要实现的接口
  not-empty: true                                 # 在进行数据库操作的时候,判断一个属性是否为空的时候,是否需要自动追加username != ""
  identity: MYSQL

3.编写自己的通用mapper

package org.example.my.mapper;

import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;

/**
 * 继承自己的myMapper
 */
public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {

}

4.常用mapper示例

package org.example.mapper;

import org.example.my.mapper.MyMapper;
import org.example.pojo.Teacher;
import org.springframework.stereotype.Repository;

@Repository
public interface TeacherMapper extends MyMapper<Teacher> {
}

接口参数验证框架

1.引入依赖

<!--        引入参数验证框架-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

2.bean添加验证注解
常用验证注解有:
在这里插入图片描述

示例:

package org.example.pojo.bo;

import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
public class TeacherBO {

    private String id;

    @NotBlank
    private String name;

    @NotNull
    private Integer age;

}

3.controller层代码配置

    @PostMapping("save")
    public JSONResult save(@Valid @RequestBody TeacherBO teacherBO,
                           BindingResult bindingResult){
        String sid = UUID.randomUUID().toString().trim();

        if (bindingResult.hasErrors()) {
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            HashMap<String, String> m = new HashMap<>();
            for (FieldError error : fieldErrors) {
                m.put(error.getField(),error.getDefaultMessage());
            }
            return JSONResult.error(m.toString());
        }


        Teacher teacher = new Teacher();
        BeanUtils.copyProperties(teacherBO, teacher);
        teacher.setId(sid);
//        teacher.setName("展示");
//        teacher.setAge(18);

        teacherService.save(teacher);

        return new JSONResult("1");
    }

事务管理

事务的传播属性:

  • required:当存在事务时沿用上一个事务,没有则新建一个事务
  • suppots:如果当前存在事务则沿用,如果没有事务则不用
  • mandatory:当前必须存在一个事务,如果没有则抛出异常
  • required_new:如果当前存在事务则创建一个事务,如果没有同required
  • not_supported:如果当前存在事务,则挂起事务,自己不用事务
  • never:如果当前存在事务,则抛出异常
  • nested:如果当前存在事务,则开启子事务(嵌套事务),嵌套事务是独立提交或回滚;
    如果当前没有事务,则同required,如果主事务提交或回滚,会携带子事务,但子事务异常,主事务可回滚可不回滚

示例:

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public List<Teacher> queryByCondition(String name) {
        Example example = new Example(Teacher.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("name",name);

        List<Teacher> teachers = teacherMapper.selectByExample(example);
        return teachers;
    }

整合自定义阿里druid数据源

1.引入依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.6</version>
</dependency>

2.配置数据源类型

spring: 
	datasource: 
		type: com.alibaba.druid.pool.DruidDataSource  # 配置自定义的数据源:阿里druid

3.配置druid连接池

spring: 
	datasource: 
		druid: 
			connection-timeout: 30000

开启mybatis的sql执行日志打印

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl    # 开启mybatis日志实现

使用AOP监控service执行时间

package org.example.config;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Aspect
@Slf4j
@Component
public class logAdvice {


    /**
     * AOP的通知类型
     * 前置通知
     * 后置通知
     * 环绕通知
     * 异常通知
     * 最终通知
     */

    @Around("execution(* org.example.service.impl..*.*(..))")
    public Object printLogOfService(ProceedingJoinPoint joinPoint) throws Throwable {

        log.info("正在执行{}.{}", joinPoint.getTarget().getClass(), joinPoint.getSignature().getName());

        long start = System.currentTimeMillis();

        Object result = joinPoint.proceed();

        // 3. 记录service的方法执行之后的时间
        long end = System.currentTimeMillis();
        // 4. 得到service的方法执行的时间差
        long takeTime = end - start;

        // 5. 根据时间差来进行判断,并且打印日志的输出到控制台
        if (takeTime > 3000) {
            log.error("当前执行时间耗时太久了,为{}毫秒", takeTime);
        } else if (takeTime > 2000) {
            log.warn("当前执行时间耗时稍微有点长,应该后期考虑优化,为{}毫秒", takeTime);
        } else {
            log.info("当前执行时间耗时为{}毫秒", takeTime);
        }

        return result;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
学习尚硅谷视频整理的文档 Spring Boot 1 1 Spring Boot入门 4 1.1 简介 4 1.2 微服务(martin fowler发表了一篇文章) 5 1.3 环境约束 7 1.4 第一个Spring Boot项目(jar):HelloWorld 8 1.5 入门案例详解 11 1.5.1 POM文件 11 1.5.2 主程序类,主入口类 12 1.6 使用Spring Initializer向导快速创建Spring Boot 16 2 Spring Boot配置 18 2.1 配置文件 18 2.2 YML语法 19 2.3 YML配置文件值获取 21 2.4 properties配置文件乱码问题 24 2.5 @ConfigurationProperties与@Value的区别 25 2.6 配置@PropertySource、@ImportResource、@Bean 27 2.7 配置文件占位符 30 2.8 Profile多环境支持 31 2.9 配置文件的加载位置 33 2.10 外部配置加载顺序 36 2.11 自动配置原理 37 2.12 @Conditional派生注解 41 3 Spring Boot与日志 42 3.1 日志框架分类和选择 42 3.2 SLF4j使用 43 3.3 其他日志框架统一转换成slf4j+logback 44 3.4 Spring Boot日志使用 45 3.5 Spring Boot默认配置 47 3.6 指定日志文件和日志Profile功能 52 3.7 切换日志框架(不使用SLF4j+LogBack) 54 4 Spring Boot与Web开发 55 4.1 Web开发简介 55 4.2 静态资源映射规则 56 4.3 引入Thymeleaf 60 4.4 Thymeleaf语法 61 4.5 SpringMVC自动配置原理 67 4.6 SpringBoot扩展与全面接管 70 4.7 如何修改SpringBoot的默认配置 72 4.8 【实验】CRUD操作 73 4.8.1 默认访问首页 73 4.8.2 登录页面国际化 74 4.8.3 登录 80 4.8.4 拦截器进行登录检查 81 4.8.5 实验要求(没按要求做,不想改了!) 82 4.8.6 CRUD-员工列表 83 4.8.7 CRUD-员工修改 86 4.8.8 CRUD-员工添加 87 4.8.9 CRUD-员工删除 88 4.9 错误处理原理&错误页面定制 90 4.10 配置嵌入式Servlet容器(springboot 1.50版本) 97 4.10.1 如何定制和修改Servelt容器的相关配置 97 4.10.2 注册servlet三大组件【servlet,filter,listener】 98 4.10.3 替换为其他嵌入式容器 102 4.10.4 嵌入式servlet容器自动配置原理 103 4.10.5 嵌入式servlet容器启动原理 103 4.11 使用外置的Servlet容器 104 4.11.1 步骤 104 4.11.2 原理 107 5 Spring Boot与Docker(虚拟化容器技术) 110 5.1 简介 110 5.2 核心概念 111 5.3 安装Docker 112 5.4 Docker常用命令&操作 113 5.5 安装MySQL示例 114 6 Spring Boot与数据访问 115 6.1 JDBC 115 6.1.1 实现 115 6.1.2 自动配置原理 116 6.2 整合Durid数据源 117 6.3 整合Mybatis 122 6.3.1 注解版 123 6.3.2 配置文件版 124 6.4 整合SpringData JPA 125 6.4.1 SpringData简介 125 6.4.2 整合 126 7 Spring Boot启动配置原理 128 7.1 启动流程(Springboot 1.50版本) 128 7.1.1 创建SpringApplication对象 129 7.1.2 运行run方法 130 7.1.3 编写事件监听机制 132 8 Spring Boot自定义starters 136 8.1 概述 136 8.2 步骤 137 9 更多Springboot整合示例 144 10 Spring Boot与缓存 145 10.1 JSR107缓存规范 145 10.2 Spring的缓存抽象 146 10.2.1 基本概念 146 10.2.2 整合项目 146 10.2.3 CacheEnable注解 148 10.2.4 Cache注解 150 10.3 整合redis 154 10.3.1 在Docker上安装redis 154 10.3.2 Redis的Template 154 10.3.3 整合(百度) 155

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值