生成 REST API 文档的步骤
Steps to generate REST API Documentation
我正在尝试为我现有的一些 REST API.
生成基于 Swagger 的 REST API 文档 (UI)
它的必要步骤或先决条件是什么?我正在研究 Windows OS.
Swagger 提供了一些关于如何构建 API 文档的选项。
首先你需要了解它分为两部分:
CORE 用于生成 JSON,其中包含关于您的 API 的相关信息。
此 JSON 遵循 swagger 模板。
INTERFACE 将读取 JSON 并生成 HTML
首先,您将注释您的控制器和端点,为此您需要 'swagger-core' 和 'swagger-annotations'。
那么你有两个选择:
a) 提供端点来生成和服务 JSON 并使用 swagger-ui 读取该端点以生成 HTML
b)编译时使用maven插件swagger-maven生成JSON和HTML
更多信息:
https://github.com/swagger-api/swagger-spec#additional-libraries
如果你正在使用Spring我建议你看看https://github.com/springfox
如果您更喜欢 Maven 插件,请参阅 https://github.com/kongchen
要完成 tbraun 回复:
这里 one 有清晰的演示(错误、注释等...),
和 another one.
我建议您也参考文档:swagger doc。
小心使用最新版本,因为有些 swagger 属性不适用于某些 swagger 版本,例如 "apisOrder" 按名称对 api 进行排序。
当你要测试你的 APi 时,你可以使用 swagger UI。
希望对你有所帮助。
swagger-core 是我们自己的用于与 JAX-RS 项目集成的库
我们还提供了 simple tutorial to explain how to integrate it with your code. It's fairly straightforward. The annotations 文档,以帮助您了解应该添加的内容和位置。
完成上述步骤后,您将获得 swagger.json
和 swagger.yaml
文件的输出。此时,您需要将 swagger-ui 与您的应用程序集成。有多种方法可以这样做。一种方法是将它与您的构建过程集成,就像我们在示例中所做的那样。
这两个插件的组合将为您完成:
<plugin>
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>swagger-ui</id>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://github.com/swagger-api/swagger-ui/archive/master.tar.gz</url>
<unpack>true</unpack>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>target/${project.artifactId}-${project.version}</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}/swagger-ui-master/dist</directory>
<filtering>true</filtering>
<excludes>
<exclude>index.html</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
你只需要确保 运行 也达到 package
目标,所以如果你想安装它,就像 mvn package install
一样(但这取决于你的开发过程) .
您可以使用以下步骤:
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.viquar./groupId>
<artifactId>messenger</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>messenger</name>
<build>
<finalName>messenger</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Swagger documentations -->
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jersey2-jaxrs_2.10</artifactId>
<version>1.3.12</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
</dependencies>
<properties>
<jersey.version>2.16</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
下载:
您可以按原样使用 swagger-ui 代码!无需 build 或重新编译——只需克隆此 repo 并使用 dist 文件夹中的 pre-built 文件。如果您喜欢 swagger-ui 原样,请到此为止。
以下步骤为您提供端到端示例
DatabaseClass.java
package org.viquar.database;
import java.util.HashMap;
import java.util.Map;
import org.viquar.model.Message;
import org.viquar.model.Profile;
public class DatabaseClass {
private static Map<Long, Message> messages = new HashMap<>();
private static Map<String, Profile> profiles = new HashMap<>();
public static Map<Long, Message> getMessages() {
return messages;
}
public static Map<String, Profile> getProfiles() {
return profiles;
}
}
DataNotFoundException.java
package org.viquar.exception;
public class DataNotFoundException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = -6328286661536343936L;
public DataNotFoundException(String message) {
super(message);
}
}
DataNotFoundExceptionMapper.java
package org.viquar.exception;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import org.viquar.model.ErrorMessage;
@Provider
public class DataNotFoundExceptionMapper implements ExceptionMapper<DataNotFoundException> {
@Override
public Response toResponse(DataNotFoundException ex) {
ErrorMessage errorMessage = new ErrorMessage(ex.getMessage(), 404, "http://localhost:8080/JerseyRestPoc.Viquar.poc");
return Response.status(Status.NOT_FOUND)
.entity(errorMessage)
.build();
}
}
GenericExceptionMapper.java
package org.viquar.exception;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import org.viquar.model.ErrorMessage;
// This class intentionally doesn't have the @Provider annotation.
// It has been disabled in order to try out other ways of throwing exceptions in JAX-RS
// @Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
@Override
public Response toResponse(Throwable ex) {
ErrorMessage errorMessage = new ErrorMessage(ex.getMessage(), 500, "http://localhost:8080/JerseyRestPoc.Viquar.poc");
return Response.status(Status.INTERNAL_SERVER_ERROR)
.entity(errorMessage)
.build();
}
}
Comment.java
package org.viquar.model;
import java.util.Date;
public class Comment {
private long id;
private String message;
private Date created;
private String author;
public Comment() {
}
public Comment(long id, String message, String author) {
this.id = id;
this.message = message;
this.author = author;
this.created = new Date();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
ErrorMessage.java
package org.viquar.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class ErrorMessage {
private String errorMessage;
private int errorCode;
private String documentation;
public ErrorMessage() {
}
public ErrorMessage(String errorMessage, int errorCode, String documentation) {
super();
this.errorMessage = errorMessage;
this.errorCode = errorCode;
this.documentation = documentation;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getDocumentation() {
return documentation;
}
public void setDocumentation(String documentation) {
this.documentation = documentation;
}
}
Link.java
package org.viquar.model;
public class Link {
private String link;
private String rel;
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getRel() {
return rel;
}
public void setRel(String rel) {
this.rel = rel;
}
}
Message.java
package org.viquar.model;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
@XmlRootElement
public class Message {
private long id;
private String message;
private Date created;
private String author;
private Map<Long, Comment> comments = new HashMap<>();
private List<Link> links = new ArrayList<>();
public Message() {
}
public Message(long id, String message, String author) {
this.id = id;
this.message = message;
this.author = author;
this.created = new Date();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@XmlTransient
public Map<Long, Comment> getComments() {
return comments;
}
public void setComments(Map<Long, Comment> comments) {
this.comments = comments;
}
public List<Link> getLinks() {
return links;
}
public void setLinks(List<Link> links) {
this.links = links;
}
public void addLink(String url, String rel) {
Link link = new Link();
link.setLink(url);
link.setRel(rel);
links.add(link);
}
}
Profile.java
package org.viquar.model;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Profile {
private long id;
private String profileName;
private String firstName;
private String lastName;
private Date created;
public Profile() {
}
public Profile(long id, String profileName, String firstName, String lastName) {
this.id = id;
this.profileName = profileName;
this.firstName = firstName;
this.lastName = lastName;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getProfileName() {
return profileName;
}
public void setProfileName(String profileName) {
this.profileName = profileName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
}
ProfileResource.java
package org.viquar.resources;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.viquar.model.Profile;
import org.viquar.service.ProfileService;
@Path("/profiles")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class ProfileResource {
private ProfileService profileService = new ProfileService();
@GET
public List<Profile> getProfiles() {
return profileService.getAllProfiles();
}
@POST
public Profile addProfile(Profile profile) {
return profileService.addProfile(profile);
}
@GET
@Path("/{profileName}")
public Profile getProfile(@PathParam("profileName") String profileName) {
return profileService.getProfile(profileName);
}
@PUT
@Path("/{profileName}")
public Profile updateProfile(@PathParam("profileName") String profileName, Profile profile) {
profile.setProfileName(profileName);
return profileService.updateProfile(profile);
}
@DELETE
@Path("/{profileName}")
public void deleteProfile(@PathParam("profileName") String profileName) {
profileService.removeProfile(profileName);
}
}
MessageResource.java
package org.viquar.resources;
import java.net.URI;
import java.util.List;
import javax.ws.rs.BeanParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.viquar.model.Message;
import org.viquar.resources.beans.MessageFilterBean;
import org.viquar.service.MessageService;
//
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiResponse;
import com.wordnik.swagger.annotations.ApiResponses;
@Path("/messages")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Api(value = "/messages", description = "Operation about orders")
public class MessageResource {
MessageService messageService = new MessageService();
@GET
public List<Message> getMessages(@BeanParam MessageFilterBean filterBean) {
if (filterBean.getYear() > 0) {
return messageService.getAllMessagesForYear(filterBean.getYear());
}
if (filterBean.getStart() >= 0 && filterBean.getSize() > 0) {
return messageService.getAllMessagesPaginated(filterBean.getStart(), filterBean.getSize());
}
return messageService.getAllMessages();
}
@POST
public Response addMessage(Message message, @Context UriInfo uriInfo) {
Message newMessage = messageService.addMessage(message);
String newId = String.valueOf(newMessage.getId());
URI uri = uriInfo.getAbsolutePathBuilder().path(newId).build();
return Response.created(uri)
.entity(newMessage)
.build();
}
@PUT
@Path("/{messageId}")
public Message updateMessage(@PathParam("messageId") long id, Message message) {
message.setId(id);
return messageService.updateMessage(message);
}
@DELETE
@Path("/{messageId}")
public void deleteMessage(@PathParam("messageId") long id) {
messageService.removeMessage(id);
}
@GET
@Path("/{messageId}")
@ApiOperation(value = "Returns user details", notes = "Returns a complete list of users details with a date of last modification.", response = Message.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful retrieval of user detail", response = Message.class),
@ApiResponse(code = 404, message = "User with given username does not exist"),
@ApiResponse(code = 500, message = "Internal server error")
})
public Message getMessage(@PathParam("messageId") long id, @Context UriInfo uriInfo) {
Message message = messageService.getMessage(id);
message.addLink(getUriForSelf(uriInfo, message), "self");
message.addLink(getUriForProfile(uriInfo, message), "profile");
message.addLink(getUriForComments(uriInfo, message), "comments");
return message;
}
private String getUriForComments(UriInfo uriInfo, Message message) {
URI uri = uriInfo.getBaseUriBuilder()
.path(MessageResource.class)
.path(MessageResource.class, "getCommentResource")
.path(CommentResource.class)
.resolveTemplate("messageId", message.getId())
.build();
return uri.toString();
}
private String getUriForProfile(UriInfo uriInfo, Message message) {
URI uri = uriInfo.getBaseUriBuilder()
.path(ProfileResource.class)
.path(message.getAuthor())
.build();
return uri.toString();
}
private String getUriForSelf(UriInfo uriInfo, Message message) {
String uri = uriInfo.getBaseUriBuilder()
.path(MessageResource.class)
.path(Long.toString(message.getId()))
.build()
.toString();
return uri;
}
@Path("/{messageId}/comments")
public CommentResource getCommentResource() {
return new CommentResource();
}
}
InjectDemoResource.java
package org.viquar.resources;
import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
@Path("/injectdemo")
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.TEXT_PLAIN)
public class InjectDemoResource {
@GET
@Path("annotations")
public String getParamsUsingAnnotations(@MatrixParam("param") String matrixParam,
@HeaderParam("authSessionID") String header,
@CookieParam("name") String cookie) {
return "Matrix param: " + matrixParam + " Header param: " + header + " Cookie param: " + cookie;
}
@GET
@Path("context")
public String getParamsUsingContext(@Context UriInfo uriInfo, @Context HttpHeaders headers) {
String path = uriInfo.getAbsolutePath().toString();
String cookies = headers.getCookies().toString();
return "Path : " + path + " Cookies: " + cookies;
}
}
CommentResource.java
package org.viquar.resources;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.viquar.model.Comment;
import org.viquar.service.CommentService;
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class CommentResource {
private CommentService commentService = new CommentService();
@GET
public List<Comment> getAllComments(@PathParam("messageId") long messageId) {
return commentService.getAllComments(messageId);
}
@POST
public Comment addComment(@PathParam("messageId") long messageId, Comment comment) {
return commentService.addComment(messageId, comment);
}
@PUT
@Path("/{commentId}")
public Comment updateComment(@PathParam("messageId") long messageId, @PathParam("commentId") long id, Comment comment) {
comment.setId(id);
return commentService.updateComment(messageId, comment);
}
@DELETE
@Path("/{commentId}")
public void deleteComment(@PathParam("messageId") long messageId, @PathParam("commentId") long commentId) {
commentService.removeComment(messageId, commentId);
}
@GET
@Path("/{commentId}")
public Comment getMessage(@PathParam("messageId") long messageId, @PathParam("commentId") long commentId) {
return commentService.getComment(messageId, commentId);
}
}
MessageFilterBean.java
package org.viquar.resources.beans;
import javax.ws.rs.QueryParam;
public class MessageFilterBean {
private @QueryParam("year") int year;
private @QueryParam("start") int start;
private @QueryParam("size") int size;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
CommentService.java
package org.viquar.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.viquar.database.DatabaseClass;
import org.viquar.model.Comment;
import org.viquar.model.ErrorMessage;
import org.viquar.model.Message;
public class CommentService {
private Map<Long, Message> messages = DatabaseClass.getMessages();
public List<Comment> getAllComments(long messageId) {
Map<Long, Comment> comments = messages.get(messageId).getComments();
return new ArrayList<Comment>(comments.values());
}
public Comment getComment(long messageId, long commentId) {
ErrorMessage errorMessage = new ErrorMessage("Not found", 404, "http://CosineOTC.Viquar.poc");
Response response = Response.status(Status.NOT_FOUND)
.entity(errorMessage)
.build();
Message message = messages.get(messageId);
if (message == null) {
throw new WebApplicationException(response);
}
Map<Long, Comment> comments = messages.get(messageId).getComments();
Comment comment = comments.get(commentId);
if (comment == null) {
throw new NotFoundException(response);
}
return comment;
}
public Comment addComment(long messageId, Comment comment) {
Map<Long, Comment> comments = messages.get(messageId).getComments();
comment.setId(comments.size() + 1);
comments.put(comment.getId(), comment);
return comment;
}
public Comment updateComment(long messageId, Comment comment) {
Map<Long, Comment> comments = messages.get(messageId).getComments();
if (comment.getId() <= 0) {
return null;
}
comments.put(comment.getId(), comment);
return comment;
}
public Comment removeComment(long messageId, long commentId) {
Map<Long, Comment> comments = messages.get(messageId).getComments();
return comments.remove(commentId);
}
}
MessageService.java
package org.viquar.service;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import org.viquar.database.DatabaseClass;
import org.viquar.exception.DataNotFoundException;
import org.viquar.model.Message;
public class MessageService {
private Map<Long, Message> messages = DatabaseClass.getMessages();
public MessageService() {
messages.put(1L, new Message(1, "Hello World", "ViquarKhan"));
messages.put(2L, new Message(2, "Hello Jersey", "Shahbazkhan"));
messages.put(3L, new Message(3, "Hello Cosine", "Snehaghosh"));
}
public List<Message> getAllMessages() {
return new ArrayList<Message>(messages.values());
}
public List<Message> getAllMessagesForYear(int year) {
List<Message> messagesForYear = new ArrayList<>();
Calendar cal = Calendar.getInstance();
for (Message message : messages.values()) {
cal.setTime(message.getCreated());
if (cal.get(Calendar.YEAR) == year) {
messagesForYear.add(message);
}
}
return messagesForYear;
}
public List<Message> getAllMessagesPaginated(int start, int size) {
ArrayList<Message> list = new ArrayList<Message>(messages.values());
if (start + size > list.size()) return new ArrayList<Message>();
return list.subList(start, start + size);
}
public Message getMessage(long id) {
Message message = messages.get(id);
if (message == null) {
throw new DataNotFoundException("Message with id " + id + " not found");
}
return message;
}
public Message addMessage(Message message) {
message.setId(messages.size() + 1);
messages.put(message.getId(), message);
return message;
}
public Message updateMessage(Message message) {
if (message.getId() <= 0) {
return null;
}
messages.put(message.getId(), message);
return message;
}
public Message removeMessage(long id) {
return messages.remove(id);
}
}
ProfileService.java
package org.viquar.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.viquar.database.DatabaseClass;
import org.viquar.model.Profile;
public class ProfileService {
private Map<String, Profile> profiles = DatabaseClass.getProfiles();
public ProfileService() {
profiles.put("Viquar", new Profile(1L, "Viquar", "Viquar", "Khan"));
profiles.put("Shahbaz", new Profile(2L, "Shahbaz", "Shahbaz", "Khan"));
profiles.put("Sneha", new Profile(3L, "Sneha", "Sneha", "Ghosh"));
}
public List<Profile> getAllProfiles() {
return new ArrayList<Profile>(profiles.values());
}
public Profile getProfile(String profileName) {
return profiles.get(profileName);
}
public Profile addProfile(Profile profile) {
profile.setId(profiles.size() + 1);
profiles.put(profile.getProfileName(), profile);
return profile;
}
public Profile updateProfile(Profile profile) {
if (profile.getProfileName().isEmpty()) {
return null;
}
profiles.put(profile.getProfileName(), profile);
return profile;
}
public Profile removeProfile(String profileName) {
return profiles.remove(profileName);
}
}
SwaggerRestApp.java
包 org.viquar.swegger;
import com.wordnik.swagger.config.ConfigFactory;
import com.wordnik.swagger.config.ScannerFactory;
import com.wordnik.swagger.config.SwaggerConfig;
import com.wordnik.swagger.jaxrs.config.ReflectiveJaxrsScanner;
import com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider;
import com.wordnik.swagger.jaxrs.listing.ApiListingResource;
import com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON;
import com.wordnik.swagger.jaxrs.listing.ResourceListingProvider;
import com.wordnik.swagger.jaxrs.reader.DefaultJaxrsApiReader;
import com.wordnik.swagger.reader.ClassReaders;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.message.MessageProperties;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.viquar.resources.MessageResource;
import javax.annotation.PostConstruct;
import javax.ws.rs.ApplicationPath;
//@Component
@ApplicationPath("api")
public class SwaggerRestApp extends ResourceConfig {
public SwaggerRestApp(){
register(MessageResource.class);
register(JacksonFeature.class);
//register(AllExceptionMapper.class);
register(ApiListingResource.class);
register(ApiDeclarationProvider.class);
register(ApiListingResourceJSON.class);
register(ResourceListingProvider.class);
property(MessageProperties.XML_FORMAT_OUTPUT, true);
property(ServerProperties.TRACING, "ALL");
}
@PostConstruct
/**
* Initializes Swagger Configuration
*/
public void initializeSwaggerConfiguration() {
final ReflectiveJaxrsScanner scanner = new ReflectiveJaxrsScanner();
scanner.setResourcePackage("org.viquar);
ScannerFactory.setScanner(scanner);
ClassReaders.setReader(new DefaultJaxrsApiReader());
final SwaggerConfig config = ConfigFactory.config();
config.setApiVersion("1.0");
config.setBasePath("http://localhost:8080/messenger/cosineotc/api/v1");
}
}
由于限制问题下一个评论继续.....
第 2 部分继续......
现在您必须配置 Webapp,使用以下名称创建文件夹并复制文件夹内的内容
复制 CSS 到 JerseyRestSSweggerPoc\src\main\webapp\css
复制JerseyRestSSweggerPoc\src\main\webapp\fonts
里面的字体
复制JerseyRestSSweggerPoc\src\main\webapp\images
里面的图片
在JerseyRestSSweggerPoc\src\main\webapp\lang
中复制lang
复制JerseyRestSSweggerPoc\src\main\webapp\lib
里面的库
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16" />
<link href='css/typography.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>
<link href='css/print.css' media='print' rel='stylesheet' type='text/css'/>
<script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
<script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
<script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
<script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
<script src='lib/handlebars-2.0.0.js' type='text/javascript'></script>
<script src='lib/underscore-min.js' type='text/javascript'></script>
<script src='lib/backbone-min.js' type='text/javascript'></script>
<script src='swagger-ui.js' type='text/javascript'></script>
<script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
<script src='lib/marked.js' type='text/javascript'></script>
<script src='lib/swagger-oauth.js' type='text/javascript'></script>
<!-- Some basic translations -->
<!-- <script src='lang/translator.js' type='text/javascript'></script> -->
<!-- <script src='lang/ru.js' type='text/javascript'></script> -->
<!-- <script src='lang/en.js' type='text/javascript'></script> -->
<script type="text/javascript">
$(function () {
var url = window.location.search.match(/url=([^&]+)/);
if (url && url.length > 1) {
url = decodeURIComponent(url[1]);
} else {
url = "http://localhost:8080/messenger/api/v1/api-docs";
}
// Pre load translate...
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
window.swaggerUi = new SwaggerUi({
url: url,
dom_id: "swagger-ui-container",
supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
onComplete: function(swaggerApi, swaggerUi){
if(typeof initOAuth == "function") {
initOAuth({
clientId: "your-client-id",
clientSecret: "your-client-secret",
realm: "your-realms",
appName: "your-app-name",
scopeSeparator: ","
});
}
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
$('pre code').each(function(i, e) {
hljs.highlightBlock(e)
});
addApiKeyAuthorization();
},
onFailure: function(data) {
log("Unable to Load SwaggerUI");
},
docExpansion: "none",
apisSorter: "alpha",
showRequestHeaders: false
});
function addApiKeyAuthorization(){
var key = encodeURIComponent($('#input_apiKey')[0].value);
if(key && key.trim() != "") {
var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("api_key", key, "query");
window.swaggerUi.api.clientAuthorizations.add("api_key", apiKeyAuth);
log("added key " + key);
}
}
$('#input_apiKey').change(addApiKeyAuthorization);
// if you have an apiKey you would like to pre-populate on the page for demonstration purposes...
/*
var apiKey = "myApiKeyXXXX123456789";
$('#input_apiKey').val(apiKey);
*/
window.swaggerUi.load();
function log() {
if ('console' in window) {
console.log.apply(console, arguments);
}
}
});
</script>
</head>
<body class="swagger-section">
<div id='header'>
<div class="swagger-ui-wrap">
<a id="logo" href="http://swagger.io">swagger</a> -->
<form id='api_selector'>
<div class='input'><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/></div>
<div class='input'><input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/></div>
<div class='input'><a id="explore" href="#" data-sw-translate>Explore</a></div>
</form>
</div>
</div>
<div id="message-bar" class="swagger-ui-wrap" data-sw-translate> </div>
<div id="swagger-ui-container" class="swagger-ui-wrap"></div>
</body>
</html>
Index.jsp
<html>
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16" />
<link href='css/typography.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>
<link href='css/print.css' media='print' rel='stylesheet' type='text/css'/>
<script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
<script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
<script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
<script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
<script src='lib/handlebars-2.0.0.js' type='text/javascript'></script>
<script src='lib/underscore-min.js' type='text/javascript'></script>
<script src='lib/backbone-min.js' type='text/javascript'></script>
<script src='swagger-ui.js' type='text/javascript'></script>
<script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
<script src='lib/marked.js' type='text/javascript'></script>
<script src='lib/swagger-oauth.js' type='text/javascript'></script>
<!-- Some basic translations -->
<!-- <script src='lang/translator.js' type='text/javascript'></script> -->
<!-- <script src='lang/ru.js' type='text/javascript'></script> -->
<!-- <script src='lang/en.js' type='text/javascript'></script> -->
<script type="text/javascript">
$(function () {
var url = window.location.search.match(/url=([^&]+)/);
if (url && url.length > 1) {
url = decodeURIComponent(url[1]);
} else {
url = "http://petstore.swagger.io/v2/swagger.json";
}
// Pre load translate...
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
window.swaggerUi = new SwaggerUi({
url: url,
dom_id: "swagger-ui-container",
supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
onComplete: function(swaggerApi, swaggerUi){
if(typeof initOAuth == "function") {
initOAuth({
clientId: "your-client-id",
clientSecret: "your-client-secret",
realm: "your-realms",
appName: "your-app-name",
scopeSeparator: ","
});
}
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
$('pre code').each(function(i, e) {
hljs.highlightBlock(e)
});
addApiKeyAuthorization();
},
onFailure: function(data) {
log("Unable to Load SwaggerUI");
},
docExpansion: "none",
apisSorter: "alpha",
showRequestHeaders: false
});
function addApiKeyAuthorization(){
var key = encodeURIComponent($('#input_apiKey')[0].value);
if(key && key.trim() != "") {
var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("api_key", key, "query");
window.swaggerUi.api.clientAuthorizations.add("api_key", apiKeyAuth);
log("added key " + key);
}
}
$('#input_apiKey').change(addApiKeyAuthorization);
// if you have an apiKey you would like to pre-populate on the page for demonstration purposes...
/*
var apiKey = "myApiKeyXXXX123456789";
$('#input_apiKey').val(apiKey);
*/
window.swaggerUi.load();
function log() {
if ('console' in window) {
console.log.apply(console, arguments);
}
}
});
</script>
</head>
<body>
<h2>Jersey RESTful Web Application!</h2>
<p><a href="webapi/myresource">Jersey resource</a>
<p>Visit <a href="http://jersey.java.net">Project Jersey website</a>
for more information on Jersey!
</body>
</html>
o2c.html
<script>
var qp = null;
if(window.location.hash) {
qp = location.hash.substring(1);
}
else {
qp = location.search.substring(1);
}
qp = qp ? JSON.parse('{"' + qp.replace(/&/g, '","').replace(/=/g,'":"') + '"}',
function(key, value) {
return key===""?value:decodeURIComponent(value) }
):{}
if (window.opener.swaggerUi.tokenUrl)
window.opener.processOAuthCode(qp);
else
window.opener.onOAuthComplete(qp);
window.close();
</script>
希望对您有所帮助。
URL 用于访问
http://localhost:8080/messenger//api/v1/messages/1
**Swegger** :
http://localhost:8080/messenger/
http://localhost:8080/jersey-swagger/rest/api-docs
http://localhost:8080/jersey-swagger/#!/employees/createEmployee
http://localhost:8080/messenger//api/v1/api-docs
http://localhost:8080/messenger/#!/messages/getMessage
http://localhost:8080/messenger//api/v1/messages/1
{
"author":"Viquar Khan","created":"2015-07-31T16:35:43.498",
"id":1,
"links":[
{"link":"http://localhost:8080/JerseyRestPoc//api/v1/messages/1","rel":"self"},
{"http://localhost:8080/JerseyRestPoc//api/v1/profiles/Viquar%20Khan","rel":"profile"},
{"link":"http://localhost:8080/JerseyRestPoc/api/v1/messages/1/comments/","rel":"comments"}
],
"message":"Hello World"
}
在 MessageResource.java 内部,我为 Swagger 添加了以下注释
@Api(value = "/messages", description = "Operation about orders")
我正在尝试为我现有的一些 REST API.
生成基于 Swagger 的 REST API 文档 (UI)它的必要步骤或先决条件是什么?我正在研究 Windows OS.
Swagger 提供了一些关于如何构建 API 文档的选项。
首先你需要了解它分为两部分:
CORE 用于生成 JSON,其中包含关于您的 API 的相关信息。 此 JSON 遵循 swagger 模板。
INTERFACE 将读取 JSON 并生成 HTML
首先,您将注释您的控制器和端点,为此您需要 'swagger-core' 和 'swagger-annotations'。
那么你有两个选择:
a) 提供端点来生成和服务 JSON 并使用 swagger-ui 读取该端点以生成 HTML
b)编译时使用maven插件swagger-maven生成JSON和HTML
更多信息:
https://github.com/swagger-api/swagger-spec#additional-libraries
如果你正在使用Spring我建议你看看https://github.com/springfox
如果您更喜欢 Maven 插件,请参阅 https://github.com/kongchen
要完成 tbraun 回复:
这里 one 有清晰的演示(错误、注释等...), 和 another one.
我建议您也参考文档:swagger doc。
小心使用最新版本,因为有些 swagger 属性不适用于某些 swagger 版本,例如 "apisOrder" 按名称对 api 进行排序。
当你要测试你的 APi 时,你可以使用 swagger UI。
希望对你有所帮助。
swagger-core 是我们自己的用于与 JAX-RS 项目集成的库
我们还提供了 simple tutorial to explain how to integrate it with your code. It's fairly straightforward. The annotations 文档,以帮助您了解应该添加的内容和位置。
完成上述步骤后,您将获得 swagger.json
和 swagger.yaml
文件的输出。此时,您需要将 swagger-ui 与您的应用程序集成。有多种方法可以这样做。一种方法是将它与您的构建过程集成,就像我们在示例中所做的那样。
这两个插件的组合将为您完成:
<plugin>
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>swagger-ui</id>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://github.com/swagger-api/swagger-ui/archive/master.tar.gz</url>
<unpack>true</unpack>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>target/${project.artifactId}-${project.version}</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}/swagger-ui-master/dist</directory>
<filtering>true</filtering>
<excludes>
<exclude>index.html</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
你只需要确保 运行 也达到 package
目标,所以如果你想安装它,就像 mvn package install
一样(但这取决于你的开发过程) .
您可以使用以下步骤:
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.viquar./groupId>
<artifactId>messenger</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>messenger</name>
<build>
<finalName>messenger</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Swagger documentations -->
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jersey2-jaxrs_2.10</artifactId>
<version>1.3.12</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
</dependencies>
<properties>
<jersey.version>2.16</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
下载:
您可以按原样使用 swagger-ui 代码!无需 build 或重新编译——只需克隆此 repo 并使用 dist 文件夹中的 pre-built 文件。如果您喜欢 swagger-ui 原样,请到此为止。
以下步骤为您提供端到端示例
DatabaseClass.java
package org.viquar.database;
import java.util.HashMap;
import java.util.Map;
import org.viquar.model.Message;
import org.viquar.model.Profile;
public class DatabaseClass {
private static Map<Long, Message> messages = new HashMap<>();
private static Map<String, Profile> profiles = new HashMap<>();
public static Map<Long, Message> getMessages() {
return messages;
}
public static Map<String, Profile> getProfiles() {
return profiles;
}
}
DataNotFoundException.java
package org.viquar.exception;
public class DataNotFoundException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = -6328286661536343936L;
public DataNotFoundException(String message) {
super(message);
}
}
DataNotFoundExceptionMapper.java
package org.viquar.exception;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import org.viquar.model.ErrorMessage;
@Provider
public class DataNotFoundExceptionMapper implements ExceptionMapper<DataNotFoundException> {
@Override
public Response toResponse(DataNotFoundException ex) {
ErrorMessage errorMessage = new ErrorMessage(ex.getMessage(), 404, "http://localhost:8080/JerseyRestPoc.Viquar.poc");
return Response.status(Status.NOT_FOUND)
.entity(errorMessage)
.build();
}
}
GenericExceptionMapper.java
package org.viquar.exception;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import org.viquar.model.ErrorMessage;
// This class intentionally doesn't have the @Provider annotation.
// It has been disabled in order to try out other ways of throwing exceptions in JAX-RS
// @Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
@Override
public Response toResponse(Throwable ex) {
ErrorMessage errorMessage = new ErrorMessage(ex.getMessage(), 500, "http://localhost:8080/JerseyRestPoc.Viquar.poc");
return Response.status(Status.INTERNAL_SERVER_ERROR)
.entity(errorMessage)
.build();
}
}
Comment.java
package org.viquar.model;
import java.util.Date;
public class Comment {
private long id;
private String message;
private Date created;
private String author;
public Comment() {
}
public Comment(long id, String message, String author) {
this.id = id;
this.message = message;
this.author = author;
this.created = new Date();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
ErrorMessage.java
package org.viquar.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class ErrorMessage {
private String errorMessage;
private int errorCode;
private String documentation;
public ErrorMessage() {
}
public ErrorMessage(String errorMessage, int errorCode, String documentation) {
super();
this.errorMessage = errorMessage;
this.errorCode = errorCode;
this.documentation = documentation;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getDocumentation() {
return documentation;
}
public void setDocumentation(String documentation) {
this.documentation = documentation;
}
}
Link.java
package org.viquar.model;
public class Link {
private String link;
private String rel;
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getRel() {
return rel;
}
public void setRel(String rel) {
this.rel = rel;
}
}
Message.java
package org.viquar.model;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
@XmlRootElement
public class Message {
private long id;
private String message;
private Date created;
private String author;
private Map<Long, Comment> comments = new HashMap<>();
private List<Link> links = new ArrayList<>();
public Message() {
}
public Message(long id, String message, String author) {
this.id = id;
this.message = message;
this.author = author;
this.created = new Date();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@XmlTransient
public Map<Long, Comment> getComments() {
return comments;
}
public void setComments(Map<Long, Comment> comments) {
this.comments = comments;
}
public List<Link> getLinks() {
return links;
}
public void setLinks(List<Link> links) {
this.links = links;
}
public void addLink(String url, String rel) {
Link link = new Link();
link.setLink(url);
link.setRel(rel);
links.add(link);
}
}
Profile.java
package org.viquar.model;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Profile {
private long id;
private String profileName;
private String firstName;
private String lastName;
private Date created;
public Profile() {
}
public Profile(long id, String profileName, String firstName, String lastName) {
this.id = id;
this.profileName = profileName;
this.firstName = firstName;
this.lastName = lastName;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getProfileName() {
return profileName;
}
public void setProfileName(String profileName) {
this.profileName = profileName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
}
ProfileResource.java
package org.viquar.resources;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.viquar.model.Profile;
import org.viquar.service.ProfileService;
@Path("/profiles")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class ProfileResource {
private ProfileService profileService = new ProfileService();
@GET
public List<Profile> getProfiles() {
return profileService.getAllProfiles();
}
@POST
public Profile addProfile(Profile profile) {
return profileService.addProfile(profile);
}
@GET
@Path("/{profileName}")
public Profile getProfile(@PathParam("profileName") String profileName) {
return profileService.getProfile(profileName);
}
@PUT
@Path("/{profileName}")
public Profile updateProfile(@PathParam("profileName") String profileName, Profile profile) {
profile.setProfileName(profileName);
return profileService.updateProfile(profile);
}
@DELETE
@Path("/{profileName}")
public void deleteProfile(@PathParam("profileName") String profileName) {
profileService.removeProfile(profileName);
}
}
MessageResource.java
package org.viquar.resources;
import java.net.URI;
import java.util.List;
import javax.ws.rs.BeanParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.viquar.model.Message;
import org.viquar.resources.beans.MessageFilterBean;
import org.viquar.service.MessageService;
//
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiResponse;
import com.wordnik.swagger.annotations.ApiResponses;
@Path("/messages")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Api(value = "/messages", description = "Operation about orders")
public class MessageResource {
MessageService messageService = new MessageService();
@GET
public List<Message> getMessages(@BeanParam MessageFilterBean filterBean) {
if (filterBean.getYear() > 0) {
return messageService.getAllMessagesForYear(filterBean.getYear());
}
if (filterBean.getStart() >= 0 && filterBean.getSize() > 0) {
return messageService.getAllMessagesPaginated(filterBean.getStart(), filterBean.getSize());
}
return messageService.getAllMessages();
}
@POST
public Response addMessage(Message message, @Context UriInfo uriInfo) {
Message newMessage = messageService.addMessage(message);
String newId = String.valueOf(newMessage.getId());
URI uri = uriInfo.getAbsolutePathBuilder().path(newId).build();
return Response.created(uri)
.entity(newMessage)
.build();
}
@PUT
@Path("/{messageId}")
public Message updateMessage(@PathParam("messageId") long id, Message message) {
message.setId(id);
return messageService.updateMessage(message);
}
@DELETE
@Path("/{messageId}")
public void deleteMessage(@PathParam("messageId") long id) {
messageService.removeMessage(id);
}
@GET
@Path("/{messageId}")
@ApiOperation(value = "Returns user details", notes = "Returns a complete list of users details with a date of last modification.", response = Message.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful retrieval of user detail", response = Message.class),
@ApiResponse(code = 404, message = "User with given username does not exist"),
@ApiResponse(code = 500, message = "Internal server error")
})
public Message getMessage(@PathParam("messageId") long id, @Context UriInfo uriInfo) {
Message message = messageService.getMessage(id);
message.addLink(getUriForSelf(uriInfo, message), "self");
message.addLink(getUriForProfile(uriInfo, message), "profile");
message.addLink(getUriForComments(uriInfo, message), "comments");
return message;
}
private String getUriForComments(UriInfo uriInfo, Message message) {
URI uri = uriInfo.getBaseUriBuilder()
.path(MessageResource.class)
.path(MessageResource.class, "getCommentResource")
.path(CommentResource.class)
.resolveTemplate("messageId", message.getId())
.build();
return uri.toString();
}
private String getUriForProfile(UriInfo uriInfo, Message message) {
URI uri = uriInfo.getBaseUriBuilder()
.path(ProfileResource.class)
.path(message.getAuthor())
.build();
return uri.toString();
}
private String getUriForSelf(UriInfo uriInfo, Message message) {
String uri = uriInfo.getBaseUriBuilder()
.path(MessageResource.class)
.path(Long.toString(message.getId()))
.build()
.toString();
return uri;
}
@Path("/{messageId}/comments")
public CommentResource getCommentResource() {
return new CommentResource();
}
}
InjectDemoResource.java
package org.viquar.resources;
import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
@Path("/injectdemo")
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.TEXT_PLAIN)
public class InjectDemoResource {
@GET
@Path("annotations")
public String getParamsUsingAnnotations(@MatrixParam("param") String matrixParam,
@HeaderParam("authSessionID") String header,
@CookieParam("name") String cookie) {
return "Matrix param: " + matrixParam + " Header param: " + header + " Cookie param: " + cookie;
}
@GET
@Path("context")
public String getParamsUsingContext(@Context UriInfo uriInfo, @Context HttpHeaders headers) {
String path = uriInfo.getAbsolutePath().toString();
String cookies = headers.getCookies().toString();
return "Path : " + path + " Cookies: " + cookies;
}
}
CommentResource.java
package org.viquar.resources;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.viquar.model.Comment;
import org.viquar.service.CommentService;
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class CommentResource {
private CommentService commentService = new CommentService();
@GET
public List<Comment> getAllComments(@PathParam("messageId") long messageId) {
return commentService.getAllComments(messageId);
}
@POST
public Comment addComment(@PathParam("messageId") long messageId, Comment comment) {
return commentService.addComment(messageId, comment);
}
@PUT
@Path("/{commentId}")
public Comment updateComment(@PathParam("messageId") long messageId, @PathParam("commentId") long id, Comment comment) {
comment.setId(id);
return commentService.updateComment(messageId, comment);
}
@DELETE
@Path("/{commentId}")
public void deleteComment(@PathParam("messageId") long messageId, @PathParam("commentId") long commentId) {
commentService.removeComment(messageId, commentId);
}
@GET
@Path("/{commentId}")
public Comment getMessage(@PathParam("messageId") long messageId, @PathParam("commentId") long commentId) {
return commentService.getComment(messageId, commentId);
}
}
MessageFilterBean.java
package org.viquar.resources.beans;
import javax.ws.rs.QueryParam;
public class MessageFilterBean {
private @QueryParam("year") int year;
private @QueryParam("start") int start;
private @QueryParam("size") int size;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
CommentService.java
package org.viquar.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.viquar.database.DatabaseClass;
import org.viquar.model.Comment;
import org.viquar.model.ErrorMessage;
import org.viquar.model.Message;
public class CommentService {
private Map<Long, Message> messages = DatabaseClass.getMessages();
public List<Comment> getAllComments(long messageId) {
Map<Long, Comment> comments = messages.get(messageId).getComments();
return new ArrayList<Comment>(comments.values());
}
public Comment getComment(long messageId, long commentId) {
ErrorMessage errorMessage = new ErrorMessage("Not found", 404, "http://CosineOTC.Viquar.poc");
Response response = Response.status(Status.NOT_FOUND)
.entity(errorMessage)
.build();
Message message = messages.get(messageId);
if (message == null) {
throw new WebApplicationException(response);
}
Map<Long, Comment> comments = messages.get(messageId).getComments();
Comment comment = comments.get(commentId);
if (comment == null) {
throw new NotFoundException(response);
}
return comment;
}
public Comment addComment(long messageId, Comment comment) {
Map<Long, Comment> comments = messages.get(messageId).getComments();
comment.setId(comments.size() + 1);
comments.put(comment.getId(), comment);
return comment;
}
public Comment updateComment(long messageId, Comment comment) {
Map<Long, Comment> comments = messages.get(messageId).getComments();
if (comment.getId() <= 0) {
return null;
}
comments.put(comment.getId(), comment);
return comment;
}
public Comment removeComment(long messageId, long commentId) {
Map<Long, Comment> comments = messages.get(messageId).getComments();
return comments.remove(commentId);
}
}
MessageService.java
package org.viquar.service;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import org.viquar.database.DatabaseClass;
import org.viquar.exception.DataNotFoundException;
import org.viquar.model.Message;
public class MessageService {
private Map<Long, Message> messages = DatabaseClass.getMessages();
public MessageService() {
messages.put(1L, new Message(1, "Hello World", "ViquarKhan"));
messages.put(2L, new Message(2, "Hello Jersey", "Shahbazkhan"));
messages.put(3L, new Message(3, "Hello Cosine", "Snehaghosh"));
}
public List<Message> getAllMessages() {
return new ArrayList<Message>(messages.values());
}
public List<Message> getAllMessagesForYear(int year) {
List<Message> messagesForYear = new ArrayList<>();
Calendar cal = Calendar.getInstance();
for (Message message : messages.values()) {
cal.setTime(message.getCreated());
if (cal.get(Calendar.YEAR) == year) {
messagesForYear.add(message);
}
}
return messagesForYear;
}
public List<Message> getAllMessagesPaginated(int start, int size) {
ArrayList<Message> list = new ArrayList<Message>(messages.values());
if (start + size > list.size()) return new ArrayList<Message>();
return list.subList(start, start + size);
}
public Message getMessage(long id) {
Message message = messages.get(id);
if (message == null) {
throw new DataNotFoundException("Message with id " + id + " not found");
}
return message;
}
public Message addMessage(Message message) {
message.setId(messages.size() + 1);
messages.put(message.getId(), message);
return message;
}
public Message updateMessage(Message message) {
if (message.getId() <= 0) {
return null;
}
messages.put(message.getId(), message);
return message;
}
public Message removeMessage(long id) {
return messages.remove(id);
}
}
ProfileService.java
package org.viquar.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.viquar.database.DatabaseClass;
import org.viquar.model.Profile;
public class ProfileService {
private Map<String, Profile> profiles = DatabaseClass.getProfiles();
public ProfileService() {
profiles.put("Viquar", new Profile(1L, "Viquar", "Viquar", "Khan"));
profiles.put("Shahbaz", new Profile(2L, "Shahbaz", "Shahbaz", "Khan"));
profiles.put("Sneha", new Profile(3L, "Sneha", "Sneha", "Ghosh"));
}
public List<Profile> getAllProfiles() {
return new ArrayList<Profile>(profiles.values());
}
public Profile getProfile(String profileName) {
return profiles.get(profileName);
}
public Profile addProfile(Profile profile) {
profile.setId(profiles.size() + 1);
profiles.put(profile.getProfileName(), profile);
return profile;
}
public Profile updateProfile(Profile profile) {
if (profile.getProfileName().isEmpty()) {
return null;
}
profiles.put(profile.getProfileName(), profile);
return profile;
}
public Profile removeProfile(String profileName) {
return profiles.remove(profileName);
}
}
SwaggerRestApp.java
包 org.viquar.swegger;
import com.wordnik.swagger.config.ConfigFactory;
import com.wordnik.swagger.config.ScannerFactory;
import com.wordnik.swagger.config.SwaggerConfig;
import com.wordnik.swagger.jaxrs.config.ReflectiveJaxrsScanner;
import com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider;
import com.wordnik.swagger.jaxrs.listing.ApiListingResource;
import com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON;
import com.wordnik.swagger.jaxrs.listing.ResourceListingProvider;
import com.wordnik.swagger.jaxrs.reader.DefaultJaxrsApiReader;
import com.wordnik.swagger.reader.ClassReaders;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.message.MessageProperties;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.viquar.resources.MessageResource;
import javax.annotation.PostConstruct;
import javax.ws.rs.ApplicationPath;
//@Component
@ApplicationPath("api")
public class SwaggerRestApp extends ResourceConfig {
public SwaggerRestApp(){
register(MessageResource.class);
register(JacksonFeature.class);
//register(AllExceptionMapper.class);
register(ApiListingResource.class);
register(ApiDeclarationProvider.class);
register(ApiListingResourceJSON.class);
register(ResourceListingProvider.class);
property(MessageProperties.XML_FORMAT_OUTPUT, true);
property(ServerProperties.TRACING, "ALL");
}
@PostConstruct
/**
* Initializes Swagger Configuration
*/
public void initializeSwaggerConfiguration() {
final ReflectiveJaxrsScanner scanner = new ReflectiveJaxrsScanner();
scanner.setResourcePackage("org.viquar);
ScannerFactory.setScanner(scanner);
ClassReaders.setReader(new DefaultJaxrsApiReader());
final SwaggerConfig config = ConfigFactory.config();
config.setApiVersion("1.0");
config.setBasePath("http://localhost:8080/messenger/cosineotc/api/v1");
}
}
由于限制问题下一个评论继续.....
第 2 部分继续......
现在您必须配置 Webapp,使用以下名称创建文件夹并复制文件夹内的内容
复制 CSS 到 JerseyRestSSweggerPoc\src\main\webapp\css
复制JerseyRestSSweggerPoc\src\main\webapp\fonts
里面的字体
复制JerseyRestSSweggerPoc\src\main\webapp\images
里面的图片
在JerseyRestSSweggerPoc\src\main\webapp\lang
中复制lang
复制JerseyRestSSweggerPoc\src\main\webapp\lib
里面的库
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16" />
<link href='css/typography.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>
<link href='css/print.css' media='print' rel='stylesheet' type='text/css'/>
<script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
<script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
<script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
<script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
<script src='lib/handlebars-2.0.0.js' type='text/javascript'></script>
<script src='lib/underscore-min.js' type='text/javascript'></script>
<script src='lib/backbone-min.js' type='text/javascript'></script>
<script src='swagger-ui.js' type='text/javascript'></script>
<script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
<script src='lib/marked.js' type='text/javascript'></script>
<script src='lib/swagger-oauth.js' type='text/javascript'></script>
<!-- Some basic translations -->
<!-- <script src='lang/translator.js' type='text/javascript'></script> -->
<!-- <script src='lang/ru.js' type='text/javascript'></script> -->
<!-- <script src='lang/en.js' type='text/javascript'></script> -->
<script type="text/javascript">
$(function () {
var url = window.location.search.match(/url=([^&]+)/);
if (url && url.length > 1) {
url = decodeURIComponent(url[1]);
} else {
url = "http://localhost:8080/messenger/api/v1/api-docs";
}
// Pre load translate...
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
window.swaggerUi = new SwaggerUi({
url: url,
dom_id: "swagger-ui-container",
supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
onComplete: function(swaggerApi, swaggerUi){
if(typeof initOAuth == "function") {
initOAuth({
clientId: "your-client-id",
clientSecret: "your-client-secret",
realm: "your-realms",
appName: "your-app-name",
scopeSeparator: ","
});
}
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
$('pre code').each(function(i, e) {
hljs.highlightBlock(e)
});
addApiKeyAuthorization();
},
onFailure: function(data) {
log("Unable to Load SwaggerUI");
},
docExpansion: "none",
apisSorter: "alpha",
showRequestHeaders: false
});
function addApiKeyAuthorization(){
var key = encodeURIComponent($('#input_apiKey')[0].value);
if(key && key.trim() != "") {
var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("api_key", key, "query");
window.swaggerUi.api.clientAuthorizations.add("api_key", apiKeyAuth);
log("added key " + key);
}
}
$('#input_apiKey').change(addApiKeyAuthorization);
// if you have an apiKey you would like to pre-populate on the page for demonstration purposes...
/*
var apiKey = "myApiKeyXXXX123456789";
$('#input_apiKey').val(apiKey);
*/
window.swaggerUi.load();
function log() {
if ('console' in window) {
console.log.apply(console, arguments);
}
}
});
</script>
</head>
<body class="swagger-section">
<div id='header'>
<div class="swagger-ui-wrap">
<a id="logo" href="http://swagger.io">swagger</a> -->
<form id='api_selector'>
<div class='input'><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/></div>
<div class='input'><input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/></div>
<div class='input'><a id="explore" href="#" data-sw-translate>Explore</a></div>
</form>
</div>
</div>
<div id="message-bar" class="swagger-ui-wrap" data-sw-translate> </div>
<div id="swagger-ui-container" class="swagger-ui-wrap"></div>
</body>
</html>
Index.jsp
<html>
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16" />
<link href='css/typography.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>
<link href='css/print.css' media='print' rel='stylesheet' type='text/css'/>
<script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
<script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
<script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
<script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
<script src='lib/handlebars-2.0.0.js' type='text/javascript'></script>
<script src='lib/underscore-min.js' type='text/javascript'></script>
<script src='lib/backbone-min.js' type='text/javascript'></script>
<script src='swagger-ui.js' type='text/javascript'></script>
<script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
<script src='lib/marked.js' type='text/javascript'></script>
<script src='lib/swagger-oauth.js' type='text/javascript'></script>
<!-- Some basic translations -->
<!-- <script src='lang/translator.js' type='text/javascript'></script> -->
<!-- <script src='lang/ru.js' type='text/javascript'></script> -->
<!-- <script src='lang/en.js' type='text/javascript'></script> -->
<script type="text/javascript">
$(function () {
var url = window.location.search.match(/url=([^&]+)/);
if (url && url.length > 1) {
url = decodeURIComponent(url[1]);
} else {
url = "http://petstore.swagger.io/v2/swagger.json";
}
// Pre load translate...
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
window.swaggerUi = new SwaggerUi({
url: url,
dom_id: "swagger-ui-container",
supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
onComplete: function(swaggerApi, swaggerUi){
if(typeof initOAuth == "function") {
initOAuth({
clientId: "your-client-id",
clientSecret: "your-client-secret",
realm: "your-realms",
appName: "your-app-name",
scopeSeparator: ","
});
}
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
$('pre code').each(function(i, e) {
hljs.highlightBlock(e)
});
addApiKeyAuthorization();
},
onFailure: function(data) {
log("Unable to Load SwaggerUI");
},
docExpansion: "none",
apisSorter: "alpha",
showRequestHeaders: false
});
function addApiKeyAuthorization(){
var key = encodeURIComponent($('#input_apiKey')[0].value);
if(key && key.trim() != "") {
var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("api_key", key, "query");
window.swaggerUi.api.clientAuthorizations.add("api_key", apiKeyAuth);
log("added key " + key);
}
}
$('#input_apiKey').change(addApiKeyAuthorization);
// if you have an apiKey you would like to pre-populate on the page for demonstration purposes...
/*
var apiKey = "myApiKeyXXXX123456789";
$('#input_apiKey').val(apiKey);
*/
window.swaggerUi.load();
function log() {
if ('console' in window) {
console.log.apply(console, arguments);
}
}
});
</script>
</head>
<body>
<h2>Jersey RESTful Web Application!</h2>
<p><a href="webapi/myresource">Jersey resource</a>
<p>Visit <a href="http://jersey.java.net">Project Jersey website</a>
for more information on Jersey!
</body>
</html>
o2c.html
<script>
var qp = null;
if(window.location.hash) {
qp = location.hash.substring(1);
}
else {
qp = location.search.substring(1);
}
qp = qp ? JSON.parse('{"' + qp.replace(/&/g, '","').replace(/=/g,'":"') + '"}',
function(key, value) {
return key===""?value:decodeURIComponent(value) }
):{}
if (window.opener.swaggerUi.tokenUrl)
window.opener.processOAuthCode(qp);
else
window.opener.onOAuthComplete(qp);
window.close();
</script>
希望对您有所帮助。
URL 用于访问
http://localhost:8080/messenger//api/v1/messages/1
**Swegger** :
http://localhost:8080/messenger/
http://localhost:8080/jersey-swagger/rest/api-docs
http://localhost:8080/jersey-swagger/#!/employees/createEmployee
http://localhost:8080/messenger//api/v1/api-docs
http://localhost:8080/messenger/#!/messages/getMessage
http://localhost:8080/messenger//api/v1/messages/1
{
"author":"Viquar Khan","created":"2015-07-31T16:35:43.498",
"id":1,
"links":[
{"link":"http://localhost:8080/JerseyRestPoc//api/v1/messages/1","rel":"self"},
{"http://localhost:8080/JerseyRestPoc//api/v1/profiles/Viquar%20Khan","rel":"profile"},
{"link":"http://localhost:8080/JerseyRestPoc/api/v1/messages/1/comments/","rel":"comments"}
],
"message":"Hello World"
}
在 MessageResource.java 内部,我为 Swagger 添加了以下注释
@Api(value = "/messages", description = "Operation about orders")