Spring Boot 应用开发基本模板

本文主要介绍 Spring Boot 开发过程使用到的一些组件,帮助开发人员快速搭建基础开发框架。

1. 配置日志相关

1.1 日志级别 Level

日志的行为等级分为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL

Log4j 建议只使用四个级别,优先级从高到低依次是:ERROR、WARN、INFO、DEBUG。

1.2 配置示例

1. 配置 application.yml,指定 logback.xml 的详细地址。

logging:
  config: classpath:logback-config.xml

2. 配置 logback-config.xml,在配置文件中指定日志的打印级别,日志文件的存储路径等日志相关信息。

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds"
    debug="false">
    <property name="log.path" value="/project/logs/" />
    <!--输出到控制台 -->
    <appender name="console"
        class="ch.qos.logback.core.ConsoleAppender">
        <!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>ERROR</level> 
            </filter> -->
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!--输出到文件 -->
    <appender name="file"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}${log.file}</file>
<!--         <rollingPolicy -->
<!--             class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> -->
<!--             <fileNamePattern>${log.path}deepev.%d{yyyy-MM-dd_HH-mm}.log -->
<!--             </fileNamePattern> -->
<!--             <maxHistory>30</maxHistory> -->
<!--             <totalSizeCap>1GB</totalSizeCap> -->
<!--         </rollingPolicy> -->

        <!-- 滚动策略 日期+大小 策略 -->
        <rollingPolicy
            class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${log.path}deepev.%d{yyyy-MM-dd}.log-%i.zip</fileNamePattern>
            <!-- 单个日志大小 -->
            <maxFileSize>30MB</maxFileSize>
            <!-- 日志保存周期 -->
            <maxHistory>30</maxHistory>
            <!-- 总大小 -->
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>

        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="warn">
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </root>
    <!-- 指定业务包-->
    <logger name="com.**" level="INFO" additivity="false">
        <appender-ref ref="console" />
        <appender-ref ref="file" />
    </logger>

</configuration>

1.3 配置示例详解

根据上边的 logback-config.xml 文件,对 Logback 的相关配置进行详细讲解。

1. 根节点<configuration> 有三个属性,scan、scanPeriod 和 debug。

  • scan 值为 true 或 false,用于监控配置文件,如果文件发生改变后,将会被重新加载,此属性默认为 true。
  • scanPeriod 是时间间隔,是用来设置监测配置文件是否有修改,默认的时间单位是毫秒,只有 scan 设置为 true 时,此属性才会生效。
  • debug 此属性值为 true 或者 false,用于控制是否打印出 Logback 内部日志信息,设置为 true 时,可以通过 Logback 的内部日志,实时查看 Logback 运行状态。默认值为 false。

2. <appender> 节点是负责写日志的组件,有两个必须的属性,分别是 name 和 class,name 用于指定 appender 组件的名称,class 是 appender 组件的策略。

这里介绍一下 appender 的常用的组件:

  • ConsoleAppender 控制台组件,该组件是把日志输出到控制台上。上边示例中的 name=“console” 的组件就是这种策略。console 组件中的 <encoder> 部分是用来格式化日志格式的。
  • FileAppender 文件组件,该组件是把日志输出到文档中去。
    • <file>info.log</file>:指定日志被写入的文件的地址,该地址可以是相对目录,也可以是绝对目录。指定的目录如果不存在的话,会自动创建。
    • <append>true</append>:文件的写入类型,true 的话新生成的日志会追加到文件的结尾,如果为 false,则清空现有的文件。默认值为 true。
  • RollingFileAppender 滚动记录文件组件,该组件与 FileAppender 相比,增加了 rollingPolicy 属性,是对日志滚动处理时,指定对文件复制和重命名时的滚动的策略。

常用策略有三种:

  • ch.qos.logback.core.rolling.TimeBasedRollingPolicy:根据时间来制定滚动策略。
  • ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy:查看当前日志文件的大小,当超过指定大小时,会告知 RollingFileAppender,触发当前日志文件滚动。
  • ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy: 根据日期和大小同时确定滚动策略。

3. <logger> 节点:用来设置某一个包或具体的某一个类的日志打印级别、以及指定<appender>。在 logger 节点下可以包含零个或多个<appender-ref> 元素,ref 值用于标识 appender 的 name,并添加到这个 logger 中。上面的示例中,添加了两个 appender-ref,分别指定 file。

4. <root>节点,它是根 logger,是所有 logger 的上级,只有一个 level 的属性,用于指定日志等级。

2. 集成 Swagger,生成接口文档

Swagger 2

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。

2.1 添加依赖

