• 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.bootgroupId>
       <artifactId>spring-boot-devtoolsartifactId>
       <optional>trueoptional>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 更改内容后,点击ctrl+F9

    propertis配置

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

    1. 新建一个properties文件放在resource里面MyConfig.properties
    user.userName=叼毛
    user.age=20
    
    • 1
    • 2
    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;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    3 引入依赖

    <dependency>
             <groupId>org.springframework.bootgroupId>
             <artifactId>spring-boot-configuration-processorartifactId>
         dependency>
    
    • 1
    • 2
    • 3
    • 4

    SpringBoot-整合redis

    配置步骤:

    1.引入依赖

    
    <dependency>
    	<groupId>org.springframework.bootgroupId>
    	<artifactId>spring-boot-starter-data-redisartifactId>
    	
    dependency>
    
    <dependency>
    	<groupId>com.squareup.okhttp3groupId>
    	<artifactId>okhttpartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.配置yml

    spring:
      redis:
        database: 0
        host: 192.168.1.201
        port: 6379
        password: 123456
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.拷贝RedisOperator

    4.controller测试redis中set和get

    @Autowired
    private RedisOperator redis;
        
    @GetMapping("/redis")
    public Object redis() {
        redis.set("name", "国产凌凌漆");
        return redis.get("name");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    自定义启动logo

    启动logo设置为图片

    spring
    	banner:
    	    image:
    	      location: classpath:img/cat.png
    	      pixelmode: block
    
    • 1
    • 2
    • 3
    • 4
    • 5

    启动logo设置为文本

    spring:
      banner:
        location: classpath:banner/banner.txt
    
    • 1
    • 2
    • 3

    web请求静态资源

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

    classpath:/static
    classpath:/public
    classpath:/resources
    classpath:/META-INF/resources
    
    • 1
    • 2
    • 3
    • 4

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

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

    自定义静态资源配置路径

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

    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";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    接口参数常用注解

    • @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";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    返回值

    一般封装成一个对象

    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;
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138

    文件上传

    文件上传大小限制

    spring:
      servlet:
        multipart:
          max-file-size: 600KB  
          max-request-size: 2MB
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    在这里插入图片描述

    自定义异常界面

    自定义封装异常

    package org.example.exception;
    
    public class MyCustomException extends RuntimeException {
        public MyCustomException(String message) {
            super(message);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    拦截器

    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");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    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");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    定时任务

    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));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    整合高性能HicarICP数据源

    1.引入依赖pom

    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-jdbcartifactId>
            dependency>
    
    
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    springboot整合mybatis配置

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

    
            <dependency>
                <groupId>org.mybatis.spring.bootgroupId>
                <artifactId>mybatis-spring-boot-starterartifactId>
                <version>2.1.0version>
            dependency>
    
    
            <dependency>
                <groupId>tk.mybatisgroupId>
                <artifactId>mapper-spring-boot-starterartifactId>
                <version>2.1.5version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    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> {
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    接口参数验证框架

    1.引入依赖

    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-validationartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    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");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    事务管理

    事务的传播属性:

    • 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;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    整合自定义阿里druid数据源

    1.引入依赖

    
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>druid-spring-boot-starterartifactId>
        <version>1.2.6version>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.配置数据源类型

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

    3.配置druid连接池

    spring: 
    	datasource: 
    		druid: 
    			connection-timeout: 30000
    
    • 1
    • 2
    • 3
    • 4

    开启mybatis的sql执行日志打印

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

    使用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;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
  • 相关阅读:
    【LeetCode算法系列题解】第56~60题
    Mapbox 与 Babylon.js 可视化 构建车子
    数据公网传输加密隧道技术
    2154. 将找到的值乘以 2
    UG NX二次开发(C++)-采用NXOpen方法计算体的质心
    MySQL 自建数据库慢日志分析
    【c++】noexcept关键字
    [附源码]计算机毕业设计基于SpringBoot文曦家教预约系统
    java项目基于 SSM+JSP 的毕业生就业信息管理系统,保证可用
    【python技巧】替换文件中的某几行
  • 原文地址:https://blog.csdn.net/u013303534/article/details/119761860