
Springboot 集成Swagger 2(springfox)
Springfox Swagger2:
Springfox Swagger UI:
创建一个以上一个类配置swagger即可。
访问界面:IP:port/swagger-uihtml
在以上配置类中添加方法:
项目中并不需要swagger将整个项目的所有类暴露出去,通过以上配置的Bean实例,设置swagger关注并显示的接口,以及是否开启使用:
只希望在开发环境中使用swagger,但是生产环境不使用:
配置API文档分组:
配置多个分组:
在配置类中,一个Docket Bean实例,对应一个swagger分组。
@Api的属性
示例:
示例:
@ApiModel的属性:
@ApiModelProperty的属性说明:
示例:
在原先dubbo+zookeeper项目中,web模块只暴露Restful接口,各服务模块只暴露duboo接口,此时用户登录后由web项目进行token的鉴权和验证,并通过dubbo的隐式传参将sessionID传递给dubbo服务模块, 拦截器再根据sessionID从Redis中获取用户信息设置到当前线程
然鹅,在springcloud中,各个微服务直接暴露的是restful接口,此时如何让各个微服务获取到当前用户信息呢?最佳的方式就是token了,token作为BS之间的会话标识(一般是原生随机token),同时也可以作为信息的载体传递一些自定义信息(jwt, 即Json web token)。
为了能更清楚的了解本文,需要对spring-security-oauth 及 jwt有一定了解,本文只关注用户信息传递这一块
认证服务器配置 AuthorizationServerConfigurerAdapter
自定义token转换器
CustomJwtAccessTokenConverter
此时按照固定格式访问授权服务器token接口获取token,如图,可以获取到jwt格式的token,并且额外信息nick_name也已经添加
直接解析jwt字符串可以获取到以下信息,即用户名和授权信息
只需要指定和授权服务器一模一样的token store 和token converter
在securiy的过滤器中 OAuth2AuthenticationProcessingFilter 会从token中获取相关信息进行鉴权
源码:
注意,资源服务器主要配置在
ResourceServerConfigurerAdapter
微服务获取jwttoken中的用户信息,两种方式,使用security上下文可以直接获取当前用户名和权限,另一种自定义拦截器获取额外信息。
这个就简单了,获取header头解析验证token
然后获取之前从授权服务器中的添加的 nick_name的额外信息放入线程变量
其中用户上下文类
启动拦截器注册webmvc配置类
在controller中获取用户信息如图
在默认的认证异常如图
假设我们做了全局异常处理,前端希望在token过期时做统一的登录跳转如何做?
实现 AuthenticationEntryPoint 接口重写 commence 方法即可
注意,直接抛出异常并不会走 @RestControllerAdvice , 因为在这里是response直接返回,并没有使用到Controller处理
此时返回我自定义的Response对象,如图
prefer,ip,address:前端是否显示ip地址;ip,address:实际ip地址;instance,id:实例注册id。
当我们需要跨服务器(不在一个局域网的情况下),可以使用以上情况解决。
静态IP就是给你的电脑分配一个不会变的IP地址,而动态IP就是路由器随机分配一个IP地址给你;静态IP的好处就是连接稳定,而动态IP就简单,用户不需要设置就可以连接别的局域网,但是人多的时候可能会出现IP冲突导致连不上。
话说这个remote shell是个人最喜欢的功能,但是在新版本的spring boot 已经移除了对他的支持,很可惜,不过在新版本中也可以自己引入支持。那我们就着眼于眼前,毕竟我们教程中的版本是还没有移除的。这个remote shell是基于 CRaSH ,他可以再应用程序中开启端口,默认是2000,我们可以连进正在运行的程序中,达到监控与维护的目的。比如说,我们希望一个正在运行的程序中,某个Bean通过人为的 *** 作下Destroy或者动态的数据订正之类的,都可以通过这个功能实现。
闲话不多说,我们看下pom
spring-boot-starter-remote-shell 这个模块主要就是将crash引入进来。然后我们在配置文件中定义用户名与密码:
剩下的我们可以使用groovy写一个获取spring 容器中Bean的脚本
这个脚本放置的位置一般情况下放到resources/commands目录下,因为在jar包中定义了脚本扫描的路径。我们就算配置好了,下面我们需要启动项目,启动成功后,打开shell界面,输入
密码我们设置的也是
登录进来后的界面是
进来后输入
进入groovy的 *** 作模式,因为我们是使用groovy写的脚本,只有在这种模式下,脚本才能运行。
返回值
说明我们已经获取到了这个Bean,然后我们可以 *** 作这个Bean里面的方法来完成某些功能。这个真的是非常实用的。大家玩起来吧
下节将的内容是: SpringBoot基础教程(八)——与velocity的结合
本节项目源码
上篇文章已经介绍了 SpringBoot 的基本使用过程 ,本文主要介绍用那篇文章中配置好的SpringBoot工程实现简单的接口。
最终工程目录是下面这样:
这是个简陋的目录结构,仅供我们参考,其中主要分为四类:
最后还有一个Application类,系统默认生成,不需要处理。
可以通过浏览器、PostMan调用以上写好的两个接口,来测试一下接口是否正常。在调用时注意检查IP地址、端口、接口名和参数是否设置正确。
Spring Boot连接Redis哨兵集群的原理如下:
1 Spring Boot使用Jedis客户端连接Redis哨兵集群。Jedis是一个Java Redis客户端,它支持连接Redis哨兵集群。
2 Jedis客户端会向Redis哨兵集群发送SENTINEL get-master-addr-by-name命令,获取当前Redis主节点的IP地址和端口号。
3 Jedis客户端会使用获取到的IP地址和端口号连接Redis主节点,并发送PING命令测试连接是否正常。
4 如果连接正常,Jedis客户端会将连接信息保存在连接池中,以便后续使用。
5 如果连接失败,Jedis客户端会向Redis哨兵集群发送SENTINEL get-master-addr-by-name命令,获取新的Redis主节点的IP地址和端口号,然后重复步骤2-4。
6 如果Redis主节点发生故障,Redis哨兵会自动将从节点升级为主节点,并通知Jedis客户端更新连接信息。
总之,Spring Boot连接Redis哨兵集群的原理是通过Jedis客户端向Redis哨兵集群发送命令获取当前Redis主节点的IP地址和端口号,然后使用获取到的信息连接Redis主节点。如果连接失败,Jedis客户端会重新获取新的Redis主节点的IP地址和端口号,直到连接成功为止。如果Redis主节点发生故障,Redis哨兵会自动将从节点升级为主节点,并通知Jedis客户端更新连接信息。
之前在SpringBoot项目中一直使用的是SpringFox提供的Swagger库,上了下官网发现已经有接近两年没出新版本了!前几天升级了SpringBoot 26x 版本,发现这个库的兼容性也越来越不好了,有的常用注解属性被废弃了居然都没提供替代!无意中发现了另一款Swagger库SpringDoc,试用了一下非常不错,推荐给大家!
SpringDoc简介
SpringDoc是一款可以结合SpringBoot使用的API文档生成工具,基于OpenAPI 3,目前在Github上已有17K+Star,更新发版还是挺勤快的,是一款更好用的Swagger库!值得一提的是SpringDoc不仅支持Spring WebMvc项目,还可以支持Spring WebFlux项目,甚至Spring Rest和Spring Native项目,总之非常强大,下面是一张SpringDoc的架构图。
使用
接下来我们介绍下SpringDoc的使用,使用的是之前集成SpringFox的mall-tiny-swagger项目,我将把它改造成使用SpringDoc。
集成
首先我们得集成SpringDoc,在pomxml中添加它的依赖即可,开箱即用,无需任何配置。
<!--springdoc 官方Starter-->orgspringdocspringdoc-openapi-ui166
从SpringFox迁移
我们先来看下经常使用的Swagger注解,看看SpringFox的和SpringDoc的有啥区别,毕竟对比已学过的技术能该快掌握新技术;
接下来我们对之前Controller中使用的注解进行改造,对照上表即可,之前在@Api注解中被废弃了好久又没有替代的description属性终于被支持了!
/
品牌管理Controller
Created by macro on 2019/4/19
/@Tag(name ="PmsBrandController", description ="商品品牌管理")@Controller@RequestMapping("/brand")publicclassPmsBrandController{@AutowiredprivatePmsBrandService brandService;privatestaticfinalLogger LOGGER = LoggerFactorygetLogger(PmsBrandControllerclass);@Operation(summary ="获取所有品牌列表",description ="需要登录后访问")@RequestMapping(value ="listAll", method = RequestMethodGET)@ResponseBodypublicCommonResult> getBrandList() {returnCommonResultsuccess(brandServicelistAllBrand()); }@Operation(summary ="添加品牌")@RequestMapping(value ="/create", method = RequestMethodPOST)@ResponseBody@PreAuthorize("hasRole('ADMIN')")publicCommonResult createBrand(@RequestBodyPmsBrand pmsBrand) { CommonResult commonResult; int count = brandServicecreateBrand(pmsBrand);if(count ==1) { commonResult = CommonResultsuccess(pmsBrand); LOGGERdebug("createBrand success:{}", pmsBrand); }else{ commonResult = CommonResultfailed(" *** 作失败"); LOGGERdebug("createBrand failed:{}", pmsBrand); }returncommonResult; }@Operation(summary ="更新指定id品牌信息")@RequestMapping(value ="/update/{id}", method = RequestMethodPOST)@ResponseBody@PreAuthorize("hasRole('ADMIN')")publicCommonResult updateBrand(@PathVariable("id")Longid,@RequestBodyPmsBrand pmsBrandDto, BindingResult result) { CommonResult commonResult; int count = brandServiceupdateBrand(id, pmsBrandDto);if(count ==1) { commonResult = CommonResultsuccess(pmsBrandDto); LOGGERdebug("updateBrand success:{}", pmsBrandDto); }else{ commonResult = CommonResultfailed(" *** 作失败"); LOGGERdebug("updateBrand failed:{}", pmsBrandDto); }returncommonResult; }@Operation(summary ="删除指定id的品牌")@RequestMapping(value ="/delete/{id}", method = RequestMethodGET)@ResponseBody@PreAuthorize("hasRole('ADMIN')")publicCommonResult deleteBrand(@PathVariable("id")Longid) { int count = brandServicedeleteBrand(id);if(count ==1) { LOGGERdebug("deleteBrand success :id={}", id);returnCommonResultsuccess(null); }else{ LOGGERdebug("deleteBrand failed :id={}", id);returnCommonResultfailed(" *** 作失败"); } }@Operation(summary ="分页查询品牌列表")@RequestMapping(value ="/list", method = RequestMethodGET)@ResponseBody@PreAuthorize("hasRole('ADMIN')")publicCommonResult> listBrand(@RequestParam(value ="pageNum", defaultValue ="1")@Parameter(description ="页码")Integer pageNum,@RequestParam(value ="pageSize", defaultValue ="3")@Parameter(description ="每页数量")Integer pageSize) { List brandList = brandServicelistBrand(pageNum, pageSize);returnCommonResultsuccess(CommonPagerestPage(brandList)); }@Operation(summary ="获取指定id的品牌详情")@RequestMapping(value ="/{id}", method = RequestMethodGET)@ResponseBody@PreAuthorize("hasRole('ADMIN')")publicCommonResult brand(@PathVariable("id")Longid) {returnCommonResultsuccess(brandServicegetBrand(id)); }}
接下来进行SpringDoc的配置,使用OpenAPI来配置基础的文档信息,通过GroupedOpenApi配置分组的API文档,SpringDoc支持直接使用接口路径进行配置。
/
SpringDoc API文档相关配置
Created by macro on 2022/3/4
/@ConfigurationpublicclassSpringDocConfig{@BeanpublicOpenAPImallTinyOpenAPI(){returnnewOpenAPI() info(newInfo()title("Mall-Tiny API") description("SpringDoc API 演示") version("v100") license(newLicense()name("Apache 20")url(">
spring-boot-devtools是Spring Boot给开发人员提供的一个工具包,它可以提高开发人员的工作效率。我们可以通过如下方式引入该工具包:
Maven
Gradle
有些SpringBoot支持的库使用了缓存技术来提高性能。比如模板引擎会对编译好的模板进行缓存从而避免每次都要解析模板文件;Spring MVC也会为静态文件缓存一些>
以上就是关于Spring boot 接入swagger以及使用全部的内容,包括:Spring boot 接入swagger以及使用、Springboot security oauth2 jwt实现权限控制,实现微服务获取当前用户信息、springboot ip地址怎么动态修改等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)