从.Net到Java学习第五篇——Spring Boot &&Profile &&Swagger2
刚学java不久,我有个疑问,为何用到的各种java开源jar包许多都是阿里巴巴的开源项目,为何几乎很少见百度和腾讯?不是说好的BAT吗?
Spring Boot 的配置文件及多环境配置
Spring Boot 使用一个全局的配置文件 application.properties 或 application.yml,放置在 src/main/resources 目录或者类路径的 /config 下。
Spring Boot 的全局配置文件的作用是对一些默认配置的配置值进行修改。
例如将 Tomcat 的默认端口号 8080 修改为 8082,并将默认的访问路径 “/” 修改为 “/boot”。可以在 application.yml 中添加:
server:
port: 8082
context-path: /boot
如果我们需要在不同的环境下面有不同的配置怎么办?比如生产、开发、测试三个不同的环境,我们的配置肯定不一样。这时,我们需要用到Profile。
Profile 是 Spring 用来针对不同的环境对不同的配置提供支持的,全局 Profile 配置使用 application-{profile}. yml(如 application-prod.yml)。通过在 application.yml 中设置 spring.profiles.active = prod 来指定活动的 Profile。
依次再目录下面新建三个配置文件,application-dev.yml、application-test.yml、application-prod.yml。它们分别代表开发环境、测试环境、生产环境的配置文件。
application-dev.yml:
server:
port: 8083
context-path: /boot
application-test.yml:
server:
port: 8085
context-path: /boot
application-prod.yml:
server:
port: 8084
context-path: /boot
接下来修改application.yml:表示,将采用application-dev.yml这个配置文件。
spring:
profiles:
active: dev
我们在IDEA中运行项目,然后看下运行结果:
我们看到启用了8083端口,而我们的配置文件application-dev.yml中正是配置的8083端口。
假设我们在application.yml中已经配置了端口8082,看下会怎么样
运行结果:
Tomcat started on port(s): 8083 (http)
还是使用的dev中8083端口,那么我们再来换下位置,把
server:
port: 8082
context-path: /boot
放到配置文件的最后面,再看下结果,结果还是启用的8083端口。
那么说明,配置文件会优先获取Profile中的配置,如果Profile中没有的配置项, 那么会直接取application.yml中的配置。
Spring Boot实现RestFul
回到之前AreaController类的代码:
@Autowired
private AreaService areaService;
@RequestMapping(value = "/get", produces = {"application/json;charset=UTF-8"})
public Map<String,Object> getArea(@PathParam("areaId") Integer areaId){
Map<String,Object> modelMap= new HashMap<String,Object>() ;
modelMap.put("area",areaService.getArea(areaId));
return modelMap;
}
我们的通过URL访问的方式是这样的:通过?号传递参数,而且要求问号后面的参数名称必须和@PathParam("areaId")中的参数名称保持一致,显然这样是不符合RestFul风格的。
@PathParam注解接收的是传统的URL界面传参的方式
接下来,我们稍微修改一下:
@RequestMapping(value = "/get/{areaId}", produces = {"application/json;charset=UTF-8"})
public Map<String,Object> getAreaApi(@PathVariable Integer areaId){
Map<String,Object> modelMap= new HashMap<String,Object>() ;
modelMap.put("area",areaService.getArea(areaId));
return modelMap;
}
再看下允许结果:
我们再来修改一下代码看下:
@RequestMapping(value = "/get/{Id}", produces = {"application/json;charset=UTF-8"})
public Map<String,Object> getAreaApi(@PathVariable("Id") Integer areaId){
Map<String,Object> modelMap= new HashMap<String,Object>() ;
modelMap.put("area",areaService.getArea(areaId));
return modelMap;
}
运行结果还是一样的。那么这说明,当@PathVariable中不指定参数名称的时候,默认就是把后面的areaId当成是接收参数了,如果@PathVariable中指定了接收参数的名称(这个名称必须和{Id}一致),那么后面的Integer areaId可以随意命名。
@PathVariable注解接收的就是符合RestFull风格的参数。此外还有一个@RequestParam注解。
@RequestParam 和 @PathVariable 注解是用于从request中接收请求的,两个都可以接收参数,关键点不同的是@RequestParam 是从request里面拿取值,而 @PathVariable 是从一个URI模板里面来填充。
SpringBoot整合Swagger2自动生成API文档
手写Api文档的几个痛点:
文档需要更新的时候,需要再次发送一份给前端,也就是文档更新交流不及时。
接口返回结果不明确
不能直接在线测试接口,通常需要使用工具,比如postman
接口文档太多,不好管理
Swagger也就是为了解决这个问题,当然也不能说Swagger就一定是完美的,当然也有缺点,最明显的就是代码移入性比较强。asp.net web api也有api文档自动生成功能,最终效果和这个差不多。
(1)添加Swagger依赖
修改我们的pom.xml文件,添加变量 <springfox.version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<springfox.version>2.7.0</springfox.version>
</properties>
引入依赖
<!--swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.version}</version>
</dependency>
(2)添加Swagger2的配置文件Swagger2Config
在config包下面新建类Swagger2Config
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.yujie.controller")) //需要注意的是这里要写入控制器所在的包
.paths(PathSelectors.any())
.build();
} private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("springboot利用swagger构建api文档")
.description("简单优雅的restfun风格,https://www.cnblogs.com/jiekzou/")
.termsOfServiceUrl("https://www.cnblogs.com/jiekzou/")
.version("1.0")
.build();
}
}
注意:用@Configuration注解该类,等价于XML中配置beans;用@Bean标注方法等价于XML中配置bean。
如上代码所示,通过@Configuration注解,让Spring来加载该类配置。再通过@EnableSwagger2注解来启用Swagger2。
createRestApi函数创建Docket的Bean之后,apiInfo()用来创建该Api的基本信息(这些基本信息会展现在文档页面中)。select()函数返回一个ApiSelectorBuilder实例用来控制哪些接口暴露给Swagger来展现,本例采用指定扫描的包路径来定义,Swagger会扫描该包下所有Controller定义的API,并产生文档内容(除了被@ApiIgnore指定的请求)。
添加文档内容
在完成了上述配置后,其实已经可以生产文档内容,但是这样的文档主要针对请求本身,而描述主要来源于函数等命名产生,对用户并不友好,我们通常需要自己增加一些说明来丰富文档内容。如下所示,我们通过@ApiOperation注解来给API增加说明、通过@ApiImplicitParams、@ApiImplicitParam注解来给参数增加说明。
查看我们AreaController类的代码如下:
@Api(value = "区域操作controller", description = "区域相关的操作", tags = {"区域模块校验接口"})
@RestController
//@RequestMapping("/area")
public class AreaController {
@Autowired
private AreaService areaService;
/* @RequestMapping(value = "/get", produces = {"application/json;charset=UTF-8"})
public Map<String,Object> getArea(@PathParam("areaId") Integer areaId){
Map<String,Object> modelMap= new HashMap<String,Object>() ;
modelMap.put("area",areaService.getArea(areaId));
return modelMap;
}*/
@ApiOperation(value="获取区域详细信息", notes="根据url的id来获取区域详细信息")
@ApiImplicitParam(name = "Id", value = "区域ID", required = true, dataType = "Integer", paramType = "path")
@RequestMapping(value = "/get/{Id}",method = RequestMethod.GET,produces = {"application/json;charset=UTF-8"})
public Map<String,Object> getAreaApi(@PathVariable("Id") Integer areaId){
Map<String,Object> modelMap= new HashMap<String,Object>() ;
modelMap.put("area",areaService.getArea(areaId));
return modelMap;
}
@ApiOperation(value="创建区域", notes="根据Area对象创建区域")
@ApiImplicitParam(name = "area", value = "区域详细实体area", required = true, dataType = "Area")
@RequestMapping(value = "/add",method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"})
public Map<String,Object> addArea(Area area){
Map<String,Object> modelMap= new HashMap<String,Object>() ;
modelMap.put("success",areaService.addArea(area));
return modelMap;
}
@ApiOperation(value="修改区域", notes="根据Area对象修改区域")
@ApiImplicitParam(name = "area", value = "区域详细实体area", required = true, dataType = "Area")
@RequestMapping(value = "/edit",method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"})
public Map<String,Object> editArea(Area area){
Map<String,Object> modelMap= new HashMap<String,Object>() ;
modelMap.put("success",areaService.addArea(area));
return modelMap;
}
@ApiOperation(value="获取区域列表", notes="获取区域列表")
@ApiImplicitParams ({
@ApiImplicitParam(name = "pageNum", value = "第多少页", required = true, dataType = "Integer", paramType = "path"),
@ApiImplicitParam(name = "pageSize", value = "每页取多少条记录", required = true, dataType = "Integer", paramType = "path")
})
@RequestMapping(value = "/all/{pageNum}/{pageSize}",method = RequestMethod.GET,produces = {"application/json;charset=UTF-8"})
public Object findAllArea(@PathVariable("pageNum") int pageNum, @PathVariable("pageSize") int pageSize){
return areaService.findAllArea(pageNum,pageSize);
}
@GetMapping(value="/del/{areaId}")
public Map<String,Object> deleteArea(@PathVariable Integer areaId){
Map<String,Object> modelMap= new HashMap<String,Object>() ;
modelMap.put("success",areaService.deleteArea(areaId));
return modelMap;
}
@GetMapping("/test")
@ApiIgnore//使用该注解忽略这个API
public String Test(){
return "test";
}
}
swagger的相关注解
swagger通过注解表明该接口会生成文档,包括接口名、请求方法、参数、返回信息的等等。
- @Api:修饰整个类,描述Controller的作用
- @ApiOperation:描述一个类的一个方法,或者说一个接口
- @ApiParam:单个参数描述
- @ApiModel:用对象来接收参数
- @ApiProperty:用对象接收参数时,描述对象的一个字段
- @ApiResponse:HTTP响应其中1个描述
- @ApiResponses:HTTP响应整体描述
- @ApiIgnore:使用该注解忽略这个API
- @ApiError :发生错误返回的信息
- @ApiImplicitParam:一个请求参数
- @ApiImplicitParams:多个请求参数
启动Spring Boot程序,访问:http://localhost:8083/boot/swagger-ui.html,最终运行效果如下:
从.Net到Java学习第五篇——Spring Boot &&Profile &&Swagger2的更多相关文章
- 从.Net到Java学习第四篇——spring boot+redis
从.Net到Java学习系列目录 “学习java已经十天,有时也怀念当初.net的经典,让这语言将你我相连,怀念你......”接上一篇,本篇使用到的框架redis.FastJSON. 环境准备 安装 ...
- 从.Net到Java学习第三篇——spring boot+mybatis+mysql
从.Net到Java学习第一篇——开篇 环境:mysql5.7 新建mysql数据库demo,然后执行如下sql脚本进行数据表创建和数据初始化: -- ------------------------ ...
- 从.Net到Java学习第十篇——Spring Boot文件上传和下载
从.Net到Java学习系列目录 图片上传 Spring Boot中的文件上传就是Spring MVC中的文件上传,将其集成进来了. 在模板目录创建一个新的页面 profile/uploadPage. ...
- kafka学习(五)Spring Boot 整合 Kafka
文章更新时间:2020/06/08 一.创建Spring boot 工程 创建过程不再描述,创建后的工程结构如下: POM文件中要加入几个依赖: <?xml version="1.0& ...
- Java学习第五篇:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题
一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ...
- Java 学习 第五篇;面向对象
1:基本数据类型的拆装: 基本变量类型 通过 new WrapperClass(primitive) 创建包装类对象: 包装类的对象 通过 WrapperInstance.XXXValue() 获取包 ...
- spring Boot 学习(五、Spring Boot与安全)
一.安全Spring Security是针对Spring项目的安全框架,也是Spring Boot底层安全模 块默认的技术选型.他可以实现强大的web安全控制.对于安全控制,我们仅 需引入spring ...
- 从.Net到Java学习第十一篇——SpringBoot登录实现
从.Net到Java学习系列目录 通过前面10篇文章的学习,相信我们对SpringBoot已经有了一些了解,那么如何来验证我们的学习成果呢?当然是通过做项目来证明啦!所以从这一篇开始我将会对之前自己做 ...
- 201671010140. 2016-2017-2 《Java程序设计》java学习第五周
java学习第五周心得体会 本周,是Java学习第五周,随着时间推移,随着课本内容的推进,我们接触到的程序也开始变得越来越复杂,不再是二三章那些用来练手的小程序了,这一点,在我们的例题运 ...
随机推荐
- vue-router路径计算问题
简书原文 昨天刚刚发表了一个前端跨域新方案尝试,今天在开发中就遇到的了问题. 起因 前端使用的是vue-router组件的history模式,但是由于我们的整个页面都是从static(静态资源站)lo ...
- 浅析Diffie–Hellman
一.作者 这个密钥交换方法,由惠特菲尔德·迪菲(Bailey Whitfield Diffie).马丁·赫尔曼(Martin Edward Hellman)于1976年发表. 二.说明 它是一种安全协 ...
- Android OpenSL ES 开发:Android OpenSL 介绍和开发流程说明
一.Android OpenSL ES 介绍 OpenSL ES (Open Sound Library for Embedded Systems)是无授权费.跨平台.针对嵌入式系统精心优化的硬件音频 ...
- Go语言反射reflect
目录 通过反射获取类型信息 理解反射的类型(Type)与种类(Kind) reflect.Elem() - 通过反射获取指针指向的元素类型 通过反射获取结构体的成员类型 通过反射获取值信息 使用反射值 ...
- python glob的安装和使用
基本概念 glob是python自己带的一个文件操作相关模块,用它可以查找符合自己目的的文件,类似于Windows下的文件搜索,支持通配符操作.*,?,[]这三个通配符,*代表0个或多个字符,?代表一 ...
- Mysql的两种“超过多少次”写法(力扣596)
题目: 有一个courses 表 ,有: student (学生) 和 class (课程). 请列出所有超过或等于5名学生的课. 例如,表: +---------+------------+ | s ...
- [usaco18Feb] New Barns
题意 每次新建一个节点,并与一个已知节点连边.(或者不连).多次询问以某个已知点点出发的最远路径长度. 分析 显然,在任何时候图都是一个森林.由树的直径算法可知,与某点最远距的点必然是树的直径的一段. ...
- JSON 序列化的时候忽略无效的属性值
例如我拥有以下代码. public class NewObject { public int? TestValue { get; set; } public int? Age { get; set; ...
- Oracle绝对秒数转换为时间戳
一般Oracle得到的时间格式为: 1970-01-05 01:23:56.297 为了计算两个时间的差值: 1970-01-05 01:23:56.297 与 1970-01-05 01:24:57 ...
- Zara带你快速入门WPF(1)---开篇
一.引言 我们时常可以看到园友们在讨论WPF与WinForm!它们两个的激情对决,看到大家热情洋溢的评论,搞技术的我也是深受感动. 二.走势 但抱歉的是,我无法预测未来WPF会怎么样.乔布斯说过这么一 ...