搜索词>>Swagger2 耗时0.0030
  • swagger2 导出离线 word文档

    Swagger2 导出离线文档简述继上一篇搬运国外的swagger2导出离线文档之后,最近发现国内一款不错的swagger ui组件和导出离线的方法,比之前的更简单优雅Swagger2 导出离线文档简述继上一篇搬运国外的swagger2导出离线文档之后,最近发现国内一款不错的swagger ui组件和导出离线的方法,比之前的更简单优雅。这里主要用的组件是下面的:<dependency> <groupId>net.ifok.swagger</groupId> <artifactId>swagger-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency>Swagger2 如何导出离线word呢? 本次的方法非常简单,首先新建一个spring boot项目,建议。2.2.x-2.4.x版本,可以直接引入上方的组件即可。项目的pom.xml依赖部分看起来像这样:$title(pom.xml) <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>net.ifok.swagger</groupId> <artifactId>swagger-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>其他低版本的spring boot 使用,请参考说明 Swagger Spring Boot Stater接下来就是配置了,配置我这里建议使用yml格式的,因为yml格式支持UTF8编码,可以更好的使用中文。当然properties 通过编码转换也行。下面就是一个简单的yml格式配置例子$title(application.yml) spring: swagger: api-title: 某某APP接口文档 api-version: v1.0 contact: url: https://www.leftso.com email: example@leftso.com name: leftso.com url-pattern: /api/**更多的配置请参考说明:Swagger Spring Boot Stater编写一个测试用的controller$title(DemoController.java) package com.example.swagger; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @Description: 测试类 * @Author: xq * @Date: 2021/3/17 8:51 **/ @RestController @RequestMapping("/api/") public class DemoController { @ApiOperation("get获取接口") @GetMapping("get") public String getData(String param){ return "Ok"; } @ApiOperation("post提交接口") @PostMapping("post") public Result postData(String name,String age){ return Result.success(name); } } 启动项目,并访问 http://localhost:8080/doc.html离线导出word的重点来了,首先点开文档管理,就可以看到离线文档栏目点击箭头指的地方,下载一个word文件,word文件的格式大概如下:part1part2part3part4part5
  • swagger2 导出离线Word/PDF/HTML文档

    1.前言通过前面的两篇博客Spring Boot Security Swagger2整合生成安全的在线REST API文档 SpringMVC也可参考spring boot REST 通过Swagger2生成接口文档(含例子源码下载)我们已1.前言通过前面的两篇博客Spring Boot Security Swagger2整合生成安全的在线REST API文档 SpringMVC也可参考spring boot REST 通过Swagger2生成接口文档(含例子源码下载)我们已经介绍了如何使用spring boot整合swagger2 生成在线的API文档。但是某些情况下,我们需要上交文档类型的接口文档以完成国内开发项目中的文档空缺。然而我们需要提交的文档一般都是Word文档或者PDF文档之类的。HTML这类都很少见。但是这些统统都要离线的。2.通过swagger2markup来实现swagger2 Word/PDF/HTML的导出2.1在项目中添加swagger2markup的依赖。 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-staticdocs</artifactId> <version>2.4.0</version> </dependency> <dependency> <groupId>org.springframework.restdocs</groupId> <artifactId>spring-restdocs-mockmvc</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-jsonSchema</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.github.robwin</groupId> <artifactId>assertj-swagger</artifactId> <version>0.2.0</version> <scope>test</scope> </dependency> <dependency> <groupId>io.github.swagger2markup</groupId> <artifactId>swagger2markup-spring-restdocs-ext</artifactId> <version>${swagger2markup.version}</version> <scope>test</scope> </dependency>当然项目之前的swagger2依赖统统的需要。如果这里有啥不懂得可以参考上面的两个博客。这里将不会再详细的讲述swagger2生成在线文档。 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> <scope>test</scope> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-bean-validators</artifactId> <version>2.7.0</version> <scope>test</scope> </dependency>2.2配置文档输出路径 <properties> <java.version>1.8</java.version> <swagger2markup.version>1.3.1</swagger2markup.version> <asciidoctor.input.directory>${project.basedir}/src/docs/asciidoc</asciidoctor.input.directory> <swagger.output.dir>${project.build.directory}/swagger</swagger.output.dir> <swagger.snippetOutput.dir>${project.build.directory}/asciidoc/snippets</swagger.snippetOutput.dir> <generated.asciidoc.directory>${project.build.directory}/asciidoc/generated</generated.asciidoc.directory> <asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory> <asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory> <swagger.input>${swagger.output.dir}/swagger.json</swagger.input> </properties> 2.3这里举个宠物controller的代码/* * * Copyright 2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * */ package io.github.robwin.swagger2markup.petstore.controller; import io.swagger.annotations.*; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import io.github.robwin.swagger2markup.petstore.Responses; import io.github.robwin.swagger2markup.petstore.model.Pet; import io.github.robwin.swagger2markup.petstore.model.Pets; import io.github.robwin.swagger2markup.petstore.repository.MapBackedRepository; import java.util.List; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.http.MediaType.APPLICATION_XML_VALUE; import static org.springframework.web.bind.annotation.RequestMethod.*; @Controller @RequestMapping(value = "/pets", produces = {APPLICATION_JSON_VALUE, APPLICATION_XML_VALUE, "application/x-smile"}) @Api(value = "/pets", tags = "Pets", description = "关于pets的操作") public class PetController { PetRepository petData = new PetRepository(); @RequestMapping(value = "/{petId}", method = GET) @ApiOperation( value = "通过ID查找宠物", notes = "当ID <10时,返回宠物。ID> 10或非整数将模拟API" + "错误条件", response = Pet.class, authorizations = { @Authorization(value = "api_key"), @Authorization(value = "petstore_auth", scopes = { @AuthorizationScope(scope = "write_pets", description = ""), @AuthorizationScope(scope = "read_pets", description = "") })}) @ApiResponses(value = { @ApiResponse(code = 400, message = "提供的ID无效"), @ApiResponse(code = 404, message = "Pet没找到")} ) public ResponseEntity<Pet> getPetById( @ApiParam(value = "需要提取的宠物ID", allowableValues = "range[1,5]", required = true) @PathVariable("petId") String petId) throws NotFoundException { Pet pet = petData.get(Long.valueOf(petId)); if (null != pet) { return Responses.ok(pet); } else { throw new NotFoundException(404, "Pet not found"); } } @RequestMapping(method = POST) @ApiOperation(value = "添加一个新宠物到商店") @ApiResponses(value = {@ApiResponse(code = 405, message = "Invalid input")}) public ResponseEntity<String> addPet( @ApiParam(value = "需要添加到商店的宠物对象", required = true) @RequestBody Pet pet) { petData.add(pet); return Responses.ok("SUCCESS"); } @RequestMapping(method = PUT) @ApiOperation(value = "更新一个已存在的宠物信息", authorizations = @Authorization(value = "petstore_auth", scopes = { @AuthorizationScope(scope = "write_pets", description = ""), @AuthorizationScope(scope = "read_pets", description = "") })) @ApiResponses(value = {@ApiResponse(code = 400, message = "无效ID"), @ApiResponse(code = 404, message = "宠物没找到"), @ApiResponse(code = 405, message = "验证错误")}) public ResponseEntity<String> updatePet( @ApiParam(value = "需要添加到商店的宠物对象", required = true) @RequestBody Pet pet) { petData.add(pet); return Responses.ok("SUCCESS"); } @RequestMapping(value = "/findByStatus", method = GET) @ApiOperation( value = "通过状态查询宠物", notes = "多个状态值可以用逗号分隔的字符串提供", response = Pet.class, responseContainer = "List", authorizations = @Authorization(value = "petstore_auth", scopes = { @AuthorizationScope(scope = "write_pets", description = ""), @AuthorizationScope(scope = "read_pets", description = "") })) @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid status value")}) /** TODO: This renders parameter as * "name": "status", "in": "query", "description": "Status values that need to be considered for filter", "required": false, "type": "array", "items": {"type": "string"}, "collectionFormat": "multi", "default": "available" */ public ResponseEntity<List<Pet>> findPetsByStatus( @ApiParam(value = "Status values that need to be considered for filter", required = true, defaultValue = "available", allowableValues = "available,pending,sold", allowMultiple = true) @RequestParam("status") String status) { return Responses.ok(petData.findPetByStatus(status)); } @RequestMapping(value = "/findByTags", method = GET) @ApiOperation( value = "通过标签查询宠物", notes = "多个标签可以用逗号分隔的字符串提供。 使用tag1,tag2,tag3进行测试。", response = Pet.class, responseContainer = "List", authorizations = @Authorization(value = "petstore_auth", scopes = { @AuthorizationScope(scope = "write_pets", description = ""), @AuthorizationScope(scope = "read_pets", description = "") })) @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid tag value")}) @Deprecated /** TODO: This renders the parameter as "name": "tags", "in": "query", "description": "Tags to filter by", "required": false, "type": "array", "items": {"type": "string"}, "collectionFormat": "multi" */ public ResponseEntity<List<Pet>> findPetsByTags( @ApiParam( value = "Tags to filter by", required = true, allowMultiple = true) @RequestParam("tags") String tags) { return Responses.ok(petData.findPetByTags(tags)); } static class PetRepository extends MapBackedRepository<Long, Pet> { public List<Pet> findPetByStatus(String status) { return where(Pets.statusIs(status)); } public List<Pet> findPetByTags(String tags) { return where(Pets.tagsContain(tags)); } } } 3.执行maven命令来生成文档 生成文档命令:maven test 或者maven install 如果是eclipse的话通过maven插件可以选中项目右键选择maven test即可或许你们会说为啥并没有Word,但是我们有PDF就够了啊。首选把PDF文件复制出来打开看看效果:文档导出效果还是不错的。接下来将PDF转换为Word,如果你安装了微软的office (我这里是office 2016按理说10,13版本都可以未做测试)Word打开效果:并且通过红色文字可以看到文档是支持编辑的。整体效果也还不错。只需要配置好在线文档那么离线文档也OK了。提示:源码下载地址 地址:spring-swagger2markup-demo-master.zip
  • spring boot REST 通过Swagger2生成接口文档(含例子源码下载)

    【重要提示】:目前已有更好的方法,可以参考:Swagger2 导出离线 word文档一、使用背景    如今,REST和微服务已经有了很大的发展势头【重要提示】:目前已有更好的方法,可以参考:Swagger2 导出离线 word文档一、使用背景    如今,REST和微服务已经有了很大的发展势头。但是,REST规范中并没有提供一种规范来编写我们的对外REST接口API文档。每个人都在用自己的方式记录api文档,因此没有一种标准规范能够让我们很容易的理解和使用该接口。我们需要一个共同的规范和统一的工具来解决文档的难易理解文档的混乱格式。    Swagger(在谷歌、IBM、微软等公司的支持下)做了一个公共的文档风格来填补上述问题。在本博客中,我们将会学习怎么使用Swagger的swagger 2注解去生成REST API文档。二、本博客将会讲解以下内容什么是Swagger?项目结构和技术堆栈创建REST api文档Swagger2的配置Swagger2注释的使用一个简单的例子项目源码下载:spring-boot-swagger2.zip三、什么是Swagger?     Swagger(现在是“开放API计划”)是一种规范和框架,它使用一种人人都能理解的通用语言来描述REST API。还有其他一些可用的框架,比如RAML、求和等等,但是,考虑到它在开发者社区中的特性和接受度,在这个时候,Swagger是最受欢迎的。    它提供了人类可读和机器可读的文档格式。它提供了JSON和UI支持。JSON可以用作机器可读的格式,而 Swagger-UI 是用于可视显示的,通过浏览api文档,人们很容易理解它。四、项目结构和技术堆栈   项目结构图如下:  我们将在这个演示中使用下面的技术Eclipse开发工具Maven 构建工具Spring Boot 应用框架Spring Rest 的REST API框架Swagger2 来作为REST API文档框架Java 1.8五、创建REST api     我们将首先创建一些REST api接口,这些api接口将用于演示Swagger的文档功能。我们将使用Spring boot风格来显示rest API,以获得更快的开发时间。    1.去spring boot官网创建一个web带Rest接口依赖的spring boot项目。提供其他maven GAV坐标并下载该项目。这个屏幕看起来是这样的:    解压缩并将项目导入到Eclipse中,作为现有的maven项目。在此步骤中,将从maven存储库下载所有必需的依赖项。在这个步骤中执行一个新的mvn清洁安装,这样所有spring boot相关的依赖组件都得到了正确的下载。2.打开application.properties配置文件。添加以下属性。他将会从 /swagger2-democontext 路径启动应用.server.contextPath=/swagger2-demo 3.添加一个REST的contrller,名称为Swagger2DemoRestController,他将会为学生实体提供基本的基于REST的功能。Swagger2DemoRestController.javapackage com.example.springbootswagger2.controller; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.example.springbootswagger2.model.Student; @RestController public class Swagger2DemoRestController { List<Student> students = new ArrayList<Student>(); { students.add(new Student("Sajal", "IV", "India")); students.add(new Student("Lokesh", "V", "India")); students.add(new Student("Kajal", "III", "USA")); students.add(new Student("Sukesh", "VI", "USA")); } @RequestMapping(value = "/getStudents") public List<Student> getStudents() { return students; } @RequestMapping(value = "/getStudent/{name}") public Student getStudent(@PathVariable(value = "name") String name) { return students.stream().filter(x -> x.getName().equalsIgnoreCase(name)).collect(Collectors.toList()).get(0); } @RequestMapping(value = "/getStudentByCountry/{country}") public List<Student> getStudentByCountry(@PathVariable(value = "country") String country) { System.out.println("Searching Student in country : " + country); List<Student> studentsByCountry = students.stream().filter(x -> x.getCountry().equalsIgnoreCase(country)) .collect(Collectors.toList()); System.out.println(studentsByCountry); return studentsByCountry; } @RequestMapping(value = "/getStudentByClass/{cls}") public List<Student> getStudentByClass(@PathVariable(value = "cls") String cls) { return students.stream().filter(x -> x.getCls().equalsIgnoreCase(cls)).collect(Collectors.toList()); } }Student.javapackage com.example.springbootswagger2.model; public class Student { private String name; private String cls; private String country; public Student(String name, String cls, String country) { super(); this.name = name; this.cls = cls; this.country = country; } public String getName() { return name; } public String getCls() { return cls; } public String getCountry() { return country; } @Override public String toString() { return "Student [name=" + name + ", cls=" + cls + ", country=" + country + "]"; } } 4.以spring boot方式启动这个程序应用。测试下面的一两个REST端点来检查他们是否正常工作:http://localhost:8080/swagger2-demo/getStudentshttp://localhost:8080/swagger2-demo/getStudent/sajalhttp://localhost:8080/swagger2-demo/getStudentByCountry/indiahttp://localhost:8080/swagger2-demo/getStudentByClass/v六、配置Swagger2 我们的REST api已经准备好了。现在,我们为项目增加swagger 2 的支持6.1首先添加Swagger2 的maven依赖库 打开项目中的pom.xml文件,添加以下两个swagger依赖。springfox-swagger2 、springfox-swagger-ui<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.1</version> </dependency>提示:实际上,Swagger的API有两种类型,并在不同的工件中维护。今天我们将使用springfox,因为这个版本可以很好地适应任何基于spring的配置。我们还可以很容易地尝试其他配置,这应该提供相同的功能——配置中没有任何变化。6.2添加Swagger2配置 使用Java config的方式添加配置。为了帮助你理解这个配置,我在代码中写了相关的注释package com.example.springbootswagger2.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import com.google.common.base.Predicates; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class Swagger2UiConfiguration extends WebMvcConfigurerAdapter { @Bean public Docket api() { // @formatter:off //Register the controllers to swagger //Also it is configuring the Swagger Docket return new Docket(DocumentationType.SWAGGER_2).select() // .apis(RequestHandlerSelectors.any()) .apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot"))) // .paths(PathSelectors.any()) // .paths(PathSelectors.ant("/swagger2-demo")) .build(); // @formatter:on } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //enabling swagger-ui part for visual documentation registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); } }6.3验证Swagger2的JSON格式文档     maven构建并启动服务器。打开链接http://localhost:8080/swagger2-demo/v2/api-docs,会生成一个JSON格式的文档。这并不是那么容易理解和理解的,实际上Swagger已经提供该文档在其他三方工具中使用,例如当今流行的API管理工具,它提供了API网关、API缓存、API文档等功能。6.4验证Swagger2 UI文档     打开链接 http://localhost:8080/swagger2-demo/swagger-ui.html 在浏览器中来查看Swagger UI文档6.5Swagger2 注解的使用 默认生成的API文档很好,但是它们缺乏详细的API级别信息。Swagger提供了一些注释,可以将这些详细信息添加到api中。如。@Api –我们可以添加这个注解在controller上,去添加一个基本的controller说明@Api(value = "Swagger2DemoRestController", description = "REST APIs related to Student Entity!!!!") @RestController public class Swagger2DemoRestController { //... } @ApiOperation and @ApiResponses – 我们添加这个注解到任何controller的rest方法上来给方法添加基本的描述。例如:@ApiOperation(value = "Get list of Students in the System ", response = Iterable.class, tags = "getStudents") @ApiResponses(value = { @ApiResponse(code = 200, message = "Success|OK"), @ApiResponse(code = 401, message = "not authorized!"), @ApiResponse(code = 403, message = "forbidden!!!"), @ApiResponse(code = 404, message = "not found!!!") }) @RequestMapping(value = "/getStudents") public List<Student> getStudents() { return students; } 在这里,我们可以向方法中添加标签,来在swagger-ui中添加一些分组。@ApiModelProperty – 这个注解用来在数据模型对象中的属性上添加一些描述,会在Swagger UI中展示模型的属性。例如:@ApiModelProperty(notes = "Name of the Student",name="name",required=true,value="test name") private String name; Controller 和 Model 类添加了swagger2注解之后,代码清单:Swagger2DemoRestController.javapackage com.example.springbootswagger2.controller; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.example.springbootswagger2.model.Student; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; @Api(value = "Swagger2DemoRestController", description = "REST Apis related to Student Entity!!!!") @RestController public class Swagger2DemoRestController { List<Student> students = new ArrayList<Student>(); { students.add(new Student("Sajal", "IV", "India")); students.add(new Student("Lokesh", "V", "India")); students.add(new Student("Kajal", "III", "USA")); students.add(new Student("Sukesh", "VI", "USA")); } @ApiOperation(value = "Get list of Students in the System ", response = Iterable.class, tags = "getStudents") @ApiResponses(value = { @ApiResponse(code = 200, message = "Suceess|OK"), @ApiResponse(code = 401, message = "not authorized!"), @ApiResponse(code = 403, message = "forbidden!!!"), @ApiResponse(code = 404, message = "not found!!!") }) @RequestMapping(value = "/getStudents") public List<Student> getStudents() { return students; } @ApiOperation(value = "Get specific Student in the System ", response = Student.class, tags = "getStudent") @RequestMapping(value = "/getStudent/{name}") public Student getStudent(@PathVariable(value = "name") String name) { return students.stream().filter(x -> x.getName().equalsIgnoreCase(name)).collect(Collectors.toList()).get(0); } @ApiOperation(value = "Get specific Student By Country in the System ", response = Student.class, tags = "getStudentByCountry") @RequestMapping(value = "/getStudentByCountry/{country}") public List<Student> getStudentByCountry(@PathVariable(value = "country") String country) { System.out.println("Searching Student in country : " + country); List<Student> studentsByCountry = students.stream().filter(x -> x.getCountry().equalsIgnoreCase(country)) .collect(Collectors.toList()); System.out.println(studentsByCountry); return studentsByCountry; } // @ApiOperation(value = "Get specific Student By Class in the System ",response = Student.class,tags="getStudentByClass") @RequestMapping(value = "/getStudentByClass/{cls}") public List<Student> getStudentByClass(@PathVariable(value = "cls") String cls) { return students.stream().filter(x -> x.getCls().equalsIgnoreCase(cls)).collect(Collectors.toList()); } } Student.javapackage com.example.springbootswagger2.model; import io.swagger.annotations.ApiModelProperty; public class Student { @ApiModelProperty(notes = "Name of the Student",name="name",required=true,value="test name") private String name; @ApiModelProperty(notes = "Class of the Student",name="cls",required=true,value="test class") private String cls; @ApiModelProperty(notes = "Country of the Student",name="country",required=true,value="test country") private String country; public Student(String name, String cls, String country) { super(); this.name = name; this.cls = cls; this.country = country; } public String getName() { return name; } public String getCls() { return cls; } public String getCountry() { return country; } @Override public String toString() { return "Student [name=" + name + ", cls=" + cls + ", country=" + country + "]"; } }七、例子 现在,当我们的REST api得到适当的注释时,让我们看看最终的输出。打开http://localhost:8080 / swagger2-demo / swagger-ui。在浏览器中查看Swagger ui 文档。
  • Swagger Spring Boot Stater

    Swagger Spring Boot Stater简介spring boot 整合 springfox 实现swagger api文档生成Swagger Spring Boot Stater简介spring boot 整合 springfox 实现swagger api文档生成。本项目主要简化整合流程,达到开箱即用,无需更多java代码配置。swagger使用说明Spring Boot项目(兼容 2.2.0-2.4.0)引入依赖<dependency> <groupId>net.ifok.swagger</groupId> <artifactId>swagger-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> 提示: 1.3.0 有两个ui界面,http://localhost:8080/doc.html 和http://localhost:8080/swagger-ui.htmlSpring Boot 介于2.0.0-2.20之间,引入方式方法一: <properties> ...其他 <spring-plugin.version>2.0.0.RELEASE</spring-plugin.version> </properties> 在pom.xml的properties节点添加<spring-plugin.version>2.0.0.RELEASE</spring-plugin.version> 然后引入<dependency> <groupId>net.ifok.swagger</groupId> <artifactId>swagger-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> 方法二:<dependency> <groupId>net.ifok.swagger</groupId> <artifactId>swagger-spring-boot-starter</artifactId> <version>1.3.0</version> <exclusions> <exclusion> <groupId>org.springframework.plugin</groupId> <artifactId>spring-plugin-core</artifactId> </exclusion> <exclusion> <groupId>org.springframework.plugin</groupId> <artifactId>spring-plugin-metadata</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.plugin</groupId> <artifactId>spring-plugin-core</artifactId> <version>2.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.plugin</groupId> <artifactId>spring-plugin-metadata</artifactId> <version>2.0.0.RELEASE</version> </dependency> Spring Boot 配置说明单组配置spring.swagger.url-pattern=/** spring.swagger.packages= spring.swagger.api-title=API开放文档 spring.swagger.api-description=Api 接口说明 spring.swagger.terms-of-service-url= spring.swagger.contact.name=联系人名 spring.swagger.contact.email=abc@qq.com spring.swagger.contact.url=wwww.baidu.com spring.swagger.license=Apache 2 spring.swagger.license-url= 提示: spring.swagger.config.packages 与 spring.swagger.config.url-pattern 可以只选择其中一个配置,如果两个同时配置则回取两个的并集。多组别配置#A组 spring.swagger.group.aaa.group-name=A组名称 spring.swagger.group.aaa.url-pattern=/aaa/** spring.swagger.group.aaa.packages= spring.swagger.group.aaa.api-title=A分组API spring.swagger.group.aaa.api-description=A分组API主要用于干xxx spring.swagger.group.aaa.terms-of-service-url= spring.swagger.group.aaa.contact.name=联系人名 spring.swagger.group.aaa.contact.email=abc@qq.com spring.swagger.group.aaa.contact.url=wwww.baidu.com spring.swagger.group.aaa.license=Apache 2 spring.swagger.group.aaa.license-url= #B组 spring.swagger.group.bbb.group-name=B组名称 spring.swagger.group.bbb.url-pattern=/bbb/** spring.swagger.group.bbb.packages= spring.swagger.group.bbb.api-title=B分组API spring.swagger.group.bbb.api-description=B分组API主要用于干xxx spring.swagger.group.bbb.terms-of-service-url= spring.swagger.group.bbb.contact.name=联系人名 spring.swagger.group.bbb.contact.email=abc@qq.com spring.swagger.group.bbb.contact.url=wwww.baidu.com spring.swagger.group.bbb.license=Apache 2 spring.swagger.group.bbb.license-url= 注意:当同时配置了多分组和单分组,单分组将会无效!Springfox相关注解使用说明Spring 项目的controller类,添加@Api(tags="该controller的处理说明")@Api(tags = "用户相关操作") public class UserController { @ApiOperation("添加用户") public Object addUser(){ return "success"; } } Spring 项目的controller类,方法添加 @ApiOpertion("该接口说明")未完待续更多参考http://springfox.github.io/springfox/https://github.com/springfox/springfoxLICENSEApache Software License, Version 2.0
  • Spring Boot Security Swagger2整合生成安全的在线REST API文档 SpringMVC也可参考

    创建REST API时,良好的文档是有帮助的。而且,API中的每一个变化都应该在参考文档中同时描述。手动完成这是一个乏味的操作,因此这个过程的自动化是不可避免的。<h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>1.概述</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">创建REST API时,良好的文档是有帮助的。</span></span></span><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">而且,API中的每一个变化都应该在参考文档中同时描述。手动完成这是一个乏味的操作,因此这个过程的自动化是不可避免的。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在本教程中,我们将看看  <strong>Swagger 2的Spring Boot REST Web服务。</strong>对于本文,我们将使用Swagger 2规范的  <strong>Springfox </strong>实现。如果您对Swagger不熟悉,则应 在继续阅读本文之前访问<a href="http://swagger.io/" rel="external nofollow" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">swagger官网</a>以了解更多信息。</span></span></span><br />  </p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.项目说明</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们在示例中使用的REST服务的创建不在本文的讨论范围之内。如果您已经有合适的项目,请使用它。如果没有,下面的链接是一个很好的开始:</span></span></span></p> <ul style="list-style-type:disc"> <li>使用Spring 4和Java Config文章构建REST API</li> <li>构建一个RESTful Web服务</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><strong>提示:创建Spring Boot REST项目可以参考之前写的<a rel="" target="_blank"href="http://www.leftso.com/blog/223.html" rel="" target="_blank">Swagger2入门篇</a></strong></p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><br /> <strong>3.添加Maven依赖项</strong></h2> 这里我们只说需要额外添加的maven依赖。Spring Boot REST项目本身的依赖决定于您自身的项目,暂时不在讨论之内。上一篇我们使用的swagger 版本为2.6.2这里我们将会使用比较新的2.7.0 <pre> <code class="language-xml"><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency></code></pre> <blockquote> <p>提示:现在已经有2.8.0版本。目前存在一些无法汉化的问题。暂不推荐正式项目升级。学习研究即可。</p> </blockquote> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>4.将Swagger 2集成到项目中</strong></h2> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>4.1。Java配置</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">Swagger的配置主要围绕着  <em><strong>Docket</strong></em> bean。</span></span></span></p> <pre> <code class="language-java">@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build(); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">Swagger 2通过<strong>@ EnableSwagger2</strong><em> </em>批注启用 。</span></span></span><br /> <br /> <span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在定义了<em>Docket</em> bean 之后,其  <strong>select()</strong>  方法返回一个<strong>ApiSelectorBuilder</strong>实例,该实例提供了一种控制Swagger公开的端点的方法。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">可以使用<strong>RequestHandlerSelectors</strong>和<strong>PathSelectors</strong>来配置<em>RequestHandler</em>选择的谓词。使用  <em>任何()</em>  都可以通过Swagger为整个API提供文档。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">这种配置足以将Swagger 2集成到现有的Spring Boot项目中。对于其他Spring项目,需要进行一些额外的调整。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>4.2。项目不是Spring Boot的配置</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果没有Spring Boot,你无法自动配置资源处理程序。Swagger UI添加了一组资源,您必须将其配置为扩展<em>WebMvcConfigurerAdapter</em>的类的一部分  <em>,</em>  并使用<em>@EnableWebMvc进行</em>注释  <em>。</em></span></span></span></p> <pre> <code class="language-java">@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); }</code></pre>   <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>4.3。验证Springfox是否正常工作</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">要验证Springfox是否正常工作,可以在浏览器中访问以下URL:</span></span></span></p> <pre> <code class="language-html">​​​​​​​http://localhost:8080/spring-security-rest/api/v2/api-docs</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">结果是带有大量键值对的JSON响应,这不是非常容易理解的。幸运的是,Swagger 为此提供了<strong>Swagger UI</strong>。</span></span></span></p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>5. Swagger UI</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">Swagger UI是一个内置的解决方案,使得用户可以更轻松地与Swagger生成的API文档进行交互。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>5.1。启用S​​pringfox的Swagger UI</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">要使用Swagger UI,需要另外一个Maven依赖项:</span></span></span></p> <pre> <code class="language-xml"><dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version> </dependency></code></pre> 现在,您可以通过访问<em>http://localhost:8080/your-app-root/swagger-ui.html</em><span style="color:#535353; font-family:raleway">在浏览器中对其进行测试</span> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>在我们的例子中,顺便说一下,确切的URL是</strong></span></span></span><em>http://localhost:8080/spring-security-rest/api/swagger-ui.html</em></p> 结果应该如下所示:<br /> <img alt="swagger2 UI结果展示" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2018-04/87611d78ac3145fbacc0fbe040cd8b8b.png" /><br />   <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>5.2。学习Swagger文档</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">Swagger的回复中<strong>列出了</strong>您的应用程序中定义<strong>的所有控制器</strong>。点击其中的任何一个将列出有效的HTTP方法(<em>DELETE</em>,<em>GET</em>,<em>HEAD</em>,<em>OPTIONS</em>,<em>PATCH</em>,<em>POST</em>,<em>PUT</em>)。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">展开每种方法都会提供其他有用的数据,例如响应状态,内容类型和参数列表。也可以使用UI来尝试每种方法。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">Swagger与您的代码库同步的能力至关重要。为了演示这一点,你可以添加一个新的控制器到你的应用程序。</span></span></span></p> <pre> <code class="language-java">@RestController public class CustomController { @RequestMapping(value = "/custom", method = RequestMethod.POST) public String custom() { return "custom"; } }</code></pre> 现在,如果刷新Swagger文档,您将在控制器列表中看到<strong>自定义</strong>控制器。如您所知,Swagger的回复中只显示一种方法(<em>POST</em>)。 <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.高级配置</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">应用程序的<em>Docket</em> bean可以配置为让您更多地控制API文档生成过程。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.1。过滤Swagger响应的API</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">公开整个API的文档并不总是可取的。您可以通过将参数传递给<em>Docket</em>类的<em><strong>apis()</strong></em>和<em><strong>paths()</strong></em>方法来限制Swagger的响应  。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如上所示,<em>RequestHandlerSelectors</em>允许使用  <em>any</em>或<em>none</em>谓词,但也可用于根据基本包,类注释和方法注释过滤API。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><em><strong>PathSelectors</strong></em>提供了额外的过滤功能,并使用谓词来扫描应用程序的请求路径。你可以使用 <em> any()</em>,<em>none(),  </em><em>regex()</em>或 <em> ant()</em>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在下面的示例中,我们将指示Swagger使用<em>ant()</em>  谓词仅包含特定包中的控制器,并使用特定的路径。</span></span></span><br />  </p> <pre> <code class="language-java">@Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("org.baeldung.web.controller")) .paths(PathSelectors.ant("/foos/*")) .build(); }</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.2。自定义信息</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">Swagger还在您的自定义响应中提供了一些默认值,例如“Api文档”,“由联系人电子邮件创建”,“Apache 2.0”。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">要更改这些值,可以使用  <strong><em>apiInfo(ApiInfo apiInfo) </em></strong>方法。包含有关API的自定义信息的  <strong><em>ApiInfo</em></strong>类。</span></span></span></p> <pre> <code class="language-java">@Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("com.example.controller")) .paths(PathSelectors.ant("/foos/*")) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { return new ApiInfo( "My REST API", "Some custom description of API.", "API TOS", "Terms of service", new Contact("John Doe", "www.example.com", "myeaddress@company.com"), "License of API", "API license URL", Collections.emptyList()); }</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.3。自定义方法响应消息</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">Swagger允许通过  <em>Docket</em>的  <strong><em>globalResponseMessage()</em></strong>方法<strong>全局覆盖HTTP方法的响应消息</strong>。首先,您必须指示Swagger不要使用默认响应消息。<strong> </strong></span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">假设您希望覆盖  所有<em>GET</em>方法的<strong>500</strong>和<strong>403</strong>响应消息。为了达到这个目的,一些代码必须被添加到<em>Docket</em>的初始化块(为了清楚起见,原始冗余代码被排除):</span></span></span></p> <pre> <code class="language-java">.useDefaultResponseMessages(false) .globalResponseMessage(RequestMethod.GET, newArrayList(new ResponseMessageBuilder() .code(500) .message("500 message") .responseModel(new ModelRef("Error")) .build(), new ResponseMessageBuilder() .code(403) .message("Forbidden!") .build()));</code></pre> <img alt="swagger UI 2" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2018-04/62c77efb299f44e3a2c90d0326531f2f.png" /> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>7.具有OAuth安全API的Swagger UI</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">Swagger UI提供了许多非常有用的功能 - 目前为止我们已经介绍了这些功能。但是如果我们的API是安全的并且不可访问的话,我们不能真正使用其中的大部分。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">让我们看看我们如何允许Swagger访问OAuth安全的API--在本例中使用授权代码授权类型。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们将使用<em>SecurityScheme</em>和<em>SecurityContext</em>支持配置Swagger以访问我们的安全API  :</span></span></span></p> <pre> <code class="language-java">@Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2).select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build() .securitySchemes(Arrays.asList(securityScheme())) .securityContexts(Arrays.asList(securityContext())); }</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>7.1。安全配置</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们将在Swagger配置中定义一个  <em>SecurityConfiguration</em> bean - 并设置一些默认值:</span></span></span></p> <pre> <code class="language-java">@Bean public SecurityConfiguration security() { return SecurityConfigurationBuilder.builder() .clientId(CLIENT_ID) .clientSecret(CLIENT_SECRET) .scopeSeparator(" ") .useBasicAuthenticationWithAccessCodeGrant(true) .build(); }</code></pre>   <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>7.2。<em>SecurityScheme</em></strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">接下来,我们将定义我们的<em>SecurityScheme</em> ; 这用于描述我们的API如何保护(基本认证,OAuth2,...)。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在我们的例子中,我们将定义一个用于保护我们的资源服务器的OAuth方案:</span></span></span></p> <pre> <code class="language-java">private SecurityScheme securityScheme() { GrantType grantType = new AuthorizationCodeGrantBuilder() .tokenEndpoint(new TokenEndpoint(AUTH_SERVER + "/token", "oauthtoken")) .tokenRequestEndpoint( new TokenRequestEndpoint(AUTH_SERVER + "/authorize", CLIENT_ID, CLIENT_ID)) .build(); SecurityScheme oauth = new OAuthBuilder().name("spring_oauth") .grantTypes(Arrays.asList(grantType)) .scopes(Arrays.asList(scopes())) .build(); return oauth; }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">请注意,我们使用了授权码授权类型 - 我们需要为其提供令牌端点以及我们的OAuth2授权服务器的授权URL。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">以下是我们需要定义的范围:</span></span></span></p> <pre> <code class="language-java">private AuthorizationScope[] scopes() { AuthorizationScope[] scopes = { new AuthorizationScope("read", "for read operations"), new AuthorizationScope("write", "for write operations"), new AuthorizationScope("foo", "Access foo API") }; return scopes; }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">这些与我们在应用中实际定义的范围同步<em>/ foos</em> API。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>7.3。Security Context</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">最后,我们需要为我们的示例API定义一个安全上下文:</span></span></span></p> <pre> <code class="language-java">private SecurityContext securityContext() { return SecurityContext.builder() .securityReferences(Arrays.asList(new SecurityReference("spring_oauth", scopes()))) .forPaths(PathSelectors.regex("/foos.*")) .build(); }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">请注意,我们在此处使用的名称(参考 -  <em>spring_oauth)</em>与我们之前使用的名称在<em>SecurityScheme中</em>同步。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>7.4。测试</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">好吧,现在我们已经准备好了所有的东西,让我们来看看我们的Swagger UI并尝试访问Foo API:</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们可以在本地访问Swagger UI:</span></span></span></p> <div style="text-align:start"> <div style="margin-left:0px; margin-right:0px"> <table cellspacing="0" class="table table-bordered table-hover" style="background:0px 0px !important; border-collapse:collapse; border-radius:0px !important; border-spacing:0px; border:0px !important; bottom:auto !important; box-sizing:content-box !important; float:none !important; font-family:"source code pro",consolas,"bitstream vera sans mono","courier new",Courier,monospace !important; font-size:14px !important; font-style:normal !important; font-weight:300 !important; height:auto !important; left:auto !important; line-height:1.43 !important; margin:0px !important; min-height:auto !important; outline:0px !important; overflow:visible !important; padding:0px !important; position:static !important; right:auto !important; text-align:left !important; top:auto !important; vertical-align:baseline !important; width:871px"> <tbody> <tr> <td style="width:auto !important"> <div style="text-align:left !important"><span style="color:#333333"><span style="font-family:raleway"><span style="background-color:#ffffff"><span style="background-color:#ffffff !important"><span style="font-family:"source code pro",consolas,"bitstream vera sans mono","courier new",Courier,monospace !important"><span style="font-family:"source code pro",consolas,"bitstream vera sans mono","courier new",Courier,monospace !important"><span style="color:#afafaf !important">1</span></span></span></span></span></span></span></div> </td> <td style="width:838px"> <div style="text-align:left !important"> <div style="text-align:left !important"><span style="color:#333333"><span style="font-family:raleway"><span style="background-color:#ffffff"><span style="background-color:#ffffff !important"><span style="font-family:"source code pro",consolas,"bitstream vera sans mono","courier new",Courier,monospace !important"><span style="font-family:"source code pro",consolas,"bitstream vera sans mono","courier new",Courier,monospace !important"><span style="font-family:"source code pro",consolas,"bitstream vera sans mono","courier new",Courier,monospace !important"><code>http:</code><code>//localhost</code><code>:8082</code><code>/spring-security-oauth-resource/swagger-ui</code><code>.html</code></span></span></span></span></span></span></span></div> </div> </td> </tr> </tbody> </table> </div> </div> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">由于我们的安全配置,我们可以看到现在存在一个新的“授权”按钮:</span></span></span></p> <img alt="swagger ui security" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2018-04/55027912a7f74e8f9c167b2fced6d4d8.png" /><br /> <br /> 当我们点击“授权”按钮时,我们可以看到以下弹出窗口 - 授权我们的Swagger UI访问安全的API:<br /> <img alt="swagger ui security 2" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2018-04/30d144368b694459bfcb3f386633e1fa.png" /> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">注意:</span></span></span></p> <ul style="list-style-type:disc"> <li>我们已经可以看到CLIENT_ID和CLIENT_SECRET了 - 因为我们已经预先配置了它们(但我们仍然可以更改它们)</li> <li>我们现在可以选择我们需要的范围</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">以下是安全API的标记方式:<br /> <img alt="swagger ui security" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2018-04/b1e5e9e7b818409486ad8b3e78b98583.png" /></span></span></span><br />  </p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">现在,最后,我们可以打我们的API!</span></span></span><br /> <span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">当然,不言而喻,我们需要小心如何在外部公开Swagger UI,因为此安全配置处于活动状态。</span></span></span></p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>8.总结</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在本教程中,我们设置了Swagger 2来为Spring REST API生成文档。我们还探索了可视化和自定义Swagger输出的方法。最后,我们查看了Swagger的一个简单的OAuth配置。</span></span></span></p>
  • HTTP协议2.0_HTTP2.0新特性

    HTTP协议2.0,HTTP 2.0如何升级_HTTP2.0新特性_HTTP2.0详解。<h2>引用</h2>   本文主要讲述HTTP协议2.0版本,以及<a rel="external nofollow" target="_blank" id="http2.0" name="http2.0">HTTP协议2.0</a>的新特性说明 <h2>一.开篇HTTP发展的心路历程</h2> <br /> <img alt="开篇HTTP发展的心路历程,1" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/76f5c3db6d6843809b1f42d62f0f8a6d.png" /><br /> 上图:连接无法复用<br /> <img alt="HTTP 协议 订单流程" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/e77a5ee7ca904be584f248722782ccfb.png" /><br /> 上图:设置Connection:Keep-Alive,保持连接在一段时间内不断开。<br /> <img alt="HTTP协议多个订单" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/f260aa472f694465ba83da7498272ade.png" /><br /> 上图:HTTPpipelining:建立多个连接<br /> <img alt="HTTP多路复用" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/af6c10458a3146fdb9bc4b8b0254deed.png" /><br /> 上图:多路复用 <h2>二.先对HTTP协议进行简单介绍</h2> <p>   1. HTTP协议 :Hyper Text Transfer Protocol(超文本传输协议),是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。</p> <p>    2. HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。</p> <p>   3. HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。</p> <p>   4. HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。<br /> <img alt="Http协议客户端和服务端" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/bd2f47f787154d74a164ca4cdc3cb381.png" /></p> <h2>三.HTTP 协议的版本</h2> <ul> <li>HTTP 0.9作为HTTP协议的第一个版本。是非常弱的。请求(Request)只有一行,比如: GET www.leautolink.com</li> <li>HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较为简单的网页上和网络请求上。</li> <li>HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使用最为广泛的HTTP协议。</li> </ul> <img alt="HTTP协议版本" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/be03a1e810d5455483dd40e6c644428e.png" /><br />   <p><strong>HTTP 1.1 做了哪些升级:</strong></p> <p> </p> <ul> <li> <p><strong>缓存处理</strong>,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。</p> </li> <li> <p><strong>带宽优化及网络连接的使用</strong>,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。</p> </li> <li> <p><strong>错误通知的管理</strong>,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。</p> </li> <li> <p><strong>Host头处理</strong>,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。</p> </li> <li> <p><strong>长连接</strong>,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。</p> </li> </ul> <p><strong>如何建立连接(三次握手)</strong></p> <p>    HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。</p> <ul> <li> <p><strong>第一次</strong><strong>握手:</strong>建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。</p> </li> <li> <p><strong>第二次握手:</strong>服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;</p> </li> <li> <p><strong>第三次握手:</strong>客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。</p> </li> </ul> <p><strong>完成三次握手,客户端与服务器开始传送数据。</strong></p> <img alt="HTTP协议三次握手流程图" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/5891e7762d3843e8aaf04edf552f6930.png" /> <p><strong>如何关闭连接(四次挥手):</strong></p> <p> </p> <p>    由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。</p> <p> </p> <p>     TCP的连接的拆除需要发送四个包,因此称为<strong>四次挥手(four-way handshake)</strong>。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。</p> <p> </p> <ol> <li> <p>客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。 </p> </li> <li> <p>服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。 </p> </li> <li> <p>服务器B关闭与客户端A的连接,发送一个FIN给客户端A。 </p> </li> <li> <p>客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。 <br /> <img alt="HTTP 第三次和第四次握手" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/7314195885b54567bac1275375c419fe.png" /><br />  </p> </li> </ol> <p><strong>浏览器阻塞(HOL blocking):</strong></p> <p>   浏览器对于同一个域名,一般PC端浏览器会针对单个域名的server同时建立6~8个连接,手机端的连接数则一般控制在4~6个(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞。</p> <h2>三.在讲HTTP/2之前我们先来说说SPDY</h2> <p>  SPDY协议是Google提出的基于传输控制协议(TCP)的应用层协议,通过压缩、多路复用和优先级来缩短加载时间。该协议是一种更加快速的内容传输协议,于2009 年年中发布。</p> <p>  GoogleChrome、MozillaFirefox以及Opera已默认开启SPDY。Google曾经称它的测试显示,页面载入提高了一倍。该协议是一种更加快速的内容传输协议。</p> <p><strong>SPDY协议设定的目标</strong></p> <p>    1. 页面加载时间(PLT,Page • Load Time)降低 50%;</p> <p>    2. 无需网站作者修改任何内容;</p> <p>    3. 最小化配置复杂度,无需变更网络基础设施;</p> <p>注:为了达到降低50% 页面加载时间的目标,SPDY 引入了一个新的二进制分帧数据层,以实现多向请求和响应、优先次序、最小化及消除不必要的网络延迟,目的是更有效地利用底层TCP 连接;</p> <h2>四.HTTP/2:SPDY的升级版</h2> <ul> <li> <p>HTTP-WG(HTTP Working Group)在2012 年初把HTTP 2.0提到了议事日程,吸取SPDY 的经验教训,并在此基础上制定官方标准。</p> </li> <li> <p>HTTP/2 的主要目标是改进传输性能,更有效地利用网络资源,实现低延迟和高吞吐量。从另一方面看,HTTP 的高层协议语义并不会因为这次版本升级而受影响。所有HTTP 首部、值,以及它们的使用场景都不会变。</p> </li> <li> <p>HTTP/2 致力于突破上一代标准众所周知的性能限制,但它也是对之前1.x 标准的扩展,而非替代。之所以要递增一个大版本到2.0,主要是因为它改变了客户端与服务器之间交换数据的方式</p> </li> </ul> <p><strong>HTTP/2 是如何提高效率呢?</strong></p> <p><strong>  二进制分帧:HTTP 2.0 的所有帧都采用二进制编码</strong></p> <ul> <li> <p><strong>帧</strong>:客户端与服务器通过交换帧来通信,帧是基于这个新协议通信的最小单位。</p> </li> <li> <p><strong>消息</strong>:是指逻辑上的 HTTP 消息,比如请求、响应等,由一或多个帧组成。</p> </li> <li> <p><strong>流</strong>:流是连接中的一个虚拟信道,可以承载双向的消息;每个流都有一个唯一的整数标识符(1、2…N);</p> </li> </ul> <img alt="HTTP 2.0连接" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/f3e1405c2a1f43c3a8ef78325d360f3b.png" /> <p><strong>多路复用 (Multiplexing)</strong></p> <p>    多路复用允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息。有了新的分帧机制后,HTTP/2 不再依赖多个TCP 连接去实现多流并行了。每个数据流都拆分成很多互不依赖的帧,而这些帧可以交错(乱序发送),还可以分优先级。最后再在另一端把它们重新组合起来。HTTP 2.0 连接都是持久化的,而且客户端与服务器之间也只需要一个连接(<strong>每个域名一个连接</strong>)即可。 </p> <p> </p> <p><strong>请求优先级</strong></p> <ul> <li> <p>把HTTP 消息分解为很多独立的帧之后,就可以通过优化这些帧的交错和传输顺序,每个流都可以带有一个31 比特的优先值:0 表示最高优先级;2的31次方-1 表示最低优先级。</p> </li> <li> <p>服务器可以根据流的优先级,控制资源分配(CPU、内存、带宽),而在响应数据准备好之后,优先将最高优先级的帧发送给客户端。</p> </li> <li> <p>HTTP 2.0 一举解决了所有这些低效的问题:浏览器可以在发现资源时立即分派请求,指定每个流的优先级,让服务器决定最优的响应次序。这样请求就不必排队了,既节省了时间,也最大限度地利用了每个连接。</p> </li> </ul> <p> </p> <p><strong>header压缩</strong></p> <p>    HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP/2使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。</p> <p> </p> <p><strong>服务端推送</strong></p> <ul> <li> <p>服务器可以对一个客户端请求发送多个响应。服务器向客户端推送资源无需客户端明确地请求。</p> </li> <li> <p>HTTP 2.0 连接后,客户端与服务器交换SETTINGS 帧,借此可以限定双向并发的流的最大数量。</p> </li> <li> <p>所有推送的资源都遵守同源策略。换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行。</p> </li> <li> <p>服务器必须遵循请求- 响应的循环,只能借着对请求的响应推送资源</p> </li> </ul> <p> </p> <p><strong>服务器推送到底是什么?</strong></p> <p>    服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。</p> <p> </p> <p>普通的客户端请求过程:<br /> <img alt="普通客户端请求HTTP协议过程" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/98d6549c4dfe4180a51242a61353286a.png" /><br />  </p> 服务端推送的过程:<br /> <img alt="服务端推送的过程" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/b1ca4e63108a42b8a7f49454b948416f.png" /> <p><strong>HTTP/2的多路复用和HTTP1.1中的长连接复用有什么区别?</strong></p> <ul> <li> <p>HTTP/1.0 一次请求-响应,建立一个连接,用完关闭;每一个请求都要建立一个连接;</p> </li> <li> <p>HTTP/1.1 Pipeling解决方式为,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞;</p> </li> <li> <p>HTTP/2多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行;<br /> <img alt="HTTP" class="img-thumbnail" src="/assets/upload/blog/thumbnail/2017-12/ab81f47df21b4aa7941fec0556dcb814.png" /><br />  </p> </li> </ul> <h2>五.如何应用到自己的项目里</h2> <p>  现有的任何网站和应用,无需做任何修改都可以在HTTP 2.0 上跑起来。不用为了利用HTTP 2.0 的好处而修改标记。HTTP 服务器必须运行HTTP 2.0 协议,但大部分用户都不会因此而受到影响。</p> <p>  如果你使用NGINX,只要在配置文件中启动相应的协议就可以了,可以参考NGINX白皮书,NGINX配置HTTP2.0官方指南。</p> <p>  使用了HTTP2.0那么,原本的HTTP1.x怎么办,这个问题其实不用担心,HTTP2.0完全兼容HTTP1.x的语义,对于不支持HTTP2.0的浏览器,NGINX会自动向下兼容的。</p>
  • spring boot 2.0 Redis整合_spring boot 2.0 集成Redis实现缓存框架(一)

    Spring Boot 2.0 Redis整合,通过spring boot 2.0整合Redis作为spring缓存框架的实现。spring boot 2.0 Redis整合_spring boot 2.0 集成Redis实现缓存框架(一)
  • Python教程-Python httplib2 HTTP GET和POST使用详解

    Python httplib2 简介学习使用Python httplib2模块Python httplib2 简介学习使用Python httplib2模块。的超文本传输协议(HTTP)是用于分布式,协作,超媒体信息系统的应用协议。HTTP是万维网数据通信的基础。Python httplib2模块提供了用于通过HTTP访问Web资源的方法。它支持许多功能,例如HTTP和HTTPS,身份验证,缓存,重定向和压缩。检查httplib2库版本第一个程序打印库的版本,其版权和文档字符串。import httplib2 print(httplib2.__version__) print(httplib2.__copyright__) print(httplib2.__doc__)在httplib2.__version__给出的版本httplib2库中,httplib2.__copyright__给出了其版权,以及httplib2.__doc__它的文档字符串。执行上方的代码可能遇到模块未找到错误,如下图:​如果出现上方问题,我们进行安装该模块即可,以下为Python 3.x版本的安装命令pip3 install httplib2 --upgrade 安装过程如下:​httplib2 安装 安装完成后我们再次执行版本检查的代码:​httplib2信息查看  使用httplib2读取网页 在下面的示例中,我们展示了如何从名为http://www.baidu.com的网站获取HTML内容。import httplib2 http = httplib2.Http() content = http.request("http://www.baidu.com")[1] print(content.decode()) 使用创建一个HTTP客户端httplib2.HTTP()。使用该request()方法创建一个新的HTTP请求。默认情况下,它是一个GET请求。返回值是响应和内容的元组。响应部分内容展示:​剥离HTML标签 以下程序获取一个小型网页,并剥离其HTML标签。import httplib2 import re http = httplib2.Http() content = http.request("http://www.baidu.com")[1] stripped = re.sub('<[^<]+?>', '', content.decode()) print(stripped) 一个简单的正则表达式用于剥离HTML标记。请注意,我们正在剥离数据,我们没有对其进行清理。(这是两总不同的情况。)​检查响应状态 响应对象包含一个status给出响应状态代码的属性。import httplib2 http = httplib2.Http() resp = http.request("http://www.baidu.com")[0] print(resp.status) resp = http.request("http://www.leftso.com/blog/0.html")[0] print(resp.status) 我们使用request()方法执行两个HTTP请求,并检查返回的状态。​200是成功HTTP请求的标准响应,而404则表明找不到所请求的资源。发送HTTP HEAD请求 HTTP HEAD方法检索文档标题。标头由字段组成,包括日期,服务器,内容类型或上次修改时间。import httplib2 http = httplib2.Http() resp = http.request("http://www.leftso.com/assist/images/carousel/855892C7F4734F3CB0721835573BAD07.jpg", "HEAD")[0] print("Server: " + resp['server']) print("Last modified: " + resp['last-modified']) print("Content type: " + resp['content-type']) print("Content length: " + resp['content-length']) ​这是程序的输出。从输出中,我们可以看到该网页是由FreeBSD托管的Apache Web服务器交付的。该文档的最后修改时间是1999年。网页是HTML文档,其长度为72个字节。发送HTTP GET请求 HTTP GET方法请求指定资源的表示形式。对于此示例,我们还将使用greet.php脚本:<?php echo "Hello " . htmlspecialchars($_GET['name']); ?> 在/usr/share/nginx/html/目录中,我们有此greet.php文件。该脚本返回name变量的值,该值是从客户端检索到的。该htmlspecialchars()函数将特殊字符转换为HTML实体;例如&到&amp.。import httplib2 http = httplib2.Http() content = http.request("http://localhost/greet.php?name=Peter", method="GET")[1] print(content.decode()) 该脚本将带有值的变量发送到服务器上的PHP脚本。该变量直接在URL中指定。Hello Peter 这是示例的输出。127.0.0.1 - - [21/Aug/2016:17:32:31 +0200] "GET /greet.php?name=Peter HTTP/1.1" 200 42 "-" "Python-httplib2/0.8 (gzip)" 我们检查了nginx访问日志。发送HTTP POST请求 POST请求方法请求Web服务器接受并存储请求消息正文中包含的数据。上载文件或提交完整的Web表单时经常使用它。<?php echo "Hello " . htmlspecialchars($_POST['name']); ?> 在本地Web服务器上,我们有此target.php文件。它只是将过帐的值打印回客户。import httplib2 import urllib http = httplib2.Http() body = {'name': 'Peter'} content = http.request("http://localhost/target.php", method="POST", headers={'Content-type': 'application/x-www-form-urlencoded'}, body=urllib.parse.urlencode(body) )[1] print(content.decode()) 脚本发送name带有Peter值的键的请求。数据使用urllib.parse.urlencode()方法进行编码,并在请求的正文中发送。Hello Peter 这是mpost.py脚本的输出。 127.0.0.1 - - [23/Aug/2016:12:21:07 +0200] "POST /target.php HTTP/1.1" 200 37 "-" "Python-httplib2/0.8 (gzip)" 使用POST方法时,不会在请求URL中发送该值。发送用户代理信息 在本节中,我们指定用户代理的名称。<?php echo $_SERVER['HTTP_USER_AGENT']; ?> 在nginx文档根目录下,我们有agent.php文件。它返回用户代理的名称。import httplib2 http = httplib2.Http() content = http.request("http://localhost/agent.php", method="GET", headers={'user-agent': 'Python script'})[1] print(content.decode()) 该脚本向脚本创建一个简单的GET请求agent.php。在headers字典中,我们指定用户代理。这可以通过PHP脚本读取,并返回给客户端。Python script 服务器使用我们随请求发送的代理名称进行了响应。将用户名/密码添加到请求 客户端的add_credentials()方法设置用于领域的名称和密码。安全领域是一种用于保护Web应用程序资源的机制。$ sudo apt-get install apache2-utils $ sudo htpasswd -c /etc/nginx/.htpasswd user7 New password: Re-type new password: Adding password for user user7 我们使用该htpasswd工具创建用于基本HTTP身份验证的用户名和密码。location /secure { auth_basic "Restricted Area"; auth_basic_user_file /etc/nginx/.htpasswd; } 在nginx /etc/nginx/sites-available/default配置文件中,我们创建一个安全页面。领域的名称是“禁区”。<!DOCTYPE html> <html lang="en"> <head> <title>Secure page</title> </head> <body> <p> This is a secure page. </p> </body> </html> 在/usr/share/nginx/html/secure目录中,我们有上面的HTML文件。import httplib2 user = 'user7' passwd = '7user' http = httplib2.Http() http.add_credentials(user, passwd) content = http.request("http://localhost/secure/")[1] print(content.decode()) 该脚本连接到安全网页;它提供访问该页面所需的用户名和密码。<!DOCTYPE html> <html lang="en"> <head> <title>Secure page</title> </head> <body> <p> This is a secure page. </p> </body> </html> 使用正确的凭据,脚本将返回受保护的页面。在本教程中,我们探索了Python httplib2模块。
  • Log4j2 HTMLLayout 配置使用详解

    这个Log4j2示例将帮助您使用HTMLLayout配置log4j2.xml文件这个Log4j2示例将帮助您使用HTMLLayout配置log4j2.xml文件。 HTMLLayout生成一个HTML页面,并将每个log语句添加到表中的一行。HTMLLayout 配置您可以在配置HTMLLayout时使用以下属性:locationInfo – 如果为“ true”,则将包括位置信息。 默认为false。 title – 要包含在文件标题中的标题。 如果未指定,则使用默认标题。 contentType – 内容类型。 默认为“ text / html”。 charset – 要使用的字符集。 如果未指定,将使用默认值。fontSize – 文本的字体大小。 font – 用于文本的字体。 我们来看看用于生成基于HTML格式的日志文件的不同配置选项。$title(log4j2.xml) <?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn"> <Properties> <Property name="basePath">C:\\logs</Property> </Properties> <Appenders> <RollingFile name="fileLogger" fileName="${basePath}/app-info.html" filePattern="${basePath}/app-info-%d{yyyy-MM-dd}.html"> <HTMLLayout charset="UTF-8" title="Howtodoinjava Info Logs" locationInfo="true" /> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <SizeBasedTriggeringPolicy size="10 MB" /> </Policies> </RollingFile> <Console name="console" target="SYSTEM_OUT"> <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n" /> </Console> </Appenders> <Loggers> <Logger name="com.howtodoinjava" level="debug" additivity="false"> <appender-ref ref="fileLogger" level="debug" /> </Logger> <Root level="debug" additivity="false"> <appender-ref ref="console" /> </Root> </Loggers> </Configuration> $title(log4j2.properties) status = error name = PropertiesConfig #Make sure to change log file path as per your need property.filename = C:\\logs\\app-info.html filters = threshold filter.threshold.type = ThresholdFilter filter.threshold.level = debug appenders = rolling appender.rolling.type = RollingFile appender.rolling.name = RollingFile appender.rolling.fileName = ${filename} appender.rolling.filePattern = debug-backup-%d{MM-dd-yy-HH-mm-ss}-%i.html.gz appender.rolling.layout.type = HTMLLayout appender.rolling.layout.charset = UTF-8 appender.rolling.layout.title = Howtodoinjava Info Logs appender.rolling.layout.locationInfo = true appender.rolling.policies.type = Policies appender.rolling.policies.time.type = TimeBasedTriggeringPolicy appender.rolling.policies.time.interval = 1 appender.rolling.policies.time.modulate = true appender.rolling.policies.size.type = SizeBasedTriggeringPolicy appender.rolling.policies.size.size=10MB appender.rolling.strategy.type = DefaultRolloverStrategy appender.rolling.strategy.max = 20 loggers = rolling #Make sure to change the package structure as per your application logger.rolling.name = com.howtodoinjava logger.rolling.level = debug logger.rolling.additivity = false logger.rolling.appenderRef.rolling.ref = RollingFile$title(log4j2.json) { "configuration": { "name": "Default", "appenders": { "RollingFile": { "name":"File", "fileName":"C:/logs/howtodoinjava.html", "filePattern":"C:/logs/howtodoinjava-backup-%d{MM-dd-yy-HH-mm-ss}-%i.html.gz", "HTMLLayout": { "charset":"UTF-8", "title":"Howtodoinjava Info Logs", "locationInfo":"true" }, "Policies": { "SizeBasedTriggeringPolicy": { "size":"10 MB" } }, "DefaultRolloverStrategy": { "max":"10" } } }, "loggers": { "root": { "level":"debug", "appender-ref": { "ref":"File" } } } } }简单日志测试import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class Log4j2HelloWorldExample { private static final Logger LOGGER = LogManager.getLogger(Log4j2HelloWorldExample.class.getName()); public static void main(String[] args) { LOGGER.debug("Debug Message Logged !!"); LOGGER.info("Info Message Logged !!"); LOGGER.debug("Another Debug Message !!"); } }Log4j2 HTMLLayout 输出日志输出
  • Newifi3 D2 硬件参数

    Newifi3 D2 硬件参数信息 Newifi3 D2 硬件配置信息 SOCMT7621A2.4G无线芯片MT7603EN5G 无线芯片MT7612EN5G 功放芯片SKY85717-21RAM内存512MBROM闪存32MB2.4G 最Newifi3 D2 硬件参数信息 Newifi3 D2 硬件配置信息 SOCMT7621A2.4G无线芯片MT7603EN5G 无线芯片MT7612EN5G 功放芯片SKY85717-21RAM内存512MBROM闪存32MB2.4G 最大速率300Mbps5G最大速率867MbpsWLAN口速率1GbpsLAN口速率1GbpsLAN口数量4天线类型外置不可拆卸4根天线增益2.4G天线增益5dBi/5G天线增益6dBiUSB 3.01是否支持刷机是(可以刷padavan/op等)当前参考价格90 关联文章:Newifi 3 D2刷BREED教程小米路由器3G 对比 Newifi3 D2(新路由3)