这里我添加了两个 UI,springfox-swagger-ui 是官方提供的,swagger-bootstrap-ui 是第三方封装的,我平时更习惯使用第三方 UI。

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>1.9.1</version>
</dependency>

2.2 application.yml 中添加开关

Swagger 只能在开发环境使用,部署生产环境时要关闭,为了方便管理,在配置文件中添加开关。

swagger:
  enable: true

2.3 编写 Swagger 配置类

在该配置类中,可以配置 API 文档中的显示信息,通过全局配置,可以为所有的 API 接口添加通用条件。

下面的示例中为所有的接口添加 token 公共配置的方法。

package com.**.**.conf;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Value("${swagger.enable}")
    private boolean enableSwagger;

    @Bean
    public Docket docket(){
        List<Parameter> params = getParam();
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).enable(enableSwagger).select()
                //当前包路径
                .apis(RequestHandlerSelectors.basePackage("com.reach.usercenter"))
                .paths(PathSelectors.any())
                .build()
//                .securitySchemes(security()).securityContexts(securityContexts()); //添加全局 token
                .globalOperationParameters(params);//在每一个接口上添加 token
    }

    private List<Parameter> getParam(){
        ParameterBuilder ticketPar = new ParameterBuilder();
        List<Parameter> pars = new ArrayList<Parameter>();
        ticketPar.name("Authorization").description("user ticket")//Token 以及 Authorization 为自定义的参数,session 保存的名字是哪个就可以写成那个
                .modelRef(new ModelRef("string")).parameterType("header")
                .required(true).build(); //header 中的 ticket 参数非必填,传空也可以
        pars.add(ticketPar.build());    //根据每个方法名也知道当前方法在设置什么参数
        return pars;
    }

    private List<SecurityContext> securityContexts() {
        List<SecurityContext> securityContexts=new ArrayList<>();
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .forPaths(PathSelectors.regex("^(?!auth).*$"))
                        .build());
        return securityContexts;
    }
    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences=new ArrayList<>();
        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        return securityReferences;
    }

    private List<ApiKey> security() {
        ApiKey key = new ApiKey("Authorization", "Authorization ", "header");
        List<ApiKey> list = new ArrayList();
        list.add(key);
        return list;
    }

    //构建 api 文档的详细信息函数
    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .title("EV DATA RESTful API")
                .version("1.0")
                .description("API 描述")
                .build();
    }
}

3. 配置文件敏感信息加密

在开发的服务中,为了安全考虑,有一些信息是必须要进行加密处理的,比如数据库的密码等信息,开发环境和测试环境还好说,但是生产环境必须要保证信息安全。Jasypt 是一个通用的加密库,我们可以使用 Jasypt 对配置文件中的敏感信息进行加密处理。

3.1 添加依赖

<!-- https://mvnrepository.com/artifact/com.github.ulisesbocchio/jasypt-spring-boot-starter -->
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.2</version>
</dependency>

3.2 application.yml 配置

#配置文件项加解密密码,此处是开发环境,实际生产中应该注销,使用启动参数的方式传入
jasypt:
  encryptor:
    password: testtest

spring:
  datasource:
    url: jdbc:......
    username: root
    password: ENC(0RVCs2UAXrb8cWsMk8tJuE6XXMuKZxAHRJ1yP9dA4jdY1MU1jKJumLyVUiF0yvuD)

    ......

3.3 Jasypt 使用测试

通过上边的配置以后,我们就完成了对数据库密码的加密工作,Spring Boot 已经可以正常启动了。更为详细的配置可以参考一下网站:

下边是 Jasypt 的测试例子,实现对信息的加密和解密处理。

package com.**;

import org.jasypt.encryption.StringEncryptor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class UserEncryptorTest {

    @Autowired
    private StringEncryptor stringEncryptor;

    //加密
    @Test
    public void encrypt() {
        System.out.println("testtest 的密文为:"+    stringEncryptor.encrypt("testtest"));
    }

    //解密
    @Test
    public void decrypt() {
        System.out.println("解密结果为:"+stringEncryptor.decrypt("+VZcKfSsRgHuXnosbV55R8elvOHMEoThfgKX+ujJDp0pzMeZLZLK3yrcFWPn2iiO"));
    }

}

//输出结果
//testtest 的密文为:+VZcKfSsRgHuXnosbV55R8elvOHMEoThfgKX+ujJDp0pzMeZLZLK3yrcFWPn2iiO
//解密结果为:testtest

4. 数据源配置

这里使用 MySQL 数据库,使用 JDBC 和 JPA 操作数据库。

4.1 添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

还有 82% 的精彩内容
©著作权归作者所有,转载或内容合作请联系作者
支付 ¥9.99 继续阅读
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容