• SpringBoot知识点总结-DX的笔记


    什么是SpringBoot?

    • Spring Boot 是由 Pivotal 团队提供的全新框架
    • 目的是用来简化新 Spring 应用的初始搭建以及开发过程
    • 该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置
    • 通过这种方式,Spring Boot 致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
    • Spring Boot 并不是对 Spring 功能上的增强,而是提供了一种快速使用 Spring 的方式。

    特性

    • 约定大于配置
    • 创建独立的spring应用程序。
    • 嵌入的tomcat jetty 或者undertow 不用部署WAR文件。
    • 允许通过Maven来根据需要获取starter
    • 尽可能的使用自动配置spring
    • 提供生产就绪功能,如指标,健康检查和外部配置properties yaml yml
    • 开箱即用,没有代码生成,也无需 XML 配置,同时也可以修改默认值来满足特定的需求。

    传统开发模式

    • 优点

      • 开发简单,集中式管理
      • 基本不会重复开发
      • 功能都在本地,没有分布式的管理和调用消耗
    • 缺点

      • 效率低:开发都在同一个项目改代码,相互等待,冲突不断
      • 维护难:代码功功能耦合在一起,新人不知道何从下手
      • 不灵活:构建时间长,任何小修改都要重构整个项目,耗时
      • 稳定性差:一个微小的问题,都可能导致整个应用挂掉
      • 扩展性不够:无法满足高并发下的业务需求
      • 对服务器的性能要求要统一,要高

    微服务开发模式

    • 优点
      • 每个微服务都很小,这样能聚焦一个指定的业务功能或业务需求
      • 微服务能够被小团队开发,这个小团队2-5人就可以完成了
      • 微服务是松耦合的,是有功能,有意义的服务,开发阶段或部署阶段都是独立的
      • 微服务可以使用不同的语言开发
      • 微服务能部署在中低端配置的服务器上
      • 很容易和第三方集成
      • 每个服务都有自己的存储能力,单独的库,也可以有统一的库
    • 缺点:
      • 微服务会带来过多的操作
      • 可能有双倍的努力
      • 分布式系统可能复杂难管理
      • 分布跟踪部署难
      • 当服务数量增加时,管理复杂度增加

    SpringBoot的配置

    配置文件

    • properties文件

      #第一种配置文件
      #mysql
      jdbc.mysql.driverClassName=com.mysql.cj.jdbc.Driver
      jdbc.mysql.url=jdbc:mysql://localhost:3306/crm?serverTimezone=UTC
      jdbc.mysql.username=root
      jdbc.mysql.password=root
      
      #druid
      druid.initialSize=10
      druid.minIdle=10
      druid.maxActive=50
      druid.maxWait=60000
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

      yml文件

      #第二种配置文件
      #myKey: myValue
      
      #yaml 层级式键值对配置
      #层级:通过换行符+空格,同一层级必须对其,父层与子层之间通常使用2个空格
      #level1:
      #  level21: aaa
      #  level2:
      #    level31: bb
      #    level32: cc
      
      #数据类型
      #简单值
      #字符串:可以不使用引号包裹,但是有特殊符号时需要使用引号包裹(例如:空格)
      name: 张三
      age: 10
      birthday: 1998/07/25
      gender: true
      obj: ~
      
      #数组(也认为是LIst集合)
      #行内
      array1: [spring, springmvc, mybatis]
      array2:
        - html
        - css
        - javascript
      
      #对象(也可认为是Map集合)
      student:
        name: 李四
        age: 22
        birth: 1999/10/17
        gender: false
        hobby: [football, games, swimming]
        address:
          city: 郑州市
          area: 金水区
          street: 民航路
      
      #主配置
      #激活环境配置profiles
      #spring:
      #  profiles:
      #    active: dev
      #server:
      #  port: 8080
      
      • 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

    读取配置文件

    • 本质是将配置类对象放到ioc容器

    • 单个读取

      @Value("${name}")
      private String username;
      
      • 1
      • 2
    • 使用配置类读取

      • 第一种方式

        @Component + @ConfigurationProperties
        
        • 1
      • 第二种方式

        @EnableConfigurationProperties + @ConfigurationProperties
        
        • 1
    • 读取第三方的properties文件

      @Component
      @ConfigurationProperties(prefix = "jdbc.mysql")
      //加载第三方资源文件
      @PropertySource(value = "classpath:db.properties")
      
      • 1
      • 2
      • 3
      • 4
    • 读取原生的xml文件

    • demo

      /**
       * 读取配置文件数据
       */
      @RestController
      public class ReadConfigController {
      
          /**
           * 单个读取,不方便
           * 使用@Value注解+SpringEL来实现配置读取 
           */
          @Value("${name}")
          private String username;
          @Value("${age}")
          private Integer age;
          @Value("${birthday}")
          private Date birthday;
          @Value("${gender}")
          private Boolean gender;
          @Value("${student.name}")
          private String studentName;
          @GetMapping("/read")
          public String read(){
              return "姓名:" + username + " 年龄:" + age + " 生日:" + birthday + " 性别:" + gender + " 学生姓名:" + studentName;
          }
      
          /**
           * 使用配置类
           * 将配置类放到IOC容器,在这里自动注入
           */
          @Autowired
          private StudentProperties studentProperties;
          @GetMapping("/readProperties")
          public StudentProperties readProperties(){
              return studentProperties;
          }
      
          /**
           * 读取第三方的properties文件
           */
          @Autowired
          private MysqlProperties mysqlProperties;
          @GetMapping("/readProp")
          public MysqlProperties readProp(){
              return mysqlProperties;
          }
      
          /**
           * 读取原生的xml配置文件
           */
          @Autowired
          private Emp emp;
          @GetMapping("/readXml")
          public Emp readXml(){
              return emp;
          }
      }
      
      • 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

      在配置类上加注解

      //加载原生的xml spring配置文件
      @ImportResource(locations = "classpath:applicationContext.xml")
      //开启配置文件读取,属性为要读取的配置类,可以批量读取配置类
      @EnableConfigurationProperties({StudentProperties.class, AddressProperties.class})
      @SpringBootApplication
      public class Springboot02ConfigApplication {
      
          public static void main(String[] args) {
              SpringApplication.run(Springboot02ConfigApplication.class, args);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

      读取yaml文件的配置类

      /**
       * 学生配置读取类,自动读取yml配置文件
       *
       * 成员变量名称必须与配置名称保持一致(驼峰与中划线)
       * 1.@Component + @ConfigurationProperties
       * 2.@EnableConfigurationProperties + @ConfigurationProperties
       *
       * 第二种方式的@EnableConfigurationProperties注解
       * 需要放到配置类上
       * 作用是:开启配置文件读取
       */
      @Data
      //@Component //配置bean
      @ConfigurationProperties(prefix = "student")  //读取配置文件,属性用来指定层级
      public class StudentProperties {
      
          private String name;
          private Integer age;
          private Date birth;
          private Boolean gender;
          private String[] hobby;
          private AddressProperties address;
      
          //get...  set...
      }
      
      • 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
      // @Component
      @Data
      @ConfigurationProperties(prefix = "student.address")
      public class AddressProperties {
          private String city;
          private String area;
          private String street;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      读取properties文件的配置类

      /**
       * 读取#第三方的priperties文件
       */
      @Data
      @Component
      @ConfigurationProperties(prefix = "jdbc.mysql")
      //加载第三方资源文件
      @PropertySource(value = "classpath:db.properties")
      public class MysqlProperties {
      
          private String driverClassName;
          private String url;
          private String username;
          private String password;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15

      读取原生的applicationContext.xml文件

      
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          
          <bean id="dept" class="com.dx.bean.Dept">
              <property name="id" value="10"/>
              <property name="dname" value="研发部"/>
          bean>
          <bean id="emp" class="com.dx.bean.Emp">
              <property name="id" value="1001"/>
              <property name="ename" value="汤姆"/>
              <property name="dept" ref="dept"/>
          bean>
      beans>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      @Data
      public class Emp {
          private Integer id;
          private String ename;
          private Dept dept;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      @Data
      //开启链式调用
      @Accessors(chain = true)
      public class Dept {
          private Integer id;
          private String dname;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    profile配置文件

    • 三种工作环境配置文件:开发环境(dev)、生产环境(prod)、测试环境(test)

      #环境配置
      #需要激活:在application.yml中激活
      #命名规则:application-xxx.xml
      
      #开发环境配置
      server:
        #端口号
        port: 8001
        servlet:
          #根路径
          context-path: /web-dev
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      #生产环境配置
      server:
        port: 8003
        servlet:
          context-path: /web-prod
      
      • 1
      • 2
      • 3
      • 4
      • 5
      #测试环境
      server:
        port: 8002
        servlet:
          context-path: /web-test
      
      • 1
      • 2
      • 3
      • 4
      • 5

      在测试的时候,需要修改pom的编译路径,确保把所有的配置文件都编译以后再测试

      <build>
          
          <resources>
              <resource>
                  <directory>D:\workspace\SpringBoot-Code\02-spring-boot-configdirectory>
                  <includes>
                      <include>**/*.ymlinclude>
                      <include>application.ymlinclude>
                  includes>
              resource>
          resources>
      build>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

    部署时配置文件

    • 外部配置文件

      在D盘放一个application.yml文件 端口指定为8009
      打包后使用命令行运行并且指定
      
      java -jar aaa.jar --spring.config.location=D:/application.yml
      
      • 1
      • 2
      • 3
      • 4
    • 命令修改配置文件

      可以使用命令行参数指定(文档一行写不下的时候,不要回车)
      
      java -jar aaa.jar --server.port=8888 --server.servlet.context-path=/bjpowernode
      
      • 1
      • 2
      • 3

    配置优先级

    • 后加载的会覆盖先加载的

    • 最后加载的优先级最高

    • spring boot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件

      其中同一目标下的properties文件的优先级大于yml文件

    • 配置文件可以放的位置和优先级
      classpath:/ --优先级4

      classpath:/config/ --优先级3

      file:./ --优先级2

      file:./config/ --优先级1

    日志logback

    配置日志级别
    • @RestController
      //注解式日志:动态为该类声明一个静态Logger成员变量
      //@Slf4j
      public class LogController {
      
          /**
           * 使用日志:
           * 在当前类中声明一个成员变量,类型为Logger类型
           */
          private Logger log = LoggerFactory.getLogger(LogController.class);
      
          @GetMapping("/getLog")
          public String getLog(){
      
              /**
               * 在各个日志框架都有级别
               * 错误error,警告warn,信息info,调试debug,底层trace
               *
               * springboot默认级别为info
               * 可以在application.yml配置文件中配置
               *
               * 例如:当级别为info,日志输入仅会输入info以及以上级别日志
               */
              //程序出现异常
              log.error("error级别的日志");
              //程序有可能出现问题,提醒或警告
              log.warn("warn级别的日志");
              //信息:记录用户操作
              log.info("info级别的日志");
              //调试信息:开发时使用
              log.debug("debug级别的日志");
              //程序底层信息
              log.trace("trace级别的日志");
              //热部署添加内容
              log.info("无需重启自动生效...");
              return "正在记录日志";
          }
      }
      
      • 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
    • 全局配置 局部配置

      #配置日志
      logging:
        level:
          #使用root配置全局的日志级别
          root: info
          #局部日志级别,两种写法
      #    com.dx.controller: trace
          com:
            dx:
              controller: trace
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    自定义日志输出格式
      #自定义日志格式
      pattern:
        console: "%d{yyyy-MM-dd HH:mm:ss SSS} %-5level [%thread] %logger -- %msg%n"
    
    • 1
    • 2
    • 3
    生成日志文件
      #日志在文件中的输出
      file:
        #日志文件名,在根目录下可以找到文件
        name: demo.log
        #指定日志文件路径,但是不能与那么同时配置,两个只能用一个
    #    path: c:/log/
    
      #如果想既自定义文件名 又指定文件位置,可以导入logback.xml文件,如果使用logback.xml记得把这里的配置去掉,不然会冲突
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    logback.xml:可以直接使用,直接放到项目中就可以

    
    
    <configuration scan="false" scanPeriod="60 seconds" debug="false">
        
        <property name="LOG_HOME" value="d:/logback/" />
        
        <property name="appName" value="springboot">property>
        
        <appender name="cc" class="ch.qos.logback.core.ConsoleAppender">
            
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
            layout>
        appender>
    
        
        <appender name="ff" class="ch.qos.logback.core.rolling.RollingFileAppender">
            
            <file>${LOG_HOME}/${appName}.logfile>
            
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                
                <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.logfileNamePattern>
                
                <MaxHistory>365MaxHistory>
                
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>10MBmaxFileSize>
                timeBasedFileNamingAndTriggeringPolicy>
            rollingPolicy>
            
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%npattern>
            layout>
        appender>
    
        
        
        <logger name="com.bjpowernode.controller" level="debug" />
        
        <logger name="org.springframework" level="debug" additivity="false">logger>
    
        
        <root level="info">
            
            <appender-ref ref="cc" />
            
            <appender-ref ref="ff" />
        root>
    configuration>
    
    • 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

    工具

    自定义配置提示
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-configuration-processorartifactId>
        <optional>trueoptional>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    热部署
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
        <scope>runtimescope>
        <optional>trueoptional>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    lombok
    
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <optional>trueoptional>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    //开启对象中set方法的链式调用
    @Accessors(chain = true)
    
    • 1
    • 2
    //链式调用
    Student s3 = new Student()
        .setId(30)
        .setName("王五")
        .setAddress("深圳")
        .setScore(82.6);
    System.out.println(s3);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    注解式日志
    //注解式日志:动态为该类声明一个静态Logger成员变量
    @Slf4j
    public class LogController {
        
    	  //可以代替这条语句
    //     private Logger log = LoggerFactory.getLogger(LogController.class);
    
        @GetMapping("/getLog")
        public String getLog(){
            log.error("error级别的日志");
            log.warn("warn级别的日志");
            log.info("info级别的日志");
            log.debug("debug级别的日志");
            log.trace("trace级别的日志");
            log.info("无需重启自动生效...");
            return "正在记录日志";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    处理静态资源

    配置静态资源路径

    • 默认位置

      # 默认静态资源路径:
      #   "classpath:/META-INF/resources/"
      #   "classpath:/resources/"
      #   "classpath:/static/"
      #   "classpath:/public/"
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 配置自定义位置

    • 配置静态资源访问路径

      spring:
        web:
          resources:
            #设置当前项目静态资源目录
            #注意:配置自定义静态资源目录时,需要添加原有配置项,否则会覆盖原有配置
            #classpath表示在类路径下查找资源,file表示在操作系统的文件系统下查找资源 d:/
            static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/my/,file:${custom.upload}
        mvc:
          #设置当前项目静态资源的访问前缀
          static-path-pattern: /static/**
          
      #配置自定义本地的资源路径
      custom:
        upload: E:\文件\图片\壁纸
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14

    使用静态资源jar包

    • 导入bootstrap和jqury依赖

      
      <dependency>
          <groupId>org.webjarsgroupId>
          <artifactId>jqueryartifactId>
          <version>3.6.0version>
      dependency>
      
      <dependency>
          <groupId>org.webjarsgroupId>
          <artifactId>bootstrapartifactId>
          <version>3.4.1version>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    • 使用demo

      DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Titletitle>
          <link rel="stylesheet" href="/webjars/bootstrap/3.4.1/css/bootstrap.min.css">
      head>
      <body>
        <div style="text-align: center">
            <h1>首页h1>
            <div>
                <span id="hello">你好span>
            div>
            <div>
                <button type="button" class="btn btn-primary">按钮button>
            div>
            <div>
                <img src="/static/bbb.jpg" alt="" style="width: 300px; height: 200px">
            div>
            
            <script type="text/javascript" src="/webjars/jquery/3.6.0/jquery.min.js">script>
            <script type="text/javascript">
                $(function (){
                    var str = $('#hello').html();
                    alert(str);
                    $('#hello').append('springboot');
                })
            script>
        div>
      body>
      html>
      
      • 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

    使用模板引擎 Thymeleaf

    配置Thymeleaf

    • 开发时关闭缓存、发布时打开缓存

      spring:   
        #Thymeleaf的配置
        thymeleaf:
          #页面缓存,开发时关闭缓存、发布时打开缓存
          cache: false
          #前后缀,使用默认值就可以
      #    prefix: classpath:/templates/
      #    suffix: .html
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

    动态属性获取数据

    • 取值

      
      <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
      ......
      
      <p th:text="${msg}">p>
      <p th:text="${message}">p>
      <p th:utext="${message}">p>
      <p>[[${msg}]]p>
          
      
      <form action="/emp/edit" th:action="@{/emp/edit}" method="post">
          <div class="form-group">
              <label>员工编号label>
              
              <input type="text" name="id" class="form-control" th:value="${emp.id}">
          div>
          <div class="form-group">
              <label>员工姓名label>
              
              <input type="text" name="ename" class="form-control" th:value="*{ename}">
          div>
          
          <div class="form-group">
              <label>入职日期label>
              
              <input type="date" name="hiredate" class="form-control" th:value="${#dates.format(emp.hiredate, 'yyyy-MM-dd')}">
          div>
          <div class="form-group">
              <label>员工性别label>
              
              <select name="gender" class="form-control">
                  <option value="">option>
                  <option value="1" th:selected="${emp.gender=='1'}">男性option>
                  <option value="2" th:selected="${emp.gender=='2'}">女性option>
              select>
          div>
          <div class="form-group">
              <button type="button" class="btn btn-primary">提交button>
          div>
      form>
      
      • 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
    • 循环

      <tr th:each="emp : ${empList}">
          <td>[[${emp.id}]]td>
          <td th:text="${emp.ename}">td>
      tr>
      
      • 1
      • 2
      • 3
      • 4
    • 判断

      <td>
          <span th:if="${emp.gender=='1'}">男性span>
          <span th:if="${emp.gender=='2'}">女性span>
      td>
      <td th:switch="${emp.gender}">
          <span th:case="'1'">帅哥span>
          <span th:case="'2'">靓女span>
      td>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 日期格式化

      //日期格式化
      //在成员变量上添加注解  @DateTimeFormat:接收参数时格式化		@JsonFormat:发送参数时格式化
      @DateTimeFormat(pattern = "yyyy-MM-dd")
      @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
      private Date hiredate;
      
      • 1
      • 2
      • 3
      • 4
      • 5
      
      <td th:text="${#dates.format(emp.hiredate, 'yyyy-MM-dd')}">td>
      
      • 1
      • 2
    • 自动根路径 @{...}

      #在application.yml文件中
      #修改项目的根路径
      server:
        servlet:
          context-path: /boot
      
      • 1
      • 2
      • 3
      • 4
      • 5
      
      <p><a href="/emp/list" th:href="@{/emp/list}">员工列表a>p>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 路径传参

      <td>
          
          <a href="/emp/get/1" th:href="@{'/emp/get/' + ${emp.id}}" class="btn btn-warning btn-xs">编辑a>
          
          <a href="#" th:href="@{/emp/remove(id=${emp.id},ename=${emp.ename},job=${emp.job})}" class="btn btn-danger btn-xs">删除a>
      td>
      
      
      <form th:action="@{/auth/login}" method="post" style="width: 350px;margin: 10px auto;">
          <div style="color: red;">[[${message}]]div>
          <div class="form-group">
              <label>用户名label>
              <input type="text" name="username" class="form-control">
          div>
          <div class="form-group">
              <label>密码label>
              <input type="password" name="password" class="form-control">
          div>
          <div class="form-group">
              <button type="submit" class="btn btn-primary">登录button>
          div>
      form>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22

    SpringMVC配置

    /**
     * 自定义WebMvc配置类
     * 实现一个接口WebMvcConfigurer的配置类,相当于原生springmvc.xml配置文件
     */
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        /**
         * 动态页面访问映射
         */
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/page/login").setViewName("login");
            registry.addViewController("/").setViewName("login");
            registry.addViewController("/page/index").setViewName("index");
        }
    
        /**
         * 注册拦截器
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry
                    //配置拦截器对象
                    .addInterceptor(new LoginInterceptor())
                    //配置拦截器拦截路径
                    .addPathPatterns("/**")
                    //配置拦截器放行路径(白名单)
                    .excludePathPatterns("/static/**", "/webjars/**", "/auth/login", "/page/login", "/");
        }
    
        /**
         * 对静态资源处理
         */
        // @Override
        // public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //     registry
        //             .addResourceHandler("/static2/**")
        //             .addResourceLocations("classpath:/my2/");
        // }
    
        /**
         * 添加自定义的数据格式转换器
         */
        @Override
        public void addFormatters(FormatterRegistry registry) {
            // registry.addFormatter();
            registry.addConverter(new PointConverter());
        }
    
        /**
         * 前后端分离的项目:设置全局跨域处理
         */
        @Override
        public void addCorsMappings(CorsRegistry registry) {
        }
    }
    
    • 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

    拦截器

    public class LoginInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            Object loginUser = request.getSession().getAttribute("loginUser");
            if(loginUser == null){
                request.setAttribute("message", "没有登录");
                request.getRequestDispatcher("/page/login").forward(request, response);
                return false;
            }
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    类型转换器

    /**
     * 自定义的类型转换器:
     * 作用:将String转换为自定义Point
     */
    public class PointConverter implements Converter<String, Point> {
        @Override
        public Point convert(String source) {
            String[] ss = source.split(",");
            Point point = new Point(ss[0], ss[1]);
            return point;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    <p><a th:href="@{/getPoint(point='15,58')}">类型转换器案例a>p>
    
    • 1

    web中的三大组件

    • servlet、filter、listener

    • 默认不支持,需要在配置类中配置bean

    • 配置三大组件

      @Configuration
      public class ServletConfig {
      
          /**
           * 注册servlet
           */
          @Bean
          public ServletRegistrationBean servletRegistrationBean(){
              ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
              //设置Servlet对象
              servletRegistrationBean.setServlet(new DemoServlet());
              //设置路径映射
              servletRegistrationBean.addUrlMappings("/demo");
              //设置初始化参数
              //单个
              servletRegistrationBean.addInitParameter("msg", "hello");
              //批量
              // servletRegistrationBean.setInitParameters();
              return servletRegistrationBean;
          }
      
          /**
           * 注册Filter
           */
          @Bean
          public FilterRegistrationBean filterRegistrationBean(){
              FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
              filterRegistrationBean.setFilter(new DemoFilter());
              filterRegistrationBean.addUrlPatterns("/*");
              // filterRegistrationBean.addInitParameter();
              return filterRegistrationBean;
          }
      
          /**
           * 注册Listener
           */
          @Bean
          public ServletListenerRegistrationBean servletListenerRegistrationBean(){
              ServletListenerRegistrationBean servletListenerRegistrationBean = new ServletListenerRegistrationBean();
              servletListenerRegistrationBean.setListener(new DemoListener());
              return servletListenerRegistrationBean;
          }
      }
      
      • 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

      DemoFilter.java

      @WebFilter("/*")
      public class DemoFilter implements Filter {
          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              System.out.println("DemoFilter执行了.........");
      
              //过滤器放行
              filterChain.doFilter(servletRequest, servletResponse);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      DemoListener.java

      @WebListener
      public class DemoListener implements ServletContextListener {
      
          @Override
          public void contextInitialized(ServletContextEvent sce) {
              System.out.println("DemoListener执行了.....");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      DemoServlet.java

      @WebServlet("/demo")
      public class DemoServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              System.out.println("DemoServlet.........." + msg);
              resp.getWriter().write("ok");
          }
      
          private String msg;
      
          @Override
          public void init(ServletConfig config) throws ServletException {
              msg = config.getInitParameter("msg");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15

    全局异常处理器

    • public class CustomException extends RuntimeException{
      }
      
      • 1
      • 2
    • /**
       * 全局异常处理器
       * @RestControllerAdvice:全局异常处理器的注解
       */
      // @ControllerAdvice
      @RestControllerAdvice
      public class GlobalExceptionHander {
      
          @ExceptionHandler(CustomException.class)
          public Map<String, Object> customExceptionHandle(CustomException e){
              Map<String, Object> map = new HashMap<>();
              map.put("code", -2);
              map.put("message", "自定义异常发生");
              return map;
          }
      
          @ExceptionHandler(Exception.class)
          public Map<String, Object> exceptionHandle(Exception e){
              Map<String, Object> map = new HashMap<>();
              map.put("code", -1);
              map.put("message", "其他异常发生");
              return map;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24

    全局日期格式化

    • 在SpringMVC使用@DateTimeFormat和@JsonFormat

      @DateTimeFormat(pattern = "yyyy-MM-dd")
      @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
      private Date hiredate;
      
      • 1
      • 2
      • 3
    • application.yml

      #全局输入日期格式化,局部@DateTimeFormat
      spring: 
        mvc: 
          format:
            date: yyyy-MM-dd HH:mm:ss
            
        #全局输出日期格式化,局部@JsonFormat
        jackson:
          date-format: yyyy-MM-dd HH:mm:ss
          time-zone: GMT+8
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

    配置文件上传

    #配置文件上传
    spring: 
      servlet:
        multipart:
          #单个文件大小限制
          max-file-size: 1MB
          #单次请求总文件大小限制
          max-request-size: 10MB
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    前后端分离

    设置全局跨域处理

    • WebConfig.java配置文件

      /**
           * 前后端分离的项目:设置全局跨域处理
           * 浏览器的同源策略:
           * 在发送异步请求时,请求地址中 协议、服务器地址、服务器端口号必须保持一致
           * 如果不一致就违反浏览器同源策略,浏览器禁止访问,会接收到一个CORS错误
           *
           * 注意:协议http与https不同源
           *      地址localhost与127.0.0.1不同源
           *
           * 前后端分离的项目:设置全局跨域处理
           */
      @Override
      public void addCorsMappings(CorsRegistry registry) {
          registry
              //跨域访问的路径(资源)
              .addMapping("/**")
              //设置允许跨域的服务器地址
              // .allowedOriginPatterns("http://localhost:63342")
              .allowedOriginPatterns("*")
              //设置允许跨域访问的请求方式
              // .allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")
              .allowedMethods("*")
              //设置允许跨域访问时的头部信息
              // .allowedHeaders()
              //设置暴露给请求服务器头部信息
              // .exposedHeaders()
              //设置跨域访问时是否允许携带凭证(cookie中JSESSIONID)
              .allowCredentials(true)
              //跨域访问时会先发送一个询问请求(询问当前请求是否允许跨域)
              //设置询问请求的发送周期
              .maxAge(3600);
      }
      
      • 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
    • 后端资源

      @RestController
      public class UserController {
      
          @GetMapping("/user/list")
          public List<User> list(){
              User user1 = new User(1, "zhangsan", "123");
              User user2 = new User(2, "lisi", "123");
              User user3 = new User(3, "wangwu", "123");
              User user4 = new User(4, "zhaoliu", "123");
              return Arrays.asList(user1,user2,user3,user4);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    • 前端请求(另一个项目)

      $.ajax('http://localhost:8080/boot/user/list',{
          type:'get',
          success:function (res) {
              var str='';
              $.each(res,function () {
                  str+='<tr>';
                      str+='<td>'+this.id+'td>';
                      str+='<td>'+this.username+'td>';
                      str+='<td>'+this.password+'td>';
                      str+='tr>';
              });
              $('#tab').html(str);
          }
      });
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14

    外部Tomcat

    • 外部Tomcat支持tomcat jsp,内部Tomcat不支持tomcat jsp

    • 新建项目的时候与SpringBoot相似,唯一不同是打包方式改为war

    • 自己配置TomCat

    • 将静态资源文件放到 webapp/WEB-IF/ 下面

    • 自动生成ServletInitializer.java文件

      /**
       * 在外部tomcat启动服务器时加载springboot程序
       * 如果把这个类去掉,不会启动springboot,也就无法使用@Controller等组件
       */
      public class ServletInitializer extends SpringBootServletInitializer {
          @Override
          protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
              return application.sources(SpringBoot05JspApplication.class);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    • 可以使用 jsp 文件

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      
      
          
          Title
      
      
          

      首页

      测试

      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      
      
          
          成功
      
      
          

      成功

      ${message}

      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    • Controller

      @Controller
      public class HelloController {
      
          @GetMapping("/hello")
          public String hello(HttpServletRequest request){
              System.out.println("HelloController中的hello方法执行了....");
              request.setAttribute("message", "hello jsp");
              return "success";
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    • application.yml

      #配置jsp页面的前缀与后缀
      spring:
        mvc:
          view:
            prefix: /WEB-INF/pages/
            suffix: .jsp
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    后端数据校验

    • 新建项目时除了选中工具和核心包外,还要选中IO中的Validation依赖

    • 自动引入依赖

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

    数据校验

    • /**
       * hibernate-validator框架,后台数据校验,通过注解的方式来实现
       */
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      @Accessors(chain = true)
      public class Student {
      
          /**
           * @NotNull 数据不能为null
           * @NotEmpty 数据不能为null,也不能为空字符串
           * @NotBlank 数据不能为null,也不能为空字符串,也不能由空白字符组成
           * @Size 校验字符串、数组、集合的长度
           * @Range 校验数字的范围
           * @Email 校验有效是否合法
           * @Pattern 通过正则表达式校验
           *
           * 注解通用配置项:message,校验失败时提示信息
           */
          @NotBlank(message = "姓名不能为空")
          @Size(message = "姓名长度为4~10个字符", min = 4, max = 10)
          private String name;
          @NotNull(message = "年龄不能为空")
          @Range(message = "年龄范围为0~100岁", min = 0, max = 100)
          private Integer age;
          @NotBlank(message = "邮箱不能为空")
          //xxx@xx.xx
          @Email(message = "邮箱格式不合法")
          //正则校验
          // @Pattern(message = "", regexp = "")
          private String email;
      }
      
      • 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
    • 开启数据校验

      @RestController
      public class ValidationController {
      
          /**
           * 开启校验 @Validated
           *
           * 在方法的参数上标注@Validated表示开启后台数据校验,每个开启的数据校验数据之后,需要跟随一个BindingResult类型的参数
           * BindingResult对象用于接收校验失败的信息
           */
          @PostMapping("/save")
          public String save(@Validated Student student, BindingResult bindingResult){
              //判断校验是否通过
              if(bindingResult.hasErrors()){
                  List<ObjectError> allErrors = bindingResult.getAllErrors();
                  for (ObjectError error : allErrors) {
                      System.out.println(error.getDefaultMessage());
                  }
              }else{
                  System.out.println(student);
              }
              return "ok";
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23

    配置文件校验

    • application.yml

      #用于校验配置文件
      user:
        username: zhangsan
        age: 20
        email: aa@aa.aa
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 配置类

      @SpringBootApplication
      //使配置类的注解生效
      @EnableConfigurationProperties(UserProperties.class)
      public class Springboot06ValidationApplication {
          public static void main(String[] args) {
              SpringApplication.run(Springboot06ValidationApplication.class, args);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      @Data
      @ConfigurationProperties(prefix = "user")
      //添加批量读取配置文件的类上
      @Validated
      public class UserProperties {
      
          @NotBlank(message = "用户名不能为空")
          @Size(message = "用户名长度为6~16个字符", min = 6, max = 16)
          private String username;
          @NotNull(message = "年龄不能为空")
          @Range(message = "年龄范围为0~100岁", min = 0, max = 100)
          private Integer age;
          @NotBlank(message = "邮箱不能为空")
          @Email(message = "邮箱格式不合法")
          private String email;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

    正则表达式

    • 可以参考JDK手册:java.util.regex / Pattern

    • 后端使用正则表达式

      public class ParttenTests {
      
          @Test
          public void run(){
              /**
               * 正则表达式,验证字符串是否符合指定的规则
               */
              //1.String类
              String str = "zhang#123";
              System.out.println(str.matches("[abc]"));
              System.out.println(str.matches("[^abc]"));
              System.out.println(str.matches("[a-zA-Z]"));
              System.out.println(str.matches("[0-9]"));
              System.out.println(str.matches("[a-zA-Z0-9]"));
              System.out.println(str.matches("\\S"));
              System.out.println(str.matches("\\w{5,10}"));
              System.out.println(str.matches(".{5,10}"));
              System.out.println(str.matches(".*"));
              System.out.println("14345678901".matches("^1[3|5|6|7|8|9]\\d{9}$"));
      
              //2.Pattern类
              boolean result = Pattern.matches("^[0-9]+$", "123");
              System.out.println(result);
      
              //3.Matcher类
              Pattern pattern = Pattern.compile("^[0-9]+$");
              Matcher matcher = pattern.matcher("123a");
              System.out.println(matcher.matches());
          }
      }
      
      • 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
    • 前端使用正则表达式

      <script type="text/javascript">
        var regex = /^[0-9]+$/;
        var result = regex.test('123');
        alert(result);
      script>
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 使用注解

      //正则校验
      // @Pattern(message = "", regexp = "")
      private String email;
      
      • 1
      • 2
      • 3

    aop

    • 引入依赖

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

      @RestController
      public class AopController {
      
          @GetMapping("/list")
          public String list(){
              System.out.println("AopController中的list方法....");
              return "ok";
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • AopAspect.java

      /**
       * 切面类
       */
      @Component
      @Aspect
      // @Order(1)	//设置切面的启动顺序
      public class AopAspect {
      
          //公共切点表达式,方式一
          public static final String POINT_CUT = "execution(* com.bjpowernode.controller.*.*(..))";
          //公共切点表达式,方式二
          @Pointcut("execution(* com.bjpowernode.controller.*.*(..))")
          public void exp(){}
          
          /**
           * 前置通知
           */
          @Before("execution(* com.bjpowernode.controller.*.*(..))")
          public void before(){
              System.out.println("切面的前置通知...");
          }
          /**
           * 后置通知
           */
          @After(POINT_CUT)
          public void after(){
              System.out.println("切面的后置通知...");
          }
          /**
           * 返回通知
           */
          @AfterReturning(value = "exp()", returning = "result")
          public void returning(Object result){
              System.out.println("切面的返回通知..." + 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

    连接数据库

    使用jdbc

    • 创建项目选择 jdbc api和Mysql Dirver 依赖

    • application.yml

      #使用jdbc
      spring:
        datasource:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/student
          username: root
          password: 111111
      
          #?切换数据源,需要配置才能生效
          type: com.alibaba.druid.pool.DruidDataSource
      
          #数据源配置
          initialSize: 5
          minIdle: 10
          maxActive: 50
          maxWait: 30000
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    • entity层 略

    • dao

      public class DeptDaoImpl implements DeptDao {
      
          /**
           * 注入JdbcTemplate对象
           * JdbcTemplate是spring-jdbc中提供的工具类,用于操作数据库
           */
          @Autowired
          private JdbcTemplate jdbcTemplate;
      
          @Override
          public int insert(Dept dept) {
              String sql="insert into dept(dname,loc) values(?,?)";
              return jdbcTemplate.update(sql,dept.getDname(),dept.getLoc());
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
    • 测试

      @SpringBootTest
      class Springboot08JdbcApplicationTests {
      
          @Autowired
          private DataSource dataSource;
      
          //查看数据源配置信息
          @Test
          void contextLoads() {
              //自带数据源是: HikariDataSource
              System.out.println("数据源:"+dataSource);
          }
      
          /**
           * 使用jdbc完成查询
           */
          @Test
          void testJdbc() throws SQLException {
              Connection connection = dataSource.getConnection();
              String sql="select deptno,dname,loc from dept where deptno=?";
              PreparedStatement preparedStatement = connection.prepareStatement(sql);
              preparedStatement.setInt(1,60);
              ResultSet resultSet = preparedStatement.executeQuery();
              while (resultSet.next()){
                  int deptno = resultSet.getInt("deptno");
                  String dname = resultSet.getString("dname");
                  String loc = resultSet.getString("loc");
                  System.out.println("编号="+deptno+" 名字="+dname+" 地址="+loc);
              }
              resultSet.close();
              preparedStatement.close();
              connection.close();
          }
      }
      
      • 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

    使用数据库连接池Druid

    自定义配置类
    • 引入依赖,版本号不能省略

      
      <dependency>
          <groupId>com.alibabagroupId>
          <artifactId>druidartifactId>
          <version>1.1.10version>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 配置文件按application.yml

      #配置数据源
      spring:
        datasource:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/student
          username: root
          password: 111111
      
          #切换数据源,需要配置才能生效
          type: com.alibaba.druid.pool.DruidDataSource
      
          #数据源配置
          initialSize: 5
          minIdle: 10
          maxActive: 50
          maxWait: 30000
      
          #开启监控: 监控stat,SQL防火墙wall,日志slf4j,需要配置
          filters: stat,wall,slf4j
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    • 自定义的配置类

      /**
       * 自定义德鲁伊数据源配置类
       */
      @Configuration
      public class DruidConfig {
      
          @Bean
          //使用注解使配置文件的数据源生效
          @ConfigurationProperties(prefix = "spring.datasource")
          public DruidDataSource dataSource(){
              DruidDataSource druidDataSource = new DruidDataSource();
              //可以在这配置,也可以使用配置文件配置
      //        druidDataSource.setInitialSize(10);
              return druidDataSource;
          }
      
          /**
           * sql监控的servlet
           */
          @Bean
          public ServletRegistrationBean servletRegistrationBean(){
              ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
              servletRegistrationBean.setServlet(new StatViewServlet());
              servletRegistrationBean.addUrlMappings("/druid/*");
              servletRegistrationBean.addInitParameter("loginUsername","admin");
              servletRegistrationBean.addInitParameter("loginPassword", "123");
              return servletRegistrationBean;
          }
      
          /**
           * sql监控过滤器
           */
          @Bean
          public FilterRegistrationBean filterRegistrationBean(){
              FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
              filterRegistrationBean.setFilter(new WebStatFilter());
              filterRegistrationBean.addUrlPatterns("/*");
              //排除路径
              filterRegistrationBean.addInitParameter("exclusions", "/druid/*,*.js,*.css,*.jpg,*.png");
              return filterRegistrationBean;
          }
      }
      
      • 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
    自带配置类
    • 引入依赖

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

      #使用自带启动类的德鲁伊
      spring:
        datasource:
          #切换数据源
          type: com.alibaba.druid.pool.DruidDataSource
          druid:
            #必要信息
            driver-class-name: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://localhost:3306/student
            username: root
            password: 111111
            #连接池基本信息
            initial-size: 6
            min-idle: 7
            max-active: 15
            max-wait: 20000
            #sql监控
            filter: stat,wall,slf4j
            #serlvet
            stat-view-servlet:
              enabled: true
              url-pattern: /druid/*
              login-password: 111
              login-username: root
            #filter
            web-stat-filter:
              enabled: true
              url-pattern: /*
              exclusions: "/druid/*,*.js,*.css,*.jpg,*.png"
      
      • 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

    JdbcTemplate工具

    • 封装了jdbc的工具

    • DeptDaoImpl.java

      @Repository
      public class DeptDaoImpl implements DeptDao {
      
          /**
           * 注入JdbcTemplate对象
           * JdbcTemplate是spring-jdbc中提供的工具类,用于操作数据库
           */
          @Autowired
          private JdbcTemplate jdbcTemplate;
      
          @Override
          public int insert(Dept dept) {
              String sql="insert into dept(dname,loc) values(?,?)";
              return jdbcTemplate.update(sql,dept.getDname(),dept.getLoc());
          }
      
          @Override
          public List<Dept> select() {
              /**
               * queryForList() 批量查询返回数据封装在map集合中
               * query(sql, rowMapper) 批量查询返回数据封装在指定的实体对象中
               *
               * RowMapper 行映射器,将字段与实体中的属性对照
               * BeanPropertyRowMapper 是RowMapper接口的实现类对象,根据字段名称与实体类中属性名称实现自动映射
               */
              String sql = "select deptno, dname, loc from dept order by deptno desc";
              //手动映射
              // jdbcTemplate.query(sql, new RowMapper(){
              //     @Override
              //     public Dept mapRow(ResultSet rs, int rowNum) throws SQLException {
              //         Dept dept = new Dept();
              //         dept.setDeptno(rs.getInt("deptno"));
              //         dept.setDname(rs.getString("dname"));
              //         dept.setLoc(rs.getString("loc"));
              //         return dept;
              //     }
              // });
              RowMapper<Dept> rowMapper = new BeanPropertyRowMapper<>(Dept.class);
              List<Dept> list = jdbcTemplate.query(sql, rowMapper);
              return list;
          }
      
          @Override
          public Dept selectById(Integer deptno) {
              String sql = "select deptno, dname, loc from dept where deptno=?";
              /**
               * queryForObject(String sql, RowMapper rowMapper) 返回结果为单行多列
               * queryForObject(String sql, Class requiredType) 返回结果为单行单列
               */
              // int i = jdbcTemplate.queryForObject(sql, Integer.class);
              RowMapper<Dept> rowMapper = new BeanPropertyRowMapper<>(Dept.class);
              Dept dept = jdbcTemplate.queryForObject(sql, rowMapper, deptno);
              return dept;
          }
      }
      
      • 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
    • 测试类

      @SpringBootTest
      class Springboot08JdbcApplicationTests {
      
          @Autowired
          private DataSource dataSource;
      
          @Test
          void contextLoads() {
              //自带数据源是: HikariDataSource
              //查看数据源配置信息
              System.out.println("数据源:"+dataSource);
              if (dataSource instanceof DruidDataSource){
                  DruidDataSource druidDataSource=(DruidDataSource) dataSource;
                  System.out.println(druidDataSource.getInitialSize());
                  System.out.println(druidDataSource.getMinIdle());
                  System.out.println(druidDataSource.getMaxActive());
                  System.out.println(druidDataSource.getMaxWait());
              }
          }
      
          @Autowired
          DeptDao deptDao;
          @Test
          void testInsert(){
              Dept dept = new Dept();
              dept.setDname("采购部");
              dept.setLoc("深圳");
              int result = deptDao.insert(dept);
              System.out.println(result);
          }
      
          @Test
          void testSelect(){
              List<Dept> list = deptDao.select();
              for (Dept dept : list) {
                  System.out.println(dept);
              }
          }
      
          @Test
          void testSelectById(){
              Dept dept = deptDao.selectById(48);
              System.out.println(dept);
          }
      }
      
      • 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

    整合MyBatis

    • 创建项目时,加上MyBatisFramwork依赖

      <dependency>
          <groupId>org.mybatis.spring.bootgroupId>
          <artifactId>mybatis-spring-boot-starterartifactId>
          <version>2.2.2version>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 数据库连接池依赖和分页插件

      
      <dependency>
          <groupId>com.alibabagroupId>
          <artifactId>druid-spring-boot-starterartifactId>
          <version>1.1.10version>
      dependency>
      
      <dependency>
          <groupId>com.github.pagehelpergroupId>
          <artifactId>pagehelper-spring-boot-starterartifactId>
          <version>1.4.2version>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    • 配置文件

      #配置数据源
      spring:
        jackson:
          date-format: yyyy-MM-dd
          time-zone: GMT+8
        mvc:
          format:
            date: yyyy-MM-dd
        datasource:
          #切换数据源
          type: com.alibaba.druid.pool.DruidDataSource
          druid:
            #必要信息
            driver-class-name: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://localhost:3306/bjpowernode
            username: root
            password: root
            #连接池基本信息
            initial-size: 6
            min-idle: 7
            max-active: 15
            max-wait: 20000
            #sql监控
            filter: stat,wall,slf4j
            #serlvet
            stat-view-servlet:
              enabled: true
              url-pattern: /druid/*
              login-password: 111
              login-username: root
            #filter
            web-stat-filter:
              enabled: true
              url-pattern: /*
              exclusions: "/druid/*,*.js,*.css,*.jpg,*.png"
      
      #mybatis配置
      #1.SqlSessionFactory配置bean -- 在自动化配置中已实现
      #2.mapper代理对象配置bean -- 通过注解的方式来实现
      mybatis:
        #加载核心配置文件
        #  config-location: classpath:mybatis.xml
        #加载mapper文件
        mapper-locations: classpath:mapper/*.xml
        #  mapper-locations: classpath:mapper/**/*.xml
        #类型别名
        type-aliases-package: com.bjpowernode.entity
        #全局参数: 与加载核心配置文件项冲突
        configuration:
          #开启下划线转驼峰
          map-underscore-to-camel-case: true
          #日志输出
          log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
        #插件:分页(单独配置)
      
      #分页组件pagehelper
      pagehelper:
        #自动识别数据库,应用数据库方言
        #mysql: select * from table_name limit offset,pageSize
        #oracle: select * from (select *,rownum myrow from (select * from table_name) where rownum <= 10) where myrow >= 5
        #  auto-dialect: true
        #合理化分页
        reasonable: true
      
      • 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
    • @SpringBootApplication
      /**
       * 批量配置mapper代理
       * 需要指定dao接口所在包
       */
       @MapperScans({
               @MapperScan(basePackages = "com.bjpowernode.dao"),
               @MapperScan(basePackages = "com.bjpowernode.dao2")
       })
       @MapperScan(basePackages = "com.bjpowernode.dao")
      public class Springboot09MybatisApplication {
      
          public static void main(String[] args) {
              SpringApplication.run(Springboot09MybatisApplication.class, args);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    • entity

      @Data
      public class Emp {
          private Integer empno;
          private String ename;
          private String job;
          private Integer mgr;
          private Date hiredate;
          private Double sal;
          private Double comm;
          private Integer deptno;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • dao

      /**
       * 使用注解来配置mapper代理对象
       *
       * @Mapper
       * 作用:为当前接口生成mapper代理对象,并将代理对象放入ioc容器
       *      类似于spring中单个接口代理对象的配置
       */
      @Mapper
      public interface EmpDao {
      
          List<Emp> select();
      
          Emp selectById(Integer id);
      
          int insert(Emp entity);
      
          int update(Emp entity);
      
          int delete(Integer id);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    • mapper

      
      DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <mapper namespace="com.bjpowernode.dao.EmpDao">
      
          <select id="select" resultType="emp">
              select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp order by empno asc
          select>
          <select id="selectById" parameterType="int" resultType="Emp">
              select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where empno=#{empno}
          select>
          <insert id="insert" parameterType="com.bjpowernode.entity.Emp">
              insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)
              values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
          insert>
          <update id="update" parameterType="com.bjpowernode.entity.Emp">
              update emp set ename=#{ename},job=#{job},mgr=#{mgr},hiredate=#{hiredate},sal=#{sal},comm=#{comm},deptno=#{deptno}
              where empno=#{empno}
          update>
          <delete id="delete" parameterType="int">
              delete from emp where empno=#{empno}
          delete>
      mapper>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
    • service

      public interface EmpService {
      
          Map<String, Object> page(Integer pageNumber, Integer pageSize);
      
          Emp get(Integer id);
      
          boolean save(Emp entity);
      
          boolean update(Emp entity);
      
          boolean remove(Integer id);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      
      @Service
      public class EmpServiceImpl implements EmpService {
      
          @Autowired
          private EmpDao empDao;
      
          @Override
          public Map<String, Object> page(Integer pageNumber, Integer pageSize) {
              PageHelper.startPage(pageNumber, pageSize);
              PageInfo<Emp> pageInfo = new PageInfo<>(empDao.select());
              Map<String, Object> pageMap = new HashMap<>();
              pageMap.put("list", pageInfo.getList());
              pageMap.put("total", pageInfo.getTotal());
              return pageMap;
          }
      
          @Override
          public Emp get(Integer id) {
              return empDao.selectById(id);
          }
      
          /**
           * springboot中事务管理
           * 使用注解的方式来实现
           */
          @Override
          @Transactional(rollbackFor = Exception.class)
          public boolean save(Emp entity) {
              return empDao.insert(entity) > 0;
          }
      
          @Override
          @Transactional(rollbackFor = Exception.class)
          public boolean update(Emp entity) {
              return empDao.update(entity) > 0;
          }
      
          @Override
          @Transactional(rollbackFor = Exception.class)
          public boolean remove(Integer id) {
              return empDao.delete(id) > 0;
          }
      }
      
      • 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
    • Controller

      @RestController
      @RequestMapping("/emp")
      public class EmpController {
      
          @Autowired
          private EmpService empService;
      
          @GetMapping("/page")
          public Map<String, Object> page(Integer pageNumber, Integer pageSize){
              Map<String, Object> pageMap = empService.page(pageNumber, pageSize);
              Map<String, Object> result = new HashMap<>();
              result.put("code", 200);
              result.put("message", "ok");
              result.put("data", pageMap);
              return result;
          }
      
          @GetMapping("/get/{id}")
          public Map<String, Object> get(@PathVariable("id") Integer id){
              Map<String, Object> result = new HashMap<>();
              result.put("code", 200);
              result.put("message", "ok");
              result.put("data", empService.get(id));
              return result;
          }
      
          @PostMapping("/save")
          public Map<String, Object> save(@RequestBody Emp emp){
              Map<String, Object> result = new HashMap<>();
              result.put("code", 200);
              result.put("message", "ok");
              result.put("data", empService.save(emp));
              return result;
          }
      
          @PutMapping("/edit")
          public Map<String, Object> edit(@RequestBody Emp emp){
              Map<String, Object> result = new HashMap<>();
              result.put("code", 200);
              result.put("message", "ok");
              result.put("data", empService.update(emp));
              return result;
          }
      
          @DeleteMapping("/remove/{id}")
          public Map<String, Object> remove(@PathVariable("id") Integer id){
              Map<String, Object> result = new HashMap<>();
              result.put("code", 200);
              result.put("message", "ok");
              result.put("data", empService.remove(id));
              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
      • 52
      • 53

    Api接口文档 swagger

    • 引入依赖

      
      <dependency>
          <groupId>io.springfoxgroupId>
          <artifactId>springfox-boot-starterartifactId>
          <version>3.0.0version>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 配置文件

      #swagger自定义配置
      #测试访问文档页面:http://localhost:8080/swagger-ui/index.html
      swagger3:
        base-package: com.dx.controller
        name: xxx
        url: https://gitee.com/
        email: 1233453534@qq.com
        version: 1.0
        group-name: dx
        title: "标题 "
        description: "描述信息"
        terms-of-service-url: https://gitee.com/
        license: cxs
        license-url: https://gitee.com/
      
      #时间格式
      spring:
        jackson:
          date-format: yyyy-MM-dd HH:mm:ss
          time-zone: GMT+8
        mvc:
          format:
            date: yyyy-MM-dd HH:mm:ss
          #解决swagger3.0和springboot整合的时问题
          pathmatch:
            matching-strategy: ant_path_matcher
      
      • 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
    • 读取配置的类

      @Data
      @ConfigurationProperties(prefix = "swagger3")
      public class SwaggerProperties {
      
          // 扫描的包
          // 给这个包下面的接口创建文档
          private String basePackage;
          // 作者姓名
          private String name;
          // 作者主页链接
          private String url;
          // 作者邮箱
          private String email;
          // 版本号
          private String version;
          // 分组名称
          private String groupName;
          // 文档标题
          private String title;
          //文档描述
          private String description;
          // 组织地址
          private String termsOfServiceUrl;
          // 许可证
          private String license;
          // 许可链接
          private String licenseUrl;
      }
      
      • 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
    • 注入配置类,配置swagger

      @Configuration
      @EnableConfigurationProperties(SwaggerProperties.class)
      public class SwaggerConfig {
      
          @Autowired
          private SwaggerProperties swaggerProperties;
      
          /**
           * 配置swagger中的标题,描述,联系人,联系方法...
           */
          public ApiInfo getApiInfo(){
              //创建联系人对象
              Contact contact = new Contact(swaggerProperties.getName(), swaggerProperties.getUrl(), swaggerProperties.getEmail());
              return new ApiInfoBuilder()
                      .contact(contact)
                      .title(swaggerProperties.getTitle())
                      .description(swaggerProperties.getDescription())
                      .version(swaggerProperties.getVersion())
                      .license(swaggerProperties.getLicense())
                      .licenseUrl(swaggerProperties.getLicenseUrl())
                      .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
                      .build();
          }
      
          /**
           * swagger的配置,基础信息,设置接口路径等等
           * RequestHandlerSelectors.basePackage()通过指定基础包来生成文档
           * RequestHandlerSelectors.withMethodAnnotation()通过指定的方法上注解来实现生成文档
           */
          @Bean
          public Docket docket(){
              return new Docket(DocumentationType.OAS_30)
                      .apiInfo(getApiInfo())
                      .select()
                      //文档的生成的位置,两种方式
                      // .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
                      .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                      .paths(PathSelectors.any())
                      .build();
          }
      }
      
      • 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
    • 实体

      @Data
      @ApiModel("学生实体")
      public class Student {
      
          @ApiModelProperty("学生编号")
          private Integer id;
          @ApiModelProperty("学生姓名")
          private String name;
          @ApiModelProperty("学生住址")
          private String address;
          @ApiModelProperty("出生日期")
          private Date birthday;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    • Controller

      • 配置对类的描述注解

      • 配置对方法的描述的注解

      • 对参数的注解

        @RestController
        @RequestMapping("/student")
        public class StudentController {
        
            @ApiOperation("分页+条件查询 学生信息")
            @ApiImplicitParams({
                    @ApiImplicitParam(name = "pageNumber", value = "当前页码", required = false, dataType = "Integer",defaultValue = "1", paramType = "query"),
                    @ApiImplicitParam(name = "pageSize", value = "每页条数", required = false, dataType = "Integer",defaultValue = "10", paramType = "query")
            })
            @ApiResponses({
                    @ApiResponse(code = 0, message = "成功"),
                    @ApiResponse(code = -1, message = "失败")
            })
            @GetMapping("/page")
            public Result page(@RequestParam(value = "pageNumber",defaultValue = "1") Integer pagerNumber,
                               @RequestParam(value = "pageSize",defaultValue = "5") Integer pageSize,
                               Student student) {
                System.out.println(pagerNumber);
                System.out.println(pageSize);
                System.out.println(student);
                return Result.success();
            }
        
            @GetMapping("/get/{id}")
            @ApiOperation("根据ID获取学生信息")
            @ApiImplicitParam(name="id",value = "学生编号",required = true, dataType="Integer", paramType = "path")
            public Result get(@PathVariable("id") Integer id) {
                System.out.println(id);
                return Result.success();
            }
        
            @PutMapping("/edit")
            @ApiOperation("编辑学生信息")
            public Result edit(@RequestBody Student student){
                System.out.println(student);
                return Result.success();
            }
        
            @DeleteMapping("/remove/{id}")
            @ApiOperation("根据编号删除学生信息")
            @ApiImplicitParam(name = "id", value = "学生编号", required = true, dataType = "Integer", paramType = "path")
            public Result remove(@PathVariable("id") Integer id){
                System.out.println(id);
                return Result.success();
            }
        }
        
        • 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
    • 查看swagger页面

      #测试访问文档页面:http://localhost:8080/swagger-ui/index.html
      
      • 1

    其他功能

    spring boot 异步

    • 异步调用需要配置注解@Async

    • 启动类 开启异步调用

      //开启异步调用
      @EnableAsync
      
      • 1
      • 2
    • 案例:统计耗时

      @Service
      public class AsyncService {
      
          /**
           * 异步调用注解
           * 在处理请求的业务时,其中核心业务必须在同步处理中完成
           *                  辅助业务可以在异步处理中完成
           */
          @Async
          public void task1(){
              try {
                  long start = System.currentTimeMillis();
                  //模拟程序执行耗时
                  Thread.sleep(1000);
                  long end = System.currentTimeMillis();
                  System.out.println("task1耗时:" + (end - start) + "毫秒");
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
      
          @Async
          public void task2(){
              try {
                  long start = System.currentTimeMillis();
                  //模拟程序执行耗时
                  Thread.sleep(2000);
                  long end = System.currentTimeMillis();
                  System.out.println("task2耗时:" + (end - start) + "毫秒");
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
      
          @Async
          public void task3(){
              try {
                  long start = System.currentTimeMillis();
                  //模拟程序执行耗时
                  Thread.sleep(3000);
                  long end = System.currentTimeMillis();
                  System.out.println("task3耗时:" + (end - start) + "毫秒");
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
      }
      
      • 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
      @RestController
      public class AsyncController {
      
          @Autowired
          private AsyncService asyncService;
      
          @GetMapping("/doAsync")
          public Map<String, Object> doAsync(){
              long start = System.currentTimeMillis();
              //调用service中的三个任务方法
              //同步:第一个方法完成之后才能调用第二方法...耗时:三个方法时间相加
              //异步:三个方法仅调用,不再登录方法执行完毕,即可向下执行
              asyncService.task1();
              asyncService.task2();
              asyncService.task3();
      
              Map<String, Object> map = new HashMap<>();
              long end = System.currentTimeMillis();
              map.put("code", 200);
              map.put("message", "调用方法成功,总耗时为" + (end-start) + "毫秒");
              return map;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23

    定时任务

    • 在启动类上开启定时任务

      //开启定时任务
      @EnableScheduling
      
      • 1
      • 2
    • service 定时任务注解

    • 定时表达式

      @Service
      public class JobService {
          /**
           * @Scheduled
           * 定时任务注解
           * cron配置项,为定时表达式
           * 秒 分 时 日 月 周 年(可选)
           * *星号:表示每,每秒、每分、每时...
           * ?问好:只能在日和周两个位置出现,排除冲突
           * -中划线:表示一个范围
           * ,逗号:表示一个列表值,比如在星期中使用1,2,4
           */
          // @Scheduled(cron = "* * * ? * 1-5")
          @Scheduled(cron = "0/5 * * ? * 1-5")
          public void myJob(){
              System.out.println("定时任务...");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18

    邮件

    • io中的 java mail … 依赖

      <dependency>
          <groupId>org.springframework.bootgroupId>
          <artifactId>spring-boot-starter-mailartifactId>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
    • 开启邮箱pop3的服务,写配置文件

      spring:
        mail:
          #邮箱服务器地址     qq:smtp.qq.com    网易163:smtp.163.com
          host: smtp.qq.com
          #授权码,邮箱-》设置-》账户-》POP3/AMTP服务,开启服务后会获得授权码
          password: xxxxxceoibdaaaaa
          username: 11118422@qq.com
          default-encoding: UTF-8
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 发送简单的内容

      @Autowired
      private JavaMailSender javaMailSender;
      
      /**
       * 发送基本的内容(纯文本)
       */
      @Test
      void testSend() {
          SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
          //发件人
          simpleMailMessage.setFrom("11112342@qq.com");
          //收件人
          simpleMailMessage.setTo("22212342@qq.com");
          //主题
          simpleMailMessage.setSubject("这是一个测试邮件20220812");
          //邮件内容
          simpleMailMessage.setText("测试内容2022-08-12");
          javaMailSender.send(simpleMailMessage);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    • 发送邮件工具类

      • 添加文件
      • 添加附件
      /**
       * 测试发送复杂内容,例如图片和附件等
       */
      @Test
      void testSend2() throws MessagingException {
          MimeMessage mimeMessage = javaMailSender.createMimeMessage();
          // 创建一个邮件工具,可以发送附件
          MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage,true,"utf-8");
          mimeMessageHelper.setFrom("28718422@qq.com");
          mimeMessageHelper.setTo("28718422@qq.com");
          mimeMessage.setSubject("这是一个携带了图片和附件的邮件20220812");
          //拼接内容参数
          StringBuilder sb = new StringBuilder();
          sb.append("  

      springboot 测试邮件发送复杂格式o

      "
      ); sb.append("

      哈哈哈

      "
      ); sb.append("

      居中

      "
      ); sb.append(" "); //如果要插入图片src='cid:picture' //设置内容,可以被html解析 mimeMessageHelper.setText(sb.toString(), true); // 从本地磁盘中读取到图片 站位到内容中去 mimeMessageHelper.addInline("picture",new File("C:\\Users\\NINGMEI\\Desktop\\aaa\\ddd.jpg")); // 添加附件 mimeMessageHelper.addAttachment("SpringBoot.doc",new File("D:\\course\\05-SpringBoot\\springboot\\document\\SpringBoot.doc")); javaMailSender.send(mimeMessage); }
      • 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
  • 相关阅读:
    mybatis03
    UE 视差材质 学习笔记
    ssm+vue的软考系统(有报告)。Javaee项目,ssm vue前后端分离项目。
    .NET 6应用程序适配国产银河麒麟V10系统随记
    花 1 万块做付费咨询,值得吗?
    awk命令应用
    C++11新特性③ | 可变参数模板介绍
    CRM系统的功能有哪些?
    Django笔记二十九之中间件介绍及使用示例
    Windows Server 2012 R2系统服务器远程桌面服务多用户登录配置分享
  • 原文地址:https://blog.csdn.net/qq_43528471/article/details/126591827