SpringBoot手册学习(三)SringBoot集成工具

SpringBoot 集成工具

  1. 开发者工具Devtools-自动重启:

    SpringBoot提供了一些开发者工具集用于提升开发应用的体验,如spring-boot-devtools工具,加载此模块可以为项目提供development-time特性,实现项目修改后不需要重新启动服务器就可自动热加载重启,唯一触发重启的方式是更新classpath,不同的IDE引起classpath更新的方式不同,如Eclipse里保存修改文件,而IEDA中需要构建工程(Build-Build Project)

    1. 添加devtools工具

      1
      2
      3
      4
      5
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <optional>true</optional>
      </dependency>
    2. 在IDEA中启动服务器后,修改文件可通过Build Project重新构建项目即可实现热加载更新

  1. 集成Swagger工具:

    由于现在WEB开发采取的模式基本都是前后端分离模式,因此交互十分重要,前后端交互的唯一方式变成了API接口,而Swagger框架定义了API文档接口的形式,不仅使后端可以直接在程序中书写API接口,还可以使前端可以直接在系统中查看最新的接口版本、测试接口

    1. 添加Swagger依赖:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      <!--Swagger依赖-->
      <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger2</artifactId>
      <version>2.2.2</version>
      </dependency>
      <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger-ui</artifactId>
      <version>2.2.2</version>
      </dependency>
    2. Swagger配置:在src/main/java/…/下创建conf包并在其下创建配置类如SwaggerConfig

      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
      package top.harviealwayshere.demo.conf;

      @Configuration
      @EnableSwagger2
      public class SwaggerConfig {

      //API页面展示数据相关信息
      private ApiInfo apiInfo(){
      return new ApiInfoBuilder()
      .title("API测试接口文档")
      .description("基于SpringBoot的Swagger搭建的API接口可视化测试平台")
      .contact("harvie")
      .version("1.0")
      .build();
      }

      @SuppressWarnings("unchecked")
      @Bean
      public Docket createRestApi(){
      //自定义异常信息
      ArrayList<ResponseMessage> responseMessages = new ArrayList<ResponseMessage>() {{
      add(new ResponseMessageBuilder().code(200).message("成功").build());
      add(new ResponseMessageBuilder().code(400).message("请求参数错误").responseModel(new ModelRef("Error")).build());
      add(new ResponseMessageBuilder().code(401).message("权限认证失败").responseModel(new ModelRef("Error")).build());
      add(new ResponseMessageBuilder().code(403).message("请求资源不可用").responseModel(new ModelRef("Error")).build());
      add(new ResponseMessageBuilder().code(404).message("请求资源不存在").responseModel(new ModelRef("Error")).build());
      add(new ResponseMessageBuilder().code(409).message("请求资源冲突").responseModel(new ModelRef("Error")).build());
      add(new ResponseMessageBuilder().code(415).message("请求格式错误").responseModel(new ModelRef("Error")).build());
      add(new ResponseMessageBuilder().code(423).message("请求资源被锁定").responseModel(new ModelRef("Error")).build());
      add(new ResponseMessageBuilder().code(500).message("服务器内部错误").responseModel(new ModelRef("Error")).build());
      add(new ResponseMessageBuilder().code(501).message("请求方法不存在").responseModel(new ModelRef("Error")).build());
      add(new ResponseMessageBuilder().code(503).message("服务暂时不可用").responseModel(new ModelRef("Error")).build());
      add(new ResponseMessageBuilder().code(-1).message("未知异常").responseModel(new ModelRef("Error")).build());
      }};
      return new Docket(DocumentationType.SWAGGER_2)
      .apiInfo(apiInfo())
      .groupName("demo")
      .genericModelSubstitutes(DeferredResult.class)
      .useDefaultResponseMessages(false) //使用自定义异常信息
      .globalResponseMessage(RequestMethod.GET, responseMessages)
      .globalResponseMessage(RequestMethod.POST, responseMessages)
      .globalResponseMessage(RequestMethod.PUT, responseMessages)
      .globalResponseMessage(RequestMethod.DELETE, responseMessages)
      .forCodeGeneration(true)
      .select()
      .paths(Predicates.or(PathSelectors.regex("/api/.*"))) //拦截的controller中的请求格式
      .build();
      }

      }
    3. 在controller中编辑Api接口信息

      1. 类名描述:Controller类接口描述

        1
        @Api(value="DemoController",description = "测试接口DemoController")
      2. 方法名描述:

        1
        @ApiOperation(value="/demo接口",notes="测试demo接口的notes")
      3. 方法参数描述:

        1
        @ApiParam(required = true,name="name",value = "姓名") @RequestParam("name") String name
  1. Logging日志系统:

    1. 日志格式解析:日期时间-日志级别-进程ID-[线程名]-日志名(源class类名)-日志信息

    2. 日志系统配置:可在application.properties中配置日志相关参数

      1. 日志级别:通过设置logging.level.*=“LEVEL”来配置不同模块的日志以不同的日志级别输出,一般日志级别从低到高有ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF

        1
        2
        3
        4
        5
        6
        #root日志以WARN级别输出
        logging.level.root=WARN
        #springframework.web日志以DEBUG级别输出
        logging.level.org.springframework.web=DEBUG
        #hibernate日志以ERROR级别输出
        logging.level.org.hibernate=ERROR
      2. 日志输出文件:可以通过设置logging.file或者logging.path属性默认记录ERROR+WARN+INFO级别的日志记录写入文件中

        | logging.file | logging.path | value | 描述 |
        | ———— | ———— | ———- | —————————— |
        | 无设置 | 无设置 | | 记录到控制台 |
        | 设置 | 无设置 | log/my.log | 写到特定目录的特定文件名中 |
        | 无设置 | 设置 | var/log | 写到特定目录的spring.log文件中 |

      3. 日志高级配置:若要设定更高级的日志配置需要使用logging.config指定相应的日志配置文件或者使用相应的*-spring.xml配置文件让SpringBoot帮我们自动配置,这里我们采用log4j2日志系统来进行系统日志配置

        1. 加载log4j2依赖:由于在spring-boot-starter中集成了logback日志系统依赖,我们需要先去除logback依赖再加载log4j2依赖

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter</artifactId>
          <!--去除logback依赖-->
          <exclusions>
          <exclusion>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-logging</artifactId>
          </exclusion>
          </exclusions>
          </dependency>
          <!--加载log4j2依赖-->
          <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-log4j2</artifactId>
          <version>2.0.0.RELEASE</version>
          </dependency>
        2. 配置log4j2配置文件:命名配置文件为log4j2-spring.xml(SpringBoot自动加载)或者自定义配置文件名称但是需要在application.properties里配置logging.config选项

          1
          logging.config=classpath:log4j2.xml
        3. 编写log4j2配置文件:

          简单的log4j2配置文件

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          <?xml version="1.0" encoding="UTF-8"?>
          <!--配置根节点 属性:status-打印日志级别 monitorinterval-监测自动重新配置时间 单位秒-->
          <Configuration>
          <!--日志输出方式组件-->
          <!--通常有Console File RollingFile节点-->
          <!--还有Socket远程服务器输出 Async中转输出至别的Appender-->
          <Appenders>
          <!--Console控制台输出节点-->
          <Console name="Console" target="SYSTEM_OUT">
          <!--输出消息规则-->
          <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
          </Console>
          </Appenders>
          <!--指定日志输出级别和输出方式的组件 通常有Root Logger节点-->
          <Loggers>
          <!--指定特定的包/类使用的日志级别-->
          <Logger name="com.example" level="INFO"/>
          <!--指定所有包/类默认使用的日志级别-->
          <Root level="WARN">
          <!--指定日志输出到哪个Appender-->
          <AppenderRef ref="Console"/>
          </Root>
          </Loggers>
          </Configuration>

          较完整的log4j2配置文件

          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
          <?xml version="1.0" encoding="UTF-8"?>
          <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
          <!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
          <!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
          <configuration status="WARN" monitorInterval="30">
          <!--先定义所有的appender-->
          <appenders>
          <!--控制台输出配置-->
          <console name="Console" target="SYSTEM_OUT">
          <!--输出日志的格式-->
          <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
          </console>

          <!--文件输出,这个log每次运行程序会自动清空,由append属性决定,适合临时测试使用-->
          <File name="log" fileName="testLog/test.log" append="false">
          <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
          </File>

          <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
          <RollingFile name="RollingFileInfo" fileName="infoLogs/info.log"
          filePattern="infoLogs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
          <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
          <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
          <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
          <Policies>
          <TimeBasedTriggeringPolicy/>
          <SizeBasedTriggeringPolicy size="100 MB"/>
          </Policies>
          </RollingFile>

          <RollingFile name="RollingFileWarn" fileName="warnLogs/warn.log"
          filePattern="warnLogs/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
          <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
          <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
          <Policies>
          <TimeBasedTriggeringPolicy/>
          <SizeBasedTriggeringPolicy size="100 MB"/>
          </Policies>
          <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
          <DefaultRolloverStrategy max="20"/>
          </RollingFile>

          <RollingFile name="RollingFileError" fileName="errorLogs/error.log"
          filePattern="errorLogs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
          <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
          <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
          <Policies>
          <TimeBasedTriggeringPolicy/>
          <SizeBasedTriggeringPolicy size="100 MB"/>
          </Policies>
          </RollingFile>
          </appenders>

          <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
          <loggers>
          <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
          <logger name="org.springframework" level="INFO"></logger>
          <!--<logger name="org.mybatis" level="INFO"></logger>-->
          <root level="all">
          <appender-ref ref="Console"/>
          <appender-ref ref="log"/>
          <appender-ref ref="RollingFileInfo"/>
          <appender-ref ref="RollingFileWarn"/>
          <appender-ref ref="RollingFileError"/>
          </root>
          </loggers>
          </configuration>
        4. 使用log自定义输出日志:

          1
          2
          3
          4
          5
          6
          7
          8
          //在类中定义log工具变量
          private static Logger log = LogManager.getLogger(DemoController.class);
          //在方法中可以使用log.日志level(String)输出对应级别的日志
          log.trace("trace");
          log.debug("debug");
          log.info("info");
          log.warn("warn");
          log.error("error");