• 使用 JSONDoc 记录 Spring Boot RESTful API


    这个博文可以分为两部分:第一部分我将编写一个Spring Boot RESTful API,第二部分将介绍如何使用JSONDoc来记录创建的API。做这两个部分最多需要15分钟,因为使用Spring Boot创建一个API非常简单快捷,并且使用JSONDoc Spring Boot启动器和UI webjar进行记录也是如此。我将跳过这个例子的测试创建,因为主要目标是如何记录API而不是编写和测试它。

    编写API

    我们首先根据快速入门的原型创建Maven项目



    并声明API所需的依赖关系:

    • spring-boot-starter-web
    • spring-boot-starter-data-jpa
    • h2
    我还添加了 Lombok 保持我的代码更干净。所得的pom看起来像这样:
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    
    	<groupId>org.example</groupId>
    	<artifactId>jsondoc-shelf</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<name>jsondoc-shelf</name>
    	<url>http://maven.apache.org</url>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    	</properties>
    
    	<dependencies>
    	
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    			<version>1.2.0.RELEASE</version>
    		</dependency>
    		
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-jpa</artifactId>
    			<version>1.2.0.RELEASE</version>
    		</dependency>
    		
    		<dependency>
    			<groupId>com.h2database</groupId>
    			<artifactId>h2</artifactId>
    			<version>1.3.176</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    			<version>1.14.8</version>
    		</dependency>
    
    		<dependency>
    			<groupId>junit</groupId>
    			<artifactId>junit</artifactId>
    			<version>4.11</version>
    			<scope>test</scope>
    		</dependency>
    		
    	</dependencies>
    </project>
    这个应用程序将是一个管理简单货架的服务的集合。将有两个实体:
    • Book
    • Author

    创建 Entities 和 Controllers

    为此,我将创建通常的组件来管理持久层和控制器层:

    • 一个包名为model将包含BookAuthor
    • 一个包名为repository将包含BookRepositoryAuthorRepository
    • 一个包名为controller将包含BookControllerAuthorController

    对于这个例子,我将跳过 Service 层。我还将创建一个DatabasePopulator类,实现CommandLineRunner,以便在启动时将在内存数据库中存在一些数据。我们来看看实体,存储库和控制器的代码:

    Entities
    package org.example.shelf.model;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.ManyToOne;
    
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    
    @Entity
    @Data
    @EqualsAndHashCode(exclude = "id")
    public class Book {
    
    	@Id
    	@GeneratedValue(strategy = GenerationType.AUTO)
    	private Long id;
    
    	@Column(name = "title")
    	private String title;
    
    	@ManyToOne
    	@JoinColumn(name = "author_id")
    	private Author author;
    
    }
    package org.example.shelf.model;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    import lombok.NoArgsConstructor;
    import lombok.ToString;
    
    import com.fasterxml.jackson.annotation.JsonIgnore;
    
    @Entity
    @Data
    @NoArgsConstructor
    @ToString(exclude = "books")
    @EqualsAndHashCode(of = "name")
    public class Author {
    
    	@Id
    	@GeneratedValue(strategy = GenerationType.AUTO)
    	private Long id;
    
    	@Column(name = "name")
    	private String name;
    
    	@JsonIgnore
    	@OneToMany(mappedBy = "author", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    	private List<Book> books = new ArrayList<Book>();
    	
    }
    Repositories
    package org.example.shelf.repository;
    
    import org.example.shelf.model.Book;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface BookRepository extends JpaRepository<Book, Long> {
    
    }
    package org.example.shelf.repository;
    
    import org.example.shelf.model.Author;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    public interface AuthorRepository extends JpaRepository<Author, Long> {
    
    }
    Controllers
    package org.example.shelf.controller;
    
    import java.util.List;
    
    import org.example.shelf.flow.ShelfFlowConstants;
    import org.example.shelf.model.Book;
    import org.example.shelf.repository.BookRepository;
    import org.jsondoc.core.annotation.Api;
    import org.jsondoc.core.annotation.ApiBodyObject;
    import org.jsondoc.core.annotation.ApiMethod;
    import org.jsondoc.core.annotation.ApiPathParam;
    import org.jsondoc.core.annotation.ApiResponseObject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    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.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.util.UriComponentsBuilder;
    
    @RestController
    @RequestMapping(value = "/books", produces = MediaType.APPLICATION_JSON_VALUE)
    public class BookController {
    	
    	@Autowired
    	private BookRepository bookRepository;
    	
    	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
    	public Book findOne(@PathVariable Long id) {
    		return bookRepository.findOne(id);
    	}
    	
    	@RequestMapping(method = RequestMethod.GET)
    	public List<Book> findAll() {
    		return bookRepository.findAll();
    	}
    	
    	@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    	@ResponseStatus(value = HttpStatus.CREATED)
    	public ResponseEntity<Void> save(@RequestBody Book book, UriComponentsBuilder uriComponentsBuilder) {
    		bookRepository.save(book);
    		
    		HttpHeaders headers = new HttpHeaders();
    		headers.setLocation(uriComponentsBuilder.path("/books/{id}").buildAndExpand(book.getId()).toUri());
    		return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
    	}
    	
    	@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    	@ResponseStatus(value = HttpStatus.OK)
    	public void delete(@PathVariable Long id) {
    		Book book = bookRepository.findOne(id);
    		bookRepository.delete(book);
    	}
    
    }
    package org.example.shelf.controller;
    
    import java.util.List;
    
    import org.example.shelf.flow.ShelfFlowConstants;
    import org.example.shelf.model.Author;
    import org.example.shelf.repository.AuthorRepository;
    import org.jsondoc.core.annotation.Api;
    import org.jsondoc.core.annotation.ApiBodyObject;
    import org.jsondoc.core.annotation.ApiMethod;
    import org.jsondoc.core.annotation.ApiPathParam;
    import org.jsondoc.core.annotation.ApiResponseObject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    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.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.util.UriComponentsBuilder;
    
    @RestController
    @RequestMapping(value = "/authors", produces = MediaType.APPLICATION_JSON_VALUE)
    public class AuthorController {
    
    	@Autowired
    	private AuthorRepository authorRepository;
    
    	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
    	public Author findOne(@PathVariable Long id) {
    		return authorRepository.findOne(id);
    	}
    
    	@RequestMapping(method = RequestMethod.GET)
    	public List<Author> findAll() {
    		return authorRepository.findAll();
    	}
    
    	@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    	@ResponseStatus(value = HttpStatus.CREATED)
    	public ResponseEntity<Void> save(@RequestBody Author author, UriComponentsBuilder uriComponentsBuilder) {
    		authorRepository.save(author);
    		
    		HttpHeaders headers = new HttpHeaders();
    		headers.setLocation(uriComponentsBuilder.path("/authors/{id}").buildAndExpand(author.getId()).toUri());
    		return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
    	}
    
    	@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    	@ResponseStatus(value = HttpStatus.OK)
    	public void delete(@PathVariable Long id) {
    		Author author = authorRepository.findOne(id);
    		authorRepository.delete(author);
    	}
    
    }
    Database populator
    package org.example.shelf;
    
    import org.example.shelf.model.Author;
    import org.example.shelf.model.Book;
    import org.example.shelf.repository.AuthorRepository;
    import org.example.shelf.repository.BookRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class DatabasePopulator implements CommandLineRunner {
    	
    	@Autowired
    	private AuthorRepository authorRepository;
    	
    	@Autowired
    	private BookRepository bookRepository;
    	
    	public void run(String... arg0) throws Exception {
    		Author horbny = new Author();
    		horbny.setId(1L);
    		horbny.setName("Nick Horby");
    		
    		Author smith = new Author();
    		smith.setId(2L);
    		smith.setName("Wilbur Smith");
    		
    		authorRepository.save(horbny);
    		authorRepository.save(smith);
    		
    		Book highFidelty = new Book();
    		highFidelty.setId(1L);
    		highFidelty.setTitle("High fidelty");
    		highFidelty.setAuthor(horbny);
    		
    		Book aLongWayDown = new Book();
    		aLongWayDown.setId(2L);
    		aLongWayDown.setTitle("A long way down");
    		aLongWayDown.setAuthor(horbny);
    
    		Book desertGod = new Book();
    		desertGod.setId(3L);
    		desertGod.setTitle("Desert god");
    		desertGod.setAuthor(smith);
    		
    		bookRepository.save(highFidelty);
    		bookRepository.save(aLongWayDown);
    		bookRepository.save(desertGod);
    	}
    
    }
    现在是编写主类来运行应用程序的时候了。Shelf在这种情况下,我会称之为Spring Boot,这很简单:

    package org.example.shelf;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
    
    @EnableAutoConfiguration
    @EnableJpaRepositories
    @ComponentScan
    public class Shelf {
    	
    	public static void main(String[] args) {
    		SpringApplication.run(Shelf.class, args);
    	}
    
    }
    通过运行这个类,我们可以实际验证应用程序是否响应请求。您可以通过使用 curl 轻松测试 API 的工作:

    curl -i http://localhost:8080/books/1
    curl -i http://localhost:8080/books
    
    curl -i http://localhost:8080/authors/1
    curl -i http://localhost:8080/authors

    用JSONDoc记录API

    这是有趣的和新的部分,即使用JSONDoc库来注释代码并自动生成其文档。要做到这一点,你必须声明JSONDoc依赖关系,并在你的类中插入一些代码。让我们看看如何做到这一点:

    声明JSONDoc依赖关系

    只需添加两个依赖关系到pom文件:

    <dependency>
    	<groupId>org.jsondoc</groupId>
    	<artifactId>spring-boot-starter-jsondoc</artifactId>
    	<version>1.1.3</version>
    </dependency>
    
    <dependency>
    	<groupId>org.jsondoc</groupId>
    	<artifactId>jsondoc-ui-webjar</artifactId>
    	<version>1.1.3</version>
    </dependency>

    在主类中启用JSONDoc

    使用JSONDoc启动器,您可以通过添加@EnableJSONDocShelf启用文档生成,如下所示:

    package org.example.shelf;
    
    import org.jsondoc.spring.boot.starter.EnableJSONDoc;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
    
    @EnableAutoConfiguration
    @EnableJpaRepositories
    @EnableJSONDoc
    @ComponentScan
    public class Shelf {
    	
    	public static void main(String[] args) {
    		SpringApplication.run(Shelf.class, args);
    	}
    
    }

    配置JSONDoc

    接下来要做的是配置JSONDoc来扫描您的控制器,对象和流类。要做到这一点,只需添加一些条目到application.properties文件(src/main/resources如果你没有它创建它)

    jsondoc.version=1.0
    jsondoc.basePath=http://localhost:8080
    jsondoc.packages[0]=org.example.shelf.model
    jsondoc.packages[1]=org.example.shelf.controller

    文档控制器

    JSONDoc可以从Spring注释中获取几个信息来构建文档。无论如何,它是一个选择加入的过程,这意味着JSONDoc将仅在使用自己的注释注释时才扫描类和方法。例如,要正确记录BookController,这里是如何使用JSONDoc注释:

    package org.example.shelf.controller;
    
    import java.util.List;
    
    import org.example.shelf.flow.ShelfFlowConstants;
    import org.example.shelf.model.Book;
    import org.example.shelf.repository.BookRepository;
    import org.jsondoc.core.annotation.Api;
    import org.jsondoc.core.annotation.ApiBodyObject;
    import org.jsondoc.core.annotation.ApiMethod;
    import org.jsondoc.core.annotation.ApiPathParam;
    import org.jsondoc.core.annotation.ApiResponseObject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    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.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.util.UriComponentsBuilder;
    
    @RestController
    @RequestMapping(value = "/books", produces = MediaType.APPLICATION_JSON_VALUE)
    @Api(description = "The books controller", name = "Books services")
    public class BookController {
    	
    	@Autowired
    	private BookRepository bookRepository;
    	
    	@ApiMethod
    	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
    	public @ApiResponseObject Book findOne(@ApiPathParam(name = "id") @PathVariable Long id) {
    		return bookRepository.findOne(id);
    	}
    	
    	@ApiMethod
    	@RequestMapping(method = RequestMethod.GET)
    	public @ApiResponseObject List<Book> findAll() {
    		return bookRepository.findAll();
    	}
    	
    	@ApiMethod
    	@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    	@ResponseStatus(value = HttpStatus.CREATED)
    	public @ApiResponseObject ResponseEntity<Void> save(@ApiBodyObject @RequestBody Book book, UriComponentsBuilder uriComponentsBuilder) {
    		bookRepository.save(book);
    		
    		HttpHeaders headers = new HttpHeaders();
    	    headers.setLocation(uriComponentsBuilder.path("/books/{id}").buildAndExpand(book.getId()).toUri());
    		return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
    	}
    	
    	@ApiMethod
    	@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    	@ResponseStatus(value = HttpStatus.OK)
    	public void delete(@ApiPathParam(name = "id") @PathVariable Long id) {
    		Book book = bookRepository.findOne(id);
    		bookRepository.delete(book);
    	}
    
    }
    同样的AuthorController

    文件对象

    接下来要做的就是把一些JSONDoc注释也需要被记录在案,在这种情况下,对象BookAuthor这是Book类:

    package org.example.shelf.model;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.ManyToOne;
    
    import org.jsondoc.core.annotation.ApiObject;
    import org.jsondoc.core.annotation.ApiObjectField;
    
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    
    @Entity
    @Data
    @EqualsAndHashCode(exclude = "id")
    @ApiObject
    public class Book {
    
    	@Id
    	@GeneratedValue(strategy = GenerationType.AUTO)
    	@ApiObjectField(description = "The book's ID")
    	private Long id;
    
    	@Column(name = "title")
    	@ApiObjectField(description = "The book's title")
    	private String title;
    
    	@ManyToOne
    	@JoinColumn(name = "author_id")
    	@ApiObjectField(description = "The book's author")
    	private Author author;
    
    }
    而且在这种情况下Author也是如此

    检查点:启动应用程序

    在开始记录流程之前,让我们启动应用程序,看看会发生什么:

    • 如果你去http://localhost:8080/jsondoc你会看到一个json,这是由JSONDoc生成的,它代表了基于控制器方法和模型对象上的注释的文档
    • 如果你去http://localhost:8080/jsondoc-ui.html你会看到JSONDoc UI。只需复制并粘贴http://localhost:8080/jsondoc到输入字段中,并在清晰的用户界面中获取文档

    这是一个很好的时机,需要一些时间来探索界面,并在界面上玩API。

    文件流

    按照流程我的意思是一些API方法的后续执行,旨在实现一个目标,即可以购买一本书,或浏览目录并获取图书详细信息。在这种情况下,流程可能涉及几种方法,API用户可能需要知道哪个是正确的调用方法序列来实现目标。在这个例子中,我不能想到有意义的流程,但是让我们假设我想要记录浏览框架的方法顺序,并通过我选择的一本书获取作者的细节,所以这个用例的结果流是就像是:

    • 获取书籍清单
    • 选择一本书并获得其细节
    • 得到这本书的作者

    要记录此流程,您只需按照以下步骤操作:

    1. 创建一个包含应用程序流的类。此类仅用于文档目的,不会在您的应用程序中实际使用。使用注释来注释这个类@ApiFlowSet,这使得JSONDoc了解在构建文档时应该考虑到这个类。
    2. 在这个类中创建假的方法,注释为@ApiFlow方法的正文以及它的返回类型和参数可以是void,因为方法签名服务器只是作为@ApiFlow注释的钩子
    3. 决定标识JSONDoc产生文档内的每一个API方法中,例如一个ID的findAll方法的BookController可有一个像IDBOOK_FIND_ALL
    4. 将这个ID内部ID@ApiMethod注释和内部 api methodid @ApiFlowStep注解
    5. 如果将流类放在一个单独的包中,请记住application.properties使用该值更新该文件

    我们来看看我是怎么做到的 这是持有应用程序流程的类:

    package org.example.shelf.flow;
    
    import org.jsondoc.core.annotation.ApiFlow;
    import org.jsondoc.core.annotation.ApiFlowSet;
    import org.jsondoc.core.annotation.ApiFlowStep;
    
    @ApiFlowSet
    public class ShelfFlows {
    
    	@ApiFlow(
    		name = "Author detail flow",
    		description = "Gets an author's details starting from the book's list",
    		steps = {
    			@ApiFlowStep(apimethodid = ShelfFlowConstants.BOOK_FIND_ALL),	
    			@ApiFlowStep(apimethodid = ShelfFlowConstants.BOOK_FIND_ONE),	
    			@ApiFlowStep(apimethodid = ShelfFlowConstants.AUTHOR_FIND_ONE)	
    		}
    	)
    	public void authorDetailFlow() {
    
    	}
    
    }
    这是包含注释中要引用的方法ID的类:

    package org.example.shelf.flow;
    
    public class ShelfFlowConstants {
    	
    	// Book IDs
    	public final static String BOOK_FIND_ALL = "BOOK_FIND_ALL";
    	public final static String BOOK_FIND_ONE = "BOOK_FIND_ONE";
    	public final static String BOOK_SAVE = "BOOK_SAVE";
    	public final static String BOOK_DELETE = "BOOK_DELETE";
    
    	// Author IDs
    	public final static String AUTHOR_FIND_ALL = "AUTHOR_FIND_ALL";
    	public final static String AUTHOR_FIND_ONE = "AUTHOR_FIND_ONE";
    	public final static String AUTHOR_SAVE = "AUTHOR_SAVE";
    	public final static String AUTHOR_DELETE = "AUTHOR_DELETE";
    
    }
    这是BookController,指定了id属性后:

    package org.example.shelf.controller;
    
    import java.util.List;
    
    import org.example.shelf.flow.ShelfFlowConstants;
    import org.example.shelf.model.Book;
    import org.example.shelf.repository.BookRepository;
    import org.jsondoc.core.annotation.Api;
    import org.jsondoc.core.annotation.ApiBodyObject;
    import org.jsondoc.core.annotation.ApiMethod;
    import org.jsondoc.core.annotation.ApiPathParam;
    import org.jsondoc.core.annotation.ApiResponseObject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    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.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.util.UriComponentsBuilder;
    
    @RestController
    @RequestMapping(value = "/books", produces = MediaType.APPLICATION_JSON_VALUE)
    @Api(description = "The books controller", name = "Books services")
    public class BookController {
    	
    	@Autowired
    	private BookRepository bookRepository;
    	
    	@ApiMethod(id = ShelfFlowConstants.BOOK_FIND_ONE)
    	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
    	public @ApiResponseObject Book findOne(@ApiPathParam(name = "id") @PathVariable Long id) {
    		return bookRepository.findOne(id);
    	}
    	
    	@ApiMethod(id = ShelfFlowConstants.BOOK_FIND_ALL)
    	@RequestMapping(method = RequestMethod.GET)
    	public @ApiResponseObject List<Book> findAll() {
    		return bookRepository.findAll();
    	}
    	
    	@ApiMethod(id = ShelfFlowConstants.BOOK_SAVE)
    	@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    	@ResponseStatus(value = HttpStatus.CREATED)
    	public @ApiResponseObject ResponseEntity<Void> save(@ApiBodyObject @RequestBody Book book, UriComponentsBuilder uriComponentsBuilder) {
    		bookRepository.save(book);
    		
    		HttpHeaders headers = new HttpHeaders();
    	    headers.setLocation(uriComponentsBuilder.path("/books/{id}").buildAndExpand(book.getId()).toUri());
    		return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
    	}
    	
    	@ApiMethod(id = ShelfFlowConstants.BOOK_DELETE)
    	@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    	@ResponseStatus(value = HttpStatus.OK)
    	public void delete(@ApiPathParam(name = "id") @PathVariable Long id) {
    		Book book = bookRepository.findOne(id);
    		bookRepository.delete(book);
    	}
    
    }
    最后的application.properties文件,用新的包:

    jsondoc.version=1.0
    jsondoc.basePath=http://localhost:8080
    jsondoc.packages[0]=org.example.shelf.model
    jsondoc.packages[1]=org.example.shelf.controller
    jsondoc.packages[2]=org.example.shelf.flow
    现在是再次启动应用程序的时候,转到http://localhost:8080/jsondoc-ui.html,插入http://localhost:8080/jsondoc输入框并获取文档。请享用!


    资源

    这是项目的结构:


    链接


  • 相关阅读:
    java链接linux服务器,命令操作
    linux中php项目无法发送邮件:PEAR mail package is not installed
    linux下部署php项目-Apache、php、mysql关联
    MyEclipse黑色主题
    MyEclipse优化-六步攻略
    致产品
    万物归宗
    【产品渗透:移动端平台与纯应用APP产品的相互嵌入】
    【异类--一万小时定律】
    【活法】
  • 原文地址:https://www.cnblogs.com/molashaonian/p/7242013.html
Copyright © 2020-2023  润新知