暂时未有相关云产品技术能力~
现任技术部负责人,架构师。 博客地址:https://blog.minbox.org
`MongoDB`在企业级项目中一般用于存储文档信息、图片资源等,`MongoDB`的内容完全是以 `JSON`字符串的形式进行存储的,所以我们在获取数据时通过简单的 `反序列化`就可以完成与项目内的实体类转换,不过这个过程是自动的,不需要我们手动进行反序列化处理。
在之前项目中我们想要读取`MongoDB`内的内容需要使用`MongoDBTemplate`来完成数据的`CRUD`,那如果我们想要通过`RestController`的形式获取`MongoDB`内的数据就更麻烦了,还需要自行去创建对应的控制器,然后使用`MongoDBTemplate`从`MongoDB`内读取出数据后返回给前端。
`Spring Cloud Gateway`可以根据配置的`断言、谓语`进行满足条件转发,也可以自动同步`服务注册中心`的服务列表进行指定`serviceId`前缀进行转发,这里的`serviceId`是业务服务的`spring.application.name`配置参数。
`Spring`在因`Netflix`开源流产事件后,在不断的更换`Netflix`相关的组件,比如:`Eureka`、`Zuul`、`Feign`、`Ribbon`等,`Zuul`的替代产品就是`SpringCloud Gateway`,这是`Spring`团队研发的网关组件,可以实现限流、安全认证、支持长连接等新特性。
在之前的章节中,我们并没有对`SpringCloud Alibaba Nacos Config`的`NameSpace`、`Group`做过修改,都是使用的默认值,默认值分别是:`Public`、`DEFAULT_GROUP`,我们本章来看下如何自定义这两项参数。
读取`Profile`多环境下`Nacos Config`的配置信息,了解多环境下相同的配置优先级加载问题。
用户请求的转发是接口服务在部署时必须要做的一步。
`ApiBoot Logging`支持整合`服务注册中心`(Eureka、Consul、Nacos Discovery、Zookeeper...)进行上报请求日志,`Logging Client`会从服务注册中心内找到指定`ServiceID`的`Logging Admin`具体可用实例,通过`SpringCloud Discovery`内部的负载均衡策略返回`Logging Admin`的部署`服务器IP`以及`端口号`,这样`Logging Client`就可以完成请求日志的上报流程。
`ApiBoot Logging`在上报日志时虽然是一般通过内网的形式部署,不过安全方面还是主要依赖于服务器的`安全策略`(防火墙),为了提高日志上报的安全性,`ApiBoot Logging`支持了整合`Spring Security`来使用`Basic Auth`的形式上传日志信息。
其实理解起来比较简单,类似于我们平时一直在使用的`logback`、`log4j`这种的日志框架的其中一个功能部分,`minbox-logging`分布式日志框架目前独立于`api-boot-plugins`,已经加入了`minbox-projects`开源组织,之前博客有一系列的文章来讲解了`ApiBoot Logging`(内部是集成的`minbox-logging`)日志组件的使用以及极简的配置方式,可以访问[ApiBoot 组件系列文章使用汇总](https://blog.minbox.org/apiboot-all-articles.html)了解日志组件的使用详情。
使用RestTempalte透传日志链路信息
`ApiBoot Logging`可以无缝整合`SpringCloud`来采集请求日志,目前支持`RestTemplate`、`Openfeign`两种方式,我们本章来讲解下在使用`Openfeign`完成服务之间请求相互调用的一条链路请求日志是否可以都采集到。
`ApiBoot Logging`会为每一个请求都对应创建链路编号(`TraceID`)以及单元编号(`SpanID`),用于归类每一次请求日志,通过一个链路下日志单元的`Parent SpanID`可以进行上下级关系的梳理。
`ApiBoot Logging`通过集成`minbox-logging`来进行管理每一次请求的日志信息,包含`头信息`、`参数`、`主体内容`、`路径`、发生的`服务器`相关信息等,根据接口的响应状态还可以记录响应的头信息、响应的内容以及发生异常时的`堆栈信息`。
`Spring`提供的原生的`OAuth2`依赖内置了几种比较常用的授权方式:`password`、`authorization-code`、`client_credentials`、`refresh_token`、`implicit`等,虽然可以满足我们日常的需求,不过针对一些特殊的需求还是捉襟见肘,有点无奈,比如:`微信登录`、`短信登录`...,针对这一点`ApiBoot`通过修改`Spring OAuth2`依赖的源码,可以根据业务进行自定义添加`grantType`。
`Spring`所提供的`OAuth2`集成策略,支持多种方式存储`认证信息`以及`客户端信息`,由于在之前的文章中讲解使用时把知识点进行了拆分,有很多同学不太会组合使用,很多单独问我`ApiBoot`所提供的`OAuth2`的整合后,多个客户端该怎么配置?
使用`Redis`来存储`OAuth2`相关的客户端信息以及生成的`AccessToken`是一个不错的选择,`Redis`与生俱来的的高效率、集群部署是比较出色的功能,如果用来作为`服务认证中心`的数据存储,可以大大的提高响应效率。
当我们整合了`Spring Security`以及`OAuth2`后发现,有一些业务请求是需要开放的,因为种种原因这时访问者还没有身份标识(`比如:用户刚来,还没有注册,需要进行新用户注册,这时注册业务相关的接口都应该是开放的`),下面我们来看看`ApiBoot`是怎么排除路径不进行权限拦截的。
接口服务的安全性一直是程序员比较注重的一个问题,成熟的安全框架也比较多,其中一个组合就是`Spring Security`与`OAuth2`的整合,在`ApiBoot`内通过代码的封装、自动化配置实现了自动化整合这两大安全框架。
`OAuth2`默认的`AccessToken`是由`DefaultAccessTokenConverter`生成,是具有唯一性的`UUID`随机字符串,我们如果想要使用`JWT`来格式化`AccessToken`就需要使用`JwtAccessTokenConverter`来进行格式化,当然如果你有自己独特的业务可以自己实现`AccessTokenConverter`接口,并将实现类交付给`IOC`托管即可。
`SpringSecurity`整合`OAuth2`是开发者公认的`资源保护`、`服务认证`的最佳搭配伙伴,这对好基友一直在默默的守护着应用服务的安全,根据访问者的不同角色可以颗粒度控制到具体的接口,从而实现权限的细微划分。
`ApiBoot Security`内部提供了**两种方式**进行读取需要认证的用户信息,在之前的文章中讲到过`ApiBoot Security`使用`内存方式(memory)`**不写一行代码**就可以实现用户的认证并获取`AccessToken`,那我们使用`JDBC`方式是不是也是这么的简单呢?
`Eureka`服务端的界面是可以自定义的,而且方式比较简单,下面我们来看下修改方式。
`Swagger2`作为侵入式文档中比较出色的一员,支持接口认证的在线调试肯定是不在话下的,当我们在调用`OAuth2`所保护的接口时,需要将有效的`AccessToken`作为请求`Header`内`Authorization`的值时,我们才拥有了访问权限,那么我们在使用`Swagger`在线调试时该设置`AccessToken`的值呢?
接口文档在前后分离的项目中是必不可少的一部分,文档的编写一直以来都是一件头疼的事情,写程序`不写注释`、`不写文档`这几乎是程序员的通病,`Swagger2`的产生给广大的程序员们带来了曙光,只需要在接口类或者接口的方法上添加注解配置,就可以实现文档效果,除了可以应用到`单体应用`,在`微服务架构中`也是可以使用的,只需要整合`zuul`就可以实现各个服务的文档整合。
BFF是(Backends For Frontends)单词的缩写,主要是用于服务前端的后台应用程序,来解决多访问终端业务耦合问题。
`Quartz`内部没有明确的任务类型的概念,在`ApiBoot`中对其进行封装后才确切的定义了这个概念,可以根据业务场景按需选择适合的任务类型来构建执行的任务。
`Quartz`是一款比较优秀的分布式任务调度框架,`ApiBoot`对其封装之前就有两种任务存储方式,分别是:`memory`(内存方式)、`jdbc`(数据库方式),不过我们需要编写一些繁琐的代码配置,`ApiBoot`实现了集成后,可快速应用到项目中
`Quartz`是一款优秀的任务调度框架,支持内存、JDBC的形式来存储未执行的任务列表,支持多个任务节点同时执行任务,支持任务漂移到不同的节点执行。
如果你想要使用`SpringBoot`构建的项目在启动后运行一些特定的代码,那么`CommandLineRunner`、`ApplicationRunner`都是很好的选择。
我们在编写前后分离项目时,前端的项目一般需要静态资源(`Image`、`CSS`、`JavaScript`...)来进行渲染界面,而如果我们对外采用依赖的方式提供使用时,我们的静态资源文件也应该放入打包文件内,这样才能更便捷的提供我们的功能,在我的开源分布式日志框架 [minbox-logging](https://gitee.com/minbox-projects/minbox-logging) 内提供了管理界面的功能,就是采用的这种方式实现,将静态资源以及**编译后**的`HTML`页面存放到`minbox-logging-admin-ui`依赖内,下面我们来看下具体的实现方式。
`SpringBoot`约定了配置文件,默认为`application.properties`,通过该文件可以修改很多默认的配置,当然我们还可以在该配置文件内添加自定义的配置,该文件通过`key=value`的形式进行配置。
`SpringBoot`提供了内部配置`application.yml`文件的方式来进行全局配置,还支持使用`profiles`来激活不同环境下使用不同的配置文件,而这种方式毕竟是已经打包完成了,因此存在一定的局限性,像数据库特殊敏感配置也可能存在泄露的风险,如何解决这种问题呢?我们来看看本章要讲到的外部配置的方式吧!!!
在`SpringFramework`编写过程中使用了大量的`Event/Listener`来做一些解耦的任务工作,当然在`SpringBoot`内同样也沿用了这一点,如果你看过我写的 [业务解耦利器Event/Listener](https://blog.minbox.org/spring-event-listener.html) ,你应该了解事件的发布都是由`ApplicationContext`进行控制,但是在`SpringBoot`启动过程中有一些`Event`是在`ApplicationContext`实例化之前发布的,那我们要怎么去监听这些`Events`呢?
`SpringBoot2.x`版本是基于`Java8`来编写的,由于内部使用到了很多新的特性,比如:`lambda`、`interface default`...,所以需要本地开发环境有`java8`的支持。
我们一直在使用`SpringBoot`来开发应用程序,但是为什么在项目启动时就会自动注册使用注解`@Component`、`@Service`、`@RestController`...标注的`Bean`呢?
随机数的使用你是不是经常用到?我们在进行运行`SpringBoot`单元测试时一般不会指定应用程序启动时的`端口号`,可以在`application.properties`文件内配置`server.port`的值为`${random.int(10000)}`,代表了随机使用`0~10000`的端口号。
`SpringBoot`在不断地版本迭代中陆续提供了不同的配置参数绑定的方式,我们可以单独获取`一个配置参数`也可以将`一系列的配置`映射绑定到`JavaBean`的属性字段,下面我们来看看这几种方式的配置绑定哪一种是你最常用到的。
我们将编写的应用程序打包为`Jar`可执行文件后,如果在`Linux`服务器环境下,可直接使用`java -jar xxx.jar`命令运行应用程序,不过当我们关闭命令窗口后`启动中`的应用程序也会停止,那我们需要通过什么方式才可以成为后台服务方式运行呢?
`SpringBoot`应用程序在启动时,我们可以传递自定义的参数来进行动态控制逻辑,比如我们使用`--debug`启动参数时就会使用`debug`启动应用程序,在控制台打印一些调试日志信息。
阿里巴巴自从跟SpringCloud共同发起创建微服务开源社区时,开启了`SpringCloud Alibaba`分支,而且在生态内提供了一款适用于分布式应用程序(`Dubbo`、`SpringCloud`等)的事务框架`Seata`,该框架经过多个大版本的发布,已经支持`MySQL`、`Oracle`这两种数据库事务回滚(`Rollback`)以及提交(`Commit`)控制,每次发版都会修复一些用户反馈的`Issue`以及添加一些新特性。
在本篇文章中我们在`SpringCloud`环境下通过使用`Seata`来模拟用户`购买商品`时由于用户**余额不足**导致本次订单提交失败,来验证下在`MySQL`数据库内事务是否会`回滚`。
`RESTful`是目前比较流行的接口路径设计规范,基于HTTP,一般使用JSON方式定义,通过不同HttpMethod来定义对应接口的资源动作,如:新增(POST)、删除(DELETE)、更新(PUT、PATCH)、查询(GET)等。
``MapStruct``是一种类型安全的``bean映射``类生成java注释处理器。 我们要做的就是定义一个映射器接口,声明任何必需的映射方法。在编译的过程中,``MapStruct``会生成此接口的实现。该实现使用纯java方法调用的源和目标对象之间的映射,``MapStruct``节省了时间,通过生成代码完成繁琐和容易出错的代码逻辑。下面我们来揭开它的神秘面纱
``Lombok``对于``Java偷懒开发者``来说应该是比较中意的,恰恰笔者就是一个喜欢在小细节上偷懒来提高开发效率的人。所以在技术框架的海洋里寻找了很久才在``GitHub``开源平台上找到,而在这之前国外很多程序猿一直使用该框架了,``Lombok``框架提供了很多编码遍历,但是也降低了代码的阅读力。下面我们看看在Idea开发工具中该怎么使用``Lombok``?
``Banner``是``SpringBoot``框架一个特色的部分,其设计的目的无非就是一个框架的标识,其中包含了版本号、框架名称等内容,既然``SpringBoot``为我们提供了这个模块,它肯定也是可以更换的这也是``Spring``开源框架的设计理念。
在传统的web项目中,防止重复提交,通常做法是:后端生成一个唯一的提交令牌(uuid),并存储在服务端。页面提交请求携带这个提交令牌,后端验证并在第一次验证后删除该令牌,保证提交请求的唯一性。
每次服务的代码更新部署,难免会存在`数据库结构`的变更以及`字典数据的添加`,手动`执行更新脚本`是一个`耗时耗力`的工作,而且还会出现遗漏或者其他状况,`SpringBoot`内部集成了一个自动执行数据库脚本的第三方依赖`Flyway`来解决这个繁琐的问题。
虽然现在springboot提供了多环境的支持,但是通常修改一下配置文件,都需要重新打包。 在开发springboot框架集成时,我遇到一个问题,就是如何让@PropertySource能够“扫描”和加载jar包外面的properties文件。
`SpringBoot`在项目启动时如果遇到异常并不能友好的打印出具体的`堆栈错误信息`,我们只能查看到简单的错误消息,以致于并不能及时解决发生的问题,针对这个问题`SpringBoot`提供了故障分析仪的概念(failure-analyzer),内部根据不同类型的异常提供了一些实现,我们如果想自定义该怎么去做?