SpringBoot实用技巧

多环境配置文件

spring mvc项目中有一种方式是通过maven中的profile去激活插件放不同的配置文件打包,样例,里面有5个分支, master分支就是SSM项目支持maven激活环境配置的实现

Spring Boot提供了更优雅的方案

spring:
  profiles:
    active: dev
...
---
spring:
  profiles: dev
...
---
spring:
  profiles: prod
...

通过这种方式来激活不同环境的配置,线上启动的时候可以用java -jar xxx.jar -spring.profiles.active=xxx来指定使用什么环境,或者xxx.jar start -spring.profiles.active=xxx,jar自启动需要额外配置,不建议使用

配置加密

通常数据库的用户名,密码都需要额外加密,我个人喜欢用jasypt-spring-boot-starter来对关键配置加密

具体使用方法首先配置文件中加这么一段:

jasypt:
  encryptor:
    password: RjY2RDgyMzU3NDY*****************QzB3MDA=
    property:
      prefix: "ENC("
      suffix: ")"

其中password表示加密的密钥,prefixsuffix就表示加密开始和结束后面会用到

然后要用这个密钥计算出账号密码加密后的值,可以本地控制台跑,也可以通过junit test来跑:

    public static void main(String[] args) {
        BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
        //加密所需的salt(盐)
        textEncryptor.setPassword("RjY2RDgyMzU3NDY*****************QzB3MDA=");
        //要加密的数据(数据库的用户名或密码)
        String username = textEncryptor.encrypt("root");
        String password = textEncryptor.encrypt("12345678");
        System.out.println("username:" + username);
        System.out.println("password:" + password);
    }

这个账号密码同样root,每次计算都是不一样的值,很有意思的算法
然后配置datasource的时候就可以用加密后的值来配:

spring:
  datasource:
    hikari:
      username: ENC(cKLR2CaV**************1yNDA)
      password: ENC(ckbTZkh53******************YbkpZ9YDk=)
    url: jdbc:mysql://******************

这样就可以了,但你会发现这个密钥在配置文件中,不配还不行,那还是不够安全,可以在启动过程中通过java -jar xxx.jar -jasypt.encryptor.password=RjY2RDgyMzU3NDY*****************QzB3MDA=的方式来配进去

如果还是不放心,那写到系统profile中,然后通过java -jar xxx.jar -jasypt.encryptor.password='$echo jasypt.encryptor.password'来取出来,部署全流程不携带密码,启动的时候才在后台把密钥填进去,这种安全级别一般中型公司都能满足,唯一的问题就是需要一个可信的运维人员来保管密码

优化配置

我们编写application.yml时都有各种提醒,告诉你都有什么配置项,那这个是怎么做到的,我们自己能不能写出来一个工具,让Springboot引入时能够提醒你的配置文件呢?

想要实现这点,首先要引入一个依赖:

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

这个依赖作用就是分析additional-spring-configuration-metadata.json文件,并生成对应的提醒到applicaiton.yml里,这个文件的位置在resources/META-INF/additional-spring-configuration-metadata.json (需要自己创建路径和文件),

具体如何配置,参考官网文档
给出我的例子:

{
  "groups": [
    {
      "name": "spring.el-util",
      "type": "com.el.utils.auto.configuration.ElApplicationConfiguration",
      "sourceType": "com.el.utils.auto.configuration.ElApplicationConfiguration"
    }
  ],
  "properties": [
    {
      "name": "spring.el-util.enable-auto-config",
      "type": "java.lang.Boolean",
      "sourceType": "com.el.utils.auto.configuration.ElApplicationConfiguration",
      "defaultValue": false
    }
  ],
  "hints": [
    {
      "name": "spring.el-util.enable-auto-config",
      /* 该配置的可选项 true和false */
      "values": [
        {
          "value": true,
          "description": "开启."
        },
        {
          "value": false,
          "description": "关闭."
        }
      ]
    }
  ]
}

配置好运行一下,让configuration-processor解析一下你的json配置,就会有这样的提示了,同理,你开发的二方包或三方包都可以用这种方式去写配置,配默认值等等,因为自己可能会有多个二方包,都依赖这个版本可能会有冲突,最好是让引用方去提供这个依赖

效果如下:
在这里插入图片描述

自动配置

首先抛出一个问题,为什么有些包引入后只要配置了,就可以自动把核心Bean注入到容器中,例如jdbc包,只要maven依赖引入了,如果没配置jdbc url这些就会报错,配置了就能在项目中直接使用了?

OK,SpringBoot约定大于配置,那一定是在什么地方有约定,spring和工具包提供商有约定,在什么地方告诉我需要把那些Bean加入到IOC容器中,在Bean初始化的过程中就会对配置进行一些校验。

那么思路清晰了之后,来看下具体时怎么实现的,通过观察,发现springboot项目的依赖库中有一个spring-boot-autoconfigure-2.2.2.RELEASE.jar, 这个依赖中 META-INF/spring.factories大概长这个样子:
在这里插入图片描述在这里插入图片描述
这里看到jdbc相关的配置在org.springframework.boot.autoconfigure.EnableAutoConfiguration有约定,DataSourceAutoConfiguration,那这个类这个样子:
在这里插入图片描述
终于看到真相了,在官方autoconfig包中,有大量的初始化声明,springboot启动过程中回去挨个找,进去之后由条件注解做判断,如果符合某些条件,就自动搭建好对应的环境,如果搭建过程中缺少必要参数就报错,例如jdbc url缺失。

那看起来好像是官方约定的,我们没法改官方autoconfig包的样子,其实只要我们在resources/META-INF下新建一个spring.factories文件,自己写个org.springframework.boot.autoconfigure.EnableAutoConfiguration=即可,就相当于spring启动时会加载你这个类,具体做什么,需不需要条件,看你自己这个类怎么实现。

全局异常

现在大多数开发者都喜欢自定义异常体系,这样灵活,每个异常符合业务,不会跨业务线错误的拦截到其他人的异常,不过会带来一个问题,只拦截自己的异常,那真的出现NPE这种系统程序抛出的异常怎么处理,不会是每个接口外都要做一次try-catch

/**
 * @author eddie
 * @description 全局异常处理类
 */
@Slf4j
@RestControllerAdvice
public class GlobalDefaultExceptionHandler {

    @ExceptionHandler(Exception.class)
    public Response defaultExceptionHandler(HttpServletRequest request, Exception e) {
        if (e instanceof NullPointerException) {
            log.error("NPE系统异常:{}", e.getMessage());
            return new Response(Constants.STATE_FAIL, e.getMessage(), "失败");
        }
        log.error("全局拦截器截获异常", e);
        return new Response(Constants.STATE_FAIL, "系统异常", null);
    }

}

可以这样单独做一个处理器来处理异常,这个就相当于请求结束回到客户端过程的拦截器,如果发现携带异常,就会抓过来,那我们处理通过instanceof或者自定义异常里面的内容就可以处理所有异常了,最后来一个兜底,保证不会把错误信息透露给外面,除非是我们希望外界知道的错误。

以上就是SpringBoot的一些技巧,还有一些不知道算不算技巧,也是太晚了,等以后有机会再续实用技巧时再聊吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你向着阳光奔跑的背影

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值