项目集成swagger,并暴露指定端点给swagger
项目集成swagger
一:思考:
1.swagger解决了我们什么问题?
传统开发中,我们在开发完成一个接口后,为了测试我们的接口,我们通常会编写单元测试,以测试我们的接口的可用性,或者用postman等第三方接口测试工具进行测试,但是这也有一些弊端,我们需要为接口准备测试数据,但有时,数据量较大时,前期准备工作可能相当耗时
2.除了用于接口测试,我们还能利用它做些什么有意义的事呢?
在项目的开发过程中,我们通常会用到大量的定时任务;
a.分布式环境:quartz
b.单机环境:有spring提供的schedule 或者用线程(局限性较大)
因为公司没有引入调度中心,没有一个统一的地方对项目中的定时任务进行统一的管理,所以需要每个项目集成自己的调度框架
例如:我现在有一个需求,是每天早上7点的时候,对昨日告警发送一个统计日报,最简单的做法是引入@schedule(cron="0 0 7 * * ?")
我们经过本地的辛苦开发测试,一切正常,可是当我们将项目发布到QA环境,发现自己无法对这个定时任务的代码进行有效测试,如果需要观察我们甚至需要等到明天早上7点
问题的根源在于 Schedule 方法基于时间触发,如果使其暴露出来,能够手工触发,将大大增加灵活性。
我通过对其定制,可以暴露使用到了schedule的地方,并提供手动触发,
二:集成swagger
1.引入依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
2.启用swagger
在配置类上加上注解@EnableSwagger2
三:为定时调度任务schedule暴露接口
#### 1.HandlerMapping 扩展
新建 ScheduleMethodHandlerMapping 继承自 RequestMappingInfoHandlerMapping ,实现 HandlerMapping 接口。
public class ScheduleMethodHandlerMapping
extends RequestMappingInfoHandlerMapping
implements HandlerMapping{
/**
* 包含@Scheduled注解方法的bean为handler
* @param beanType
* @return
*/
@Override
protected boolean isHandler(Class<?> beanType) {
return Arrays.asList(MethodUtil.getMethods(beanType)).stream()
.anyMatch(method -> method.getAnnotation(Scheduled.class) != null);
}
/**
* 处理@Scheduled标注方法,生成对于的RequestMappingInfo
* @param method
* @param handlerType
* @return
*/
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
if (method.getAnnotation(Scheduled.class) == null){
return null;
}
return RequestMappingInfo.paths("/schedule/" + handlerType.getSimpleName() + "/" + method.getName())
.methods(RequestMethod.GET)
.build();
}
/**
* 提高该HandlerMapping在HandlerMapping中的顺序,使其能优先处理
* @return
*/
@Override
public int getOrder() {
return 1;
}
}
2.HandlerAdapter 扩展
andlerAdapter 扩展主要解决 Schedule 方法的执行问题。
带有 @Scheduled 注解的 Method 方法,需要单独的 HandlerAdapter 进行处理,并将处理结果通过 json 方式返回。
新建 ScheduleMethodHandlerAdapter
ScheduleMethodHandlerAdapter 继承自 AbstractHandlerMethodAdapter ,实现 HandlerAdapter 接口。
public class ScheduleMethodHandlerAdapter
extends AbstractHandlerMethodAdapter
implements HandlerAdapter {
/**
* 支持使用@Scheduled标准的handlerMethod对象
* @param handlerMethod
* @return
*/
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return handlerMethod.hasMethodAnnotation(Scheduled.class);
}
/**
* 调用HandlerMethod方法,并返回json视图
* @param request
* @param response
* @param handlerMethod
* @return
* @throws Exception
*/
@Override
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
Map<String, Object> data = Maps.newHashMap();
data.put("service", handlerMethod.getBeanType().getSimpleName());
data.put("method", handlerMethod.getMethod().getName());
Stopwatch stopwatch = Stopwatch.createStarted();
try {
// 调用HandleMethod方法
handlerMethod.getMethod().invoke(handlerMethod.getBean());
stopwatch.stop();
data.put("result", "success");
}catch (Exception e){
data.put("result", "error");
data.put("exception", e.toString());
}finally {
data.put("cost", stopwatch.elapsed(TimeUnit.MILLISECONDS) + "ms");
}
// 返回Json视图
return new ModelAndView(new MappingJackson2JsonView(), data);
}
@Override
protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) {
return 0;
}
/**
* 提高在HandlerAdapter列表中的顺序,以优先处理
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
3.与 Spring Boot 集成
ScheduleMethodHandlerMapping 和 ScheduleMethodHandlerAdapter 开发完成后,我们需要将其与 Spring Boot 进行集成,并通过参数控制是否启用。
新建 ScheduleEndpointConfiguration
新建 ScheduleEndpointConfiguration 配置类,对 ScheduleMethodHandlerMapping 和 ScheduleMethodHandlerAdapter 进行注册。
/**
* 根据配置属性控制是否启用该配置。
* <br />
* spring.schedule.endpoint.enabled = true 启用配置 <br />
* spring.schedule.endpoint.enabled = false 禁用配置 <br />
*/
@ConditionalOnProperty(prefix = "spring.schedule.endpoint", value = "enabled", havingValue = "true", matchIfMissing = false)
@Configuration
public class ScheduleEndpointConfiguration {
/**
* 注册 ScheduleMethodHandlerAdapter Bean
* @return
*/
@Bean
public ScheduleMethodHandlerAdapter scheduleMethodHandlerAdapter(){
return new ScheduleMethodHandlerAdapter();
}
/**
* 注册ScheduleMethodHandlerMapping Bean
* @return
*/
@Bean
public ScheduleMethodHandlerMapping scheduleMethodHandlerMapping(){
return new ScheduleMethodHandlerMapping();
}
}
在 resources 目录新建 META-INF 目录,并新建 spring.factories 文件,文件内声明 ScheduleEndpointConfiguration 为自动配置项。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.fudax.sqcs.common.schedule.ScheduleEndpointConfiguration
四:集成效果
访问接口:/swagger-ui.html
这谁ChangeController下的所有接口
查看暴露的定时任务接口
在类MessageServer我有两个定时任务:pushAll()方法 clear()方法
点击 try it out即可立即触发
五:安全
这种端点暴露只能在本地测试,开发环境使用,上到生产应该是严格禁止操作的
所以,我写环境校验,以保证生产的安全性
package com.fudax.sqcs.common.schedule.condition; import com.fudax.sqcs.common.constants.Env;
import com.google.common.collect.Sets;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata; import java.util.Map; public class OnEnvironmentCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnEnvironment.class.getName());
Env[] envs = (Env[]) attributes.get("values");
Env currentEnv = Env.getCurrentEnv();
return Sets.newHashSet(envs).contains(currentEnv);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional(OnEnvironmentCondition.class)
public @interface ConditionalOnEnvironment { Env[] values() default {Env.LOCAL};
}
项目集成swagger,并暴露指定端点给swagger的更多相关文章
- 开源一款强大的文件服务组件(QJ_FileCenter)(系列三 访问接口与项目集成)
系列文章 1. 开源一款强大的文件服务组件(QJ_FileCenter)(系列一) 2. 开源一款强大的文件服务组件(QJ_FileCenter)(系列二 安装说明) 3. 开源一款强大的文件服务组件 ...
- 分享一个集成在项目中的REST APIs文档框架swagger
1 为什么是使用swagger? 1-1 当后台开发人员开发好接口,是不是还要重新书写一份接口文档提给前端人员,当然对于程序员最不喜欢的就是书写文档(当然文档是必须的,有利于项目的维护) 1-2 当后 ...
- 使用IDEA快速搭建基于Maven的SpringBoot项目(集成使用Redis)
迫于好久没写博客心慌慌,随便写个简单版的笔记便于查阅. 新建项目 新建项目 然后起名 继续next netx finish. 首先附上demo的项目结构图 配置pom.xml <?xml ver ...
- iOS-Cordova集成开发,已有项目集成cordova
iOS-Cordova集成开发,已有项目集成cordova 项目组准备开发一个APP,要求Android和iOS端页面完全一致,除了一个页面跟业务相关的不同,其他界面基本一致,因此,萌生一个想法,关于 ...
- SpringBoot项目集成Hystrix
Hystrix Hystrix是由Netflix开源的一个服务隔离组件,通过服务隔离来避免由于依赖延迟.异常,引起资源耗尽导致系统不可用的解决方案. 1.什么是服务熔断 服务熔断就是对该服务的调用 ...
- [转帖]spring boot项目集成jacoco
小试牛刀:spring boot项目集成jacoco 2019-03-28 20:14:36 zyq23333 阅读数 509 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议, ...
- Apollo简介及项目集成
1. 产生背景 随着程序功能的日益复杂,程序的配置日益增多:各种功能的开关.参数的配置.服务器的地址…… 对程序配置的期望值也越来越高:配置修改后实时生效,灰度发布,分环境.分集群管理配置,完善的权限 ...
- 【DataBase】Hsqldb与项目集成
Hsqldb与项目集成 进行模式下集成 可以集成进行(In-Process)模式下的hsqldb,由于数据存储在文件中,即使程序退出,数据也不会被销毁 采用jdbc集成的方式 package com. ...
- Spring Boot 项目集成 Alibaba Druid
Druid 是一个非常好用的数据库连接池,但是他的好并不止体现在作为一个连接池加快数据访问性能上和连接管理上,他带有一个强大的监控工具:Druid Monitor.不仅可以监控数据源和慢查询,还可以监 ...
随机推荐
- 大数据给IT企业带来攫金市场新机遇
大数据给IT企业带来攫金市场新机遇 大数据,一个时髦的名词,也是当下热门的业务领域.大数据诱人的利益诉求点之一,即通过大数据能更好地提高效率,更好地有的放矢.一方面,大数据让公司内部更有效地运作:另一 ...
- Asp.Net Core 第07局:路由
总目录 前言 本文介绍Asp.Net Core 路由. 环境 1.Visual Studio 2017 2.Asp.Net Core 2.2 开局 第一手:路由概述 1.路由主要用于处理特定的请求. ...
- 科普:std::sort干了什么
std::sort算是STL中对OIer比较友好的函数了,但你有想过sort是如何保证它的高速且稳定吗? 正文 我们首先来到第一层:sort函数 template<typename _Rando ...
- 基于名称快速定位文件和文件夹的搜索工具Everything和dll依赖查询工具Dependency Walker
在工作中有时需要定位头文件.lib库文件.dll文件等的路径,自己去一个个盘符查找实在太麻烦,最近发现使用Everything这款工具很方便,下载地址为:下载 Everything 1.4.1.935 ...
- centos7下查看cup核数
centos7下查看cup核数 # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数cat ...
- gulp构建前端,压缩css,js文件,实现浏览器自动刷新
一.安装node nodejs下载地址:https://nodejs.org/ nodejs自带npm模块管理器,安装完成之后打开dos命令窗口输入 node -v就能查看nodejs是否安装成成功 ...
- CSS实现不换行/自动换行/文本超出隐藏显示省略号
在写页面的时候,我们经常会需要用到关于文本的换行,强制换行以及显示几行超过显示省略号等,今天我们就对这些问题来做个汇总吧! 1.自动换行 div{ word-wrap:break-word; word ...
- LeetCode Array Easy 268. Missing Number
Description Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one th ...
- 【记录】spring boot 整合mybatis 实体类返回日期格式化
1:首先将返回的实体类的时间由Date类型 换成String类型 2:将mapper.xml里的created_time 不设置类型,并将查询字段时间格式化,注意此次查询需要使用别名 不然返回查不到此 ...
- 【记录】linux 文件权限的查看和修改
从上图可以看出每个文件权限与类型都是不一样的,如果对各个字母表达的含义不了解,那么看的真是一脸懵逼. 别急,具体解释如下: d rwx rwx rwx - rwx r-- rw- 第一列含义 ...