暂时未有相关云产品技术能力~
现任技术部负责人,架构师。 博客地址: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`的值呢?
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),内部根据不同类型的异常提供了一些实现,我们如果想自定义该怎么去做?
在我们平时的项目研发过程中,异常一般都是程序员最为头疼的问题,异常的抛出、捕获、处理等既涉及事务回滚,还会涉及返回前端消息提醒信息。那么我们怎么设计可以解决上面的两个的痛点呢?我们可不可以统一处理业务逻辑然后给出前端对应的异常提醒内容呢?