Springfox Reference Documentation

1. Introduction

The Springfox suite of java libraries are all about automating the generation of machine and human readable specifications for JSON APIs written using the spring family of projects. Springfox works by examining an application, once, at runtime to infer API semantics based on spring configurations, class structure and various compile time java Annotations.

1.1. History

Springfox has evolved from a project originally created by Marty Pitt and was named swagger-springmvc. Much kudos goes to Marty.

1.2. Goals

  • To extend support for a number of the evolving standards targeted at JSON API specification and documentation such as: swaggerRAML and jsonapi.
  • To extend support for spring technologies other than spring webmvc
  • Philosophically, we want to discourage using (swagger-core) annotations that are not material to the service description at runtime. For e.g. the jackson annotations should always trump or have more weight than@ApiModelProperty or for e.g. @NotNull or specifying @RequestParam#required should always win. Annotations are to to be used only to supplement documentation or override/tweak the resulting spec in cases where its not possible to infer service/schema characteristics.

1.3. What it’s not

Endorsed or approved by the Spring Framework Contributors

1.4. Development Environment

  • File >> open >> build.gradle
  • Make sure to check the 'use the default gradle wrapper' option.
  • First time build
./gradlew cleanIdea idea
  • To get more output from any gradle commands/tasks append a -i (info) or -d (debug) e.g.
./gradlew build -i
  • To publish to local maven repository
./gradlew clean build publishToMavenLocal -i
  This build is optimized for releasing software to bintray/sonatype. In order for gradle to figure out the version the gradle plugin relies on local folder being a cloned git repository. Downloading the source archive and building will NOT work!

1.4.1. Pre-Commit Build

  • Code quality (code coverage, checkstyle)
./gradlew check

1.4.2. Building reference documentation

To view the docs in a browser run:

./gradlew docs

When frequently generating the docs use the Gradle daemon as follows

 ./gradlew asciidoc --daemon

1.4.3. CI Environment

Circle CI

1.5. Releasing

To release a non-snapshot version of Springfox:

  • Execute the the release commands: The below properties are required to run a release:
  • GITHUB_TOKEN
  • BINTRAY_USERNAME
  • BINTRAY_PASSWORD

Recommend using [autoenv](https://github.com/kennethreitz/autoenv) with a .env file at the root of the repo.

    ./gradlew release publishDocs -PbintrayUsername=$BINTRAY_USERNAME -PbintrayPassword=$BINTRAY_PASSWORD
    -PreleaseType=<MAJOR|MINOR|PATCH> -i

The release steps are as follows: - check that the git workspace is clean - check that the local git branch is master - check that the local git branch is the same as origin - gradle test - gradle check - upload (publish) all artifacts to Bintray - Bumps the project version in version.properties - Git tag the release - Git push

1.5.1. Snapshot

This is normally done by the CI server

./gradlew snapshot -PbintrayUsername=<bintrayUsername> -PbintrayPassword=<bintrayPassword>

1.5.2. Override deploy

To bypass the standard release flow and upload directly to bintray use the following task - manually set the version in version.properties

./gradlew clean build bintrayUpload -PbintrayUsername=$BINTRAY_USERNAME -PbintrayPassword=$BINTRAY_PASSWORD -PreleaseType=<MAJOR|MINOR|PATCH>
 --stacktrace

1.5.3. Updating documentation

To update the docs for an existing release pass the updateMode switch

./gradlew publishDocs -PupdateMode

1.5.4. Contributing

Please see the wiki for some guidelines

1.6. Support

If you find issues or bugs please submit them via the Springfox Github project

2. Getting Started

2.1. Dependencies

The Springfox libraries are hosted on bintray and jcenter. The artifacts can be viewed accessed at the following locations:

Springfox has multiple modules and the dependencies will vary depending on the desired API specification standard. Below outlines how to include the springfox-swagger2 module which produces Swagger 2.0 API documentation.

2.1.1. Gradle

Release
repositories {
  jcenter()
}

dependencies {
    compile "io.springfox:springfox-swagger2:2.6.1"
}
Snapshot
repositories {
   maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local/' }
}

dependencies {
    compile "io.springfox:springfox-swagger2:2.6.2-SNAPSHOT"
}

2.1.2. Maven

Release
<repositories>
    <repository>
      <id>jcenter-snapshots</id>
      <name>jcenter</name>
      <url>https://jcenter.bintray.com/</url>
    </repository>
</repositories>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.6.1</version>
</dependency>
Snapshot
<repositories>
    <repository>
      <id>jcenter-snapshots</id>
      <name>jcenter</name>
      <url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
    </repository>
</repositories>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.6.2-SNAPSHOT</version>
</dependency>

2.1.3. Springfox-swagger2 with Spring MVC and Spring Boot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 *
 *  Copyright 2015 the original author or authors.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *
 */

package springfox.springconfig;

import com.fasterxml.classmate.TypeResolver;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.async.DeferredResult;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.schema.WildcardType;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.Tag;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.ApiKeyVehicle;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import springfox.petstore.controller.PetController;

import java.util.List;

import static com.google.common.collect.Lists.*;
import static springfox.documentation.schema.AlternateTypeRules.*;

@SpringBootApplication
@EnableSwagger2
@ComponentScan(basePackageClasses = {
    PetController.class
})
public class Swagger2SpringBoot {

  public static void main(String[] args) {
    ApplicationContext ctx = SpringApplication.run(Swagger2SpringBoot.class, args);
  }

  @Bean
  public Docket petApi() {
    return new Docket(DocumentationType.SWAGGER_2)
        .select()
          .apis(RequestHandlerSelectors.any())
          .paths(PathSelectors.any())
          .build()
        .pathMapping("/")
        .directModelSubstitute(LocalDate.class,
            String.class)
        .genericModelSubstitutes(ResponseEntity.class)
        .alternateTypeRules(
            newRule(typeResolver.resolve(DeferredResult.class,
                    typeResolver.resolve(ResponseEntity.class, WildcardType.class)),
                typeResolver.resolve(WildcardType.class)))
        .useDefaultResponseMessages(false)
        .globalResponseMessage(RequestMethod.GET,
            newArrayList(new ResponseMessageBuilder()
                .code(500)
                .message("500 message")
                .responseModel(new ModelRef("Error"))
                .build()))
        .securitySchemes(newArrayList(apiKey()))
        .securityContexts(newArrayList(securityContext()))
        .enableUrlTemplating(true)
        .globalOperationParameters(
            newArrayList(new ParameterBuilder()
                .name("someGlobalParameter")
                .description("Description of someGlobalParameter")
                .modelRef(new ModelRef("string"))
                .parameterType("query")
                .required(true)
                .build()))
        .tags(new Tag("Pet Service", "All apis relating to pets"))
        .additionalModels(typeResolver.resolve(AdditionalModel.class))
        ;
  }

  @Autowired
  private TypeResolver typeResolver;

  private ApiKey apiKey() {
    return new ApiKey("mykey", "api_key", "header");
  }

  private SecurityContext securityContext() {
    return SecurityContext.builder()
        .securityReferences(defaultAuth())
        .forPaths(PathSelectors.regex("/anyPath.*"))
        .build();
  }

  List<SecurityReference> defaultAuth() {
    AuthorizationScope authorizationScope
        = new AuthorizationScope("global", "accessEverything");
    AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
    authorizationScopes[0] = authorizationScope;
    return newArrayList(
        new SecurityReference("mykey", authorizationScopes));
  }

  @Bean
  SecurityConfiguration security() {
    return new SecurityConfiguration(
        "test-app-client-id",
        "test-app-client-secret",
        "test-app-realm",
        "test-app",
        "apiKey",
        ApiKeyVehicle.HEADER,
        "api_key",
        "," /*scope separator*/);
  }

  @Bean
  UiConfiguration uiConfig() {
    return new UiConfiguration(
        "validatorUrl",// url
        "none",       // docExpansion          => none | list
        "alpha",      // apiSorter             => alpha
        "schema",     // defaultModelRendering => schema
        UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS,
        false,        // enableJsonEditor      => true | false
        true,         // showRequestHeaders    => true | false
        60000L);      // requestTimeout => in milliseconds, defaults to null (uses jquery xh timeout)
  }
}
Configuration explained
  This library extensively uses googles guava library. For e.g. when you see newArrayList(…​) its actually the guava equivalent of creating an normal array list and adding item(s) to it.
//This guava code snippet
List<Something> guavaList = newArrayList(new Something);

//... is equivalent to
List<Something> list = new ArrayList<Something>();
list.add(new Something());
  Enables Springfox swagger 2
  Instructs spring where to scan for API controllers
  Docket, Springfox’s, primary api configuration mechanism is initialized for swagger specification 2.0
  select() returns an instance of ApiSelectorBuilder to give fine grained control over the endpoints exposed via swagger.
  apis() allows selection of RequestHandler’s using a predicate. The example here uses an `any predicate (default). Out of the box predicates provided are anynonewithClassAnnotationwithMethodAnnotation andbasePackage.
  paths() allows selection of Path’s using a predicate. The example here uses an `any predicate (default)
  The selector requires to be built after configuring the api and path selectors. Out of the box we provide predicates for regexantanynone
  Adds a servlet path mapping, when the servlet has a path mapping. this prefixes paths with the provided path mapping
  Convenience rule builder substitutes LocalDate with String when rendering model properties
  Convenience rule builder that substitutes a generic type with one type parameter with the type parameter. In this example ResponseEntity<T> with TalternateTypeRules allows custom rules that are a bit more involved. The example substitutes DeferredResult<ResponseEntity<T>> with T generically
  Flag to indicate if default http response codes need to be used or not
  Allows globally overriding response messages for different http methods. In this example we override the 500 error code for all `GET`s …​
  …​and indicate that it will use the response model Error (which will be defined elsewhere)
  Sets up the security schemes used to protect the apis. Supported schemes are ApiKey, BasicAuth and OAuth
  Provides a way to globally set up security contexts for operation. The idea here is that we provide a way to select operations to be protected by one of the specified security schemes.
  Here we use ApiKey as the security schema that is identified by the name mykey
  Selector for the paths this security context applies to.
  Here we same key defined in the security scheme mykey
  Optional swagger-ui security configuration for oauth and apiKey settings
  Optional swagger-ui ui configuration currently only supports the validation url
  Incubating * setting this flag signals to the processor that the paths generated should try and use form style query expansion. As a result we could distinguish paths that have the same path stem but different query string combinations. An example of this would be two apis:
  Allows globally configuration of default path-/request-/headerparameters which are common for every rest operation of the api, but aren`t needed in spring controller method signature (for example authenticaton information). Parameters added here will be part of every API Operation in the generated swagger specification.
  How do you want to transport the api key via a HEADER (header) or QUERY_PARAM (query)?
  What header key needs to be used to send the api key. By default this value is set to api_key. Depending on how the security is setup the name of the header used may need to be different. Overriding this value is a way to override the default behavior.
  Adding tags is a way to define all the available tags that services/operations can opt into. Currently this only has name and description.
  Are there models in the application that are not "reachable"? Not reachable is when we have models that we would like to be described but aren’t explicitly used in any operation. An example of this is an operation that returns a model serialized as a string. We do want to communicate the expectation of the schema for the string. This is a way to do exactly that. There are plenty of more options to configure the Docket. This should provide a good start.
Support for Spring Data Rest

In version greater than 2.6.0, support for spring data rest was added.

  This is still in incubation.

In order to use it

  add the springfox-data-rest dependency.
Gradle
dependencies {
    compile "io.springfox:springfox-data-rest:2.6.1"
}
Maven
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-data-rest</artifactId>
    <version>2.6.1</version>
</dependency>
  Import the configuration from the springfox-data-rest module as shown below
java config
//For java config
@Import({ ... springfox.documentation.spring.data.rest.configuration.SpringDataRestConfiguration.class, ...})
xml config

Import the bean in your xml configuration by defining a bean of the following type

<bean class="springfox.documentation.spring.data.rest.configuration.SpringDataRestConfiguration.class" />
Support for JSR-303

In version greater than 2.3.2, support for bean validation annotations was added, specifically for @NotNull, @Min, @Max, and @Size.

In order to use it

  add the springfox-bean-validators dependency.
Gradle
dependencies {
    compile "io.springfox:springfox-bean-validators:2.6.1"
}
Maven
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-bean-validators</artifactId>
    <version>2.6.1</version>
</dependency>
  Import the configuration from the springfox-bean-validators module as shown below
java config
//For java config
@Import({ ... springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration.class, ...})
xml config

Import the bean in your xml configuration by defining a bean of the following type

<bean class="springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration" />
Swagger UI

The springfox-swagger-ui web jar ships with Swagger UI. To include it in a standard Spring Boot application you can add the dependency as follows:

dependencies {
    compile 'io.springfox:springfox-swagger-ui:2.6.1'
}

Pulling in the dependency creates a webjar containing the swagger-ui static content. It adds a JSON endpoint /swagger-resources which lists all of the swagger resources and versions configured for a given application. The Swagger UI page should then be available at http://localhost:8080/swagger-ui.html

The swagger ui version is specified in ./build.gradle where swaggerUiVersion is a git tag on the https:// github.com/swagger-api/swagger-ui[swagger-ui repo].

All content is served from a webjar convention, relative url taking the following form: webjars/springfox-swagger-ui/2.6.1/swagger-ui.html

By default Spring Boot has sensible defaults for serving content from webjars. To configure vanilla spring web mvc apps to serve webjar content see the webjar documentation

Swagger-Ui that comes bundled with springfox uses meta-urls to configure itself and discover documented endpoints. The urls for the discovery are as shown below.

Url New Url in 2.5.+ Purpose

/configuration/ui


/swagger-resources/configuration/ui


Configuring swagger-ui options


/configuration/security


/swagger-resources/configuration/security


Configuring swagger-ui security

Since swagger ui is a static resource it needs to rely on known endpoints to configure itself at runtime. So these ️ are *cool uris that cannot change. There is some customization that is possible, but swagger-ui needs to be available at the root of the webcontext.

Regarding [where swagger-ui itself is served](http://springfox.github.io/springfox/docs/current/#q13) and [where the api docs are served](http://springfox.github.io/springfox/docs/current/#customizing-the-swagger-endpoints) those are totally configurable.

RFC6570 support incubating
  Keep in mind this is experimental! In order to use this feature 1. Add springfox-swagger-ui-rfc6570instead of springfox-swagger-ui as a dependency experimental swagger-ui.

For gradle:

dependencies {
    compile 'io.springfox.ui:springfox-swagger-ui-rfc6570:1.0.0'
}

For maven:

<dependency>
    <groupId>io.springfox.ui</groupId>
    <artifactId>springfox-swagger-ui-rfc6570</artifactId>
    <version>1.0.0</version>
</dependency>
  The newer version has changed the group id from io.springfox to io.springfox.ui!
  1. Enable url templating; (see #21)

2.2. Springfox samples

The springfox-demos repository contains a number of samples.

3. Architecture

3.1. Background

When we started work on 2.0 swagger specification we realized that we’re rewriting the logic to infer the service models and the schema. So we decided to take a step back and break it out into a two step process. First infer the service model into an internal representation. Second create a mapping layer that can map the internal models to different specification formats. Out of the box we will support swagger 1.2 and swagger 2.0, but this leads us to the possibility of supporting other formats and other scenarios as well e.g. RAML, ALPS and hypermedia formats.

3.2. Component Model

The different SpringFox modules are split up as shown below.

        +-----------------------------------------------------------------------------------------+
        |                                  springfox-core                                         |
        |                                                                                         |
        | Contains the internal service and schema description models along with their builders.  |
        +------------------------------------------+----------------------------------------------+
                                                   ^
        +------------------------------------------+----------------------------------------------+
        |                                  springfox-spi                                          |
        |                                                                                         |
        | Contains the service provider interfaces that can be used to extend and enrich the      |
        | service models e.g. swagger specific annotation processors.                             |
        +------------------------------------------+----------------------------------------------+
                                                   |
                                                   |
                        +--------------------------|------------------------+
                        |                          |                        |
        +----------------------------------+       |       +--------------------------------------+
        |        springfox-schema          |       |       |         springfox-spring-web         |
        |                                  |       |       |                                      |
        | Schema inference extensions that |       |       | spring web specific extensions that  |
        | help build up the schema for the |       |       | can build the service models based   |
        |  the parameters, models and      |       |       | on RequestMapping information.       |
        |  responses                       |       |       | This is the heart library that       |
        +----------------------------------+       |       | infers the service model.            |
                                                   |       +--------------------------------------+
                                                   |
              +------------------------------------+------------------------------------+
              |                         springfox-swagger-common                        |
              |                                                                         |
              | Common swagger specific extensions that are aware of the different      |
              | swagger annotations.                                                    |
              +----------+--------------------------------------------------------------+
                         ^                          ^                        ^
              +----------+---------+     +----------+---------+     +-----...
              |                    |     |                    |     |
              | springfox-swagger1 |     | springfox-swagger2 |     |
              |                    |     |                    |     |
              +--------------------+     +--------------------+     +-----...

               Configurations, and mapping layer that know how to convert the service models
               to swagger 1.2 and swagger 2.0 specification documents.
               Also contains the controller for each of the specific formats.

4. Swagger

Springfox supports both version 1.2 and version 2.0 of the Swagger specification. Where possible, the Swagger 2.0 specification is preferable.

The swagger-core annotations, as provided by swagger-core, are typically used to decorate the java source code of an API which is bing 'swaggered'. Springfox is aware of the Swagger-Core Annotations and will favor those annotations over inferred defaults.

4.1. Swagger 1.2 vs Swagger 2.0

One major difference between the two swagger specification is the composition of the generated swagger documentation.

With Swagger 1.2 an applications API is represented as a Resource Listing and multiple API Declarations which has the implication of producing multiple JSON files

With Swagger 2.0 things are much simpler and an application’s API can be represented in a single JSON file.

4.2. Moving from swagger-springmvc?

Here is a guide to help with the transition from 1.0.2 to 2.0.

Legacy documentation is available here.

4.3. Springfox configuration and demo applications

The springfox-demos repository contains a number of sample Spring application which can be used a reference.

5. Configuring Springfox

To enable support for swagger specification 1.2 use the @EnableSwagger annotation

To enable support for swagger specification 2.0 use the @EnableSwagger2 annotation

To document the service we use a Docket. This is changed to be more inline with the fact that expressing the contents of the documentation is agnostic of the format the documentation is rendered.

Docket stands for A summary or other brief statement of the contents of a document; an abstract.

Docket helps configure a subset of the services to be documented and groups them by name. Significant changes to this is the ability to provide an expressive predicate based for api selection.

  import static springfox.documentation.builders.PathSelectors.*;
  import static com.google.common.base.Predicates.*;

  @Bean
  public Docket swaggerSpringMvcPlugin() {
    return new Docket(DocumentationType.SWAGGER_2)
            .groupName("business-api")
            .select()
               //Ignores controllers annotated with @CustomIgnore
              .apis(not(withClassAnnotation(CustomIgnore.class)) //Selection by RequestHandler
              .paths(paths()) // and by paths
              .build()
            .apiInfo(apiInfo())
            .securitySchemes(securitySchemes())
            .securityContext(securityContext());
  }

  //Here is an example where we select any api that matches one of these paths
  private Predicate<String> paths() {
    return or(
        regex("/business.*"),
        regex("/some.*"),
        regex("/contacts.*"),
        regex("/pet.*"),
        regex("/springsRestController.*"),
        regex("/test.*"));
  }

For a list of handy predicates Look at RequestHandlerSelectors and PathSelectors.

5.1. Configuring the ObjectMapper

A simple way to configure the object mapper is to listen for the ObjectMapperConfigured event. Regardless of whether there is a customized ObjectMapper in play with a corresponding MappingJackson2HttpMessageConverter, the library always has a configured ObjectMapper that is customized to serialize swagger 1.2 and swagger 2.0 types.

In order to do this implement the ApplicationListener<ObjectMapperConfigured> interface. The event has a handle to the ObjectMapper that was configured. Configuring application specific ObjectMapper customizations in this applicaiton event handler guarantees that application specific customizations will be applied to each and every ObjectMapper that is in play.

If you encounter a NullPointerException during application startup like this issue. Its because most likely the WebMvcConfigurerAdapter isn’t working. These adapter especially in a non-spring-boot scenarios will only get loaded if the @EnableWebMvc annotation is present.

If using Spring Boot Web MVC, there is no need to use the @EnableWebMvc annotation, as the framework automatically detects Web MVC usage and configures itself as appropriate. In this scenario, Springfox will not correctly generate and expose the Swagger UI endpoint (/swagger-ui.html) if @EnableWebMvc is present in the application.

Caveat to using the library is that it depends on Jackson for serialization, more importantly the ObjectMapper. A good example of where this breaks down is the following issue when using Gson serialization

5.2. Customizing the swagger endpoints.

By default the swagger service descriptions are generated at the following urls

Swagger version Documentation Url Group

2.0


/v2/api-docs?group=external


external group via docket.groupName()


1.2


/api-docs


implicit default group


2.0


/api-docs?group=external


external group via docket.groupName()


2.0


/v2/api-docs


implicit default group

To customize these endpoints, loading a property source with the following properties allows the properties to be overridden

Swagger version Override property

2.0


springfox.documentation.swagger.v2.path


1.2


springfox.documentation.swagger.v1.path

5.3. Overriding property datatypes

Using the ApiModelProperty#dataType we can override the inferred data types. However it is restricted to only allow data types to be specified with a fully qualified class name. For e.g. if we have the following definition

// if com.qualified.ReplaceWith is not a Class that can be created using Class.forName(...)
// Original will be replaced with the new class
@ApiModelProperty(dataType = "com.qualified.ReplacedWith")
public Original getOriginal() { ... }

// if ReplaceWith is not a Class that can be created using Class.forName(...) Original will be preserved
@ApiModelProperty(dataType = "ReplaceWith")
public Original getAnotherOriginal() { ... }

5.4. Docket XML Configuration

To use the plugin you must create a spring java configuration class which uses spring’s @Configuration. This config class must then be defined in your xml application context.

<!-- Required so springfox can access spring's RequestMappingHandlerMapping  -->
<mvc:annotation-driven/>

<!-- Required to enable Spring post processing on @Configuration classes. -->
<context:annotation-config/>

<bean class="com.yourapp.configuration.MySwaggerConfig"/>
@Configuration
@EnableSwagger //Loads the spring beans required by the framework
public class MySwaggerConfig {

   /**
    * Every Docket bean is picked up by the swagger-mvc framework - allowing for multiple
    * swagger groups i.e. same code base multiple swagger resource listings.
    */
   @Bean
   public Docket customDocket(){
      return new Docket(); //some customization goes here
   }

}

5.5. Docket Spring Java Configuration

  • Use the @EnableSwagger or @EnableSwagger2 annotation.
  • Define one or more Docket instances using springs @Bean annotation.
@Configuration
@EnableWebMvc //NOTE: Only needed in a non-springboot application
@EnableSwagger2
@ComponentScan("com.myapp.controllers")
public class CustomJavaPluginConfig {

   @Bean //Don't forget the @Bean annotation
   public Docket customImplementation(){
      return new Docket()
            .apiInfo(apiInfo());
            //... more options available

   }

   //...
}

5.5.1. Swagger group

A swagger group is a concept introduced by this library which is simply a unique identifier for a Swagger Resource Listing within your application. The reason this concept was introduced was to support applications which require more than one Resource Listing. Why would you need more than one Resource Listing? - A single Spring Web MVC application serves more than one API e.g. publicly facing and internally facing. - A single Spring Web MVC application serves multiple versions of the same API. e.g. v1 and v2

In most cases an application will not need more than one Resource Listing and the concept of swagger groups can be ignored.

5.5.2. Configuring the output of operationId in a Swagger 2.0 spec

As defined operationId was introduced in the Swagger 2.0 spec, the operationId parameter, which was referred to as nickname in pre-2.0 versions of the Swagger spec, provides the author a means by which to describe an API operation with a friendly name . This field is often used by consumers of a Swagger 2.0 spec in order to name functions in generated clients. An example of this can be seen in the swagger-codegen project.

The default value of operationId according to Springfox

By default, when using Springfox in Swagger 2.0 mode, the value of operationID will be rendered using the following structure: “[java_method_name_here]Using[HTTP_verb_here]”. For example, if one has a method getPets() connected to an HTTP GET verb, Springfox will render getPetsUsingGET for the operationId.

Given this annotated method …​
@ApiOperation(value = "")
@RequestMapping(value = "/pets", method = RequestMethod.GET)
public Model getAllThePets() {
    ...
}
the default operationId will render looking like this:
"paths": {
  "/pets": {
    "get": {
            ...
      "operationId":"getAllThePetsUsingGET"
      ...
    }
  }
}
Customizing the value of operationId

In the event you wish to overide the default operationId which Springfox renders, you may do so by providing thenickname element in an @ApiOperation annotation.

Given this annotated method …​
@ApiOperation(value = "", nickname = "getMeAllThePetsPlease")
@RequestMapping(value = "/pets", method = RequestMethod.GET)
public Model getAllThePets() {
    ...
}
…​ the customized operationId will render looking like this:
"paths": {
  "/pets": {
    "get": {
            ...
      "operationId":"getMeAllThePetsPlease"
      ...
    }
  }
}

5.5.3. Changing how Generic Types are Named

By default, types with generics will be labeled with '\u00ab'(<<), '\u00bb'(>>), and commas. This can be problematic with things like swagger-codegen. You can override this behavior by implementing your own GenericTypeNamingStrategy. For example, if you wanted List<String> to be encoded as 'ListOfString' and Map<String, Object> to be encoded as 'MapOfStringAndObject' you could set the forCodeGeneration customization option to true during plugin customization:

 docket.forCodeGeneration(true|false);

5.6. Caching

The caching feature that was introduced in 2.1.0 has been removed. Springfox no longer uses the cache abstraction to improve performance the api scanners and readers. It has been rolled into the library as an internal implementation detail as of 2.1.2. This is a runtime breaking change, however, since its not really breaking api compatibility change other than the introduction of configuration change in consuming applications, we’re not incrementing the minor version.

5.7. Configuring Security Schemes and Contexts an Overview

The security provisions in SpringFox at a high level, without getting into the code, has different pieces that all work together in concert

  • The API itself needs to be protected. This is achieved by using, for simplicity sake, spring security and may also use a combination of servlet container and tomcat/jersey etc.
  • The security scheme which describes the techniques you’ve used to protect the api. Spring fox supports whatever schemes swagger specification supports (ApiKey, BasicAuth and OAuth2 (certain profiles))
  • Finally the security contexts which actually provides information on which api’s are protected by which schemes. I think in your example, you’re missing the last piece of the puzzle, the security context see 15.

5.8. Extensibility

The library provides a variety of extensibility hooks to enrich/ augment the schema and service models

  • For enriching models and properties (TODO)
  • For enriching services models (TODO)

5.9. Example application

For an examples for spring-boot, vanilla spring applications take a look examples in the demo application.

6. Configuring springfox-staticdocs

Springfox-staticdocs is a module which brings together springfox and swagger2markup. Swagger2Markup is a library which simplifies the generation of an up-to-date RESTful API documentation by combining documentation that’s been hand-written with auto-generated API documentation produced by Springfox. The result is intended to be an up-to-date, easy-to-read, on- and offline user guide. Swagger2Markup converts a Swagger JSON or YAML file into several AsciiDoc or GitHub Flavored Markdown documents which can be converted to HTML, PDF and EPUB. The output of Swagger2Markup can be used as an alternative to swagger-ui and can be served as static content.

6.1. Usage guide

Adding springfox-staticdocs to your project

6.1.1. Maven

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>{releaseVersion}</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-staticdocs</artifactId>
    <version>{releaseVersion}</version>
    <scope>test</scope>
</dependency>

6.1.2. Gradle

dependencies {
    ...
    compile 'io.springfox:springfox-swagger2:{releaseVersion}'
    testCompile 'io.springfox:springfox-staticdocs:{releaseVersion}'
    ...
}

6.1.3. Generate Markup during an unit test

Spring’s MVC Test framework can be used to make a request to a springfox Swagger endpoint during an unit test. The ResultHandler Swagger2MarkupResultHandler can be used to convert the Swagger JSON response into an AsciiDoc document. The custom ResultHandler is part of springfox-staticdocs. That way you also verify that your Swagger endpoint is working. The following is an example with Spring Boot:

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class)
public class Swagger2MarkupTest {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;

    @Before
    public void setUp() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
    }

    @Test
    public void convertSwaggerToAsciiDoc() throws Exception {
        this.mockMvc.perform(get("/v2/api-docs")
                .accept(MediaType.APPLICATION_JSON))
                .andDo(Swagger2MarkupResultHandler.outputDirectory("src/docs/asciidoc/generated").build())
                .andExpect(status().isOk());
    }

    @Test
    public void convertSwaggerToMarkdown() throws Exception {
        this.mockMvc.perform(get("/v2/api-docs")
                .accept(MediaType.APPLICATION_JSON))
                .andDo(Swagger2MarkupResultHandler.outputDirectory("src/docs/markdown/generated")
                    .withMarkupLanguage(MarkupLanguage.MARKDOWN).build())
                .andExpect(status().isOk());
    }
}

If you want to combine the generated documentation with your hand-written documentation, then have a look at the user guide of swagger2Markup. You can also include generated CURL request, HTTP request and HTTP response example snippets from spring-restdocs into the generated documentation.

6.1.4. Generated HTML using Swagger2Markup and AsciidoctorJ

7. Plugins

7.1. Introduction

Any plugin or extensibility hook that is available is available in the SPI module. In the spi module, anything that ends in *Plugin is generally an extensibility point that is meant for library consumers to consume.

The bean validation (JSR-303) is a great example of a contribution to support bean validations. Its fairly simple and small in scope and should give an idea how one goes about creating a plugin. Its a set of plugins are act on ModelProperty, hence they are implementations of ModelPropertyBuilderPlugin.

7.2. Plugins Available For Extensibility

To explicitly state the extensibility points that are available: * At the schema level .Schema Plugins

Name Description

ModelBuilderPlugin


for enriching models


ModelPropertyBuilderPlugin


for enriching model properties


TypeNameProviderPlugin


these are for overriding names for models

Name Description

ApiListingScannerPlugin


for adding custom api descriptions


ApiListingBuilderPlugin


for enriching api listings


DefaultsProviderPlugin


for providing your own defaults


DocumentationPlugin


for enriching the documentation context


ExpandedParameterBuilderPlugin


for parameter expansion used in the context of @ModelAttribute


OperationBuilderPlugin


for enriching operations


OperationModelsProviderPlugin


for providing additional models that you might load a different way


ParameterBuilderPlugin


for enriching parameters

7.3. Steps To Create A Plugin

  The same patterns apply to all of the extensibility mechanisms
  1. Implement one of the above plugin interfaces
  2. Give the plugin an order for e.g. ApiParamParameterBuilder has an order specified in the bean. In general spring plugins get the highest priority, The swagger plugins (the ones that process all the @Api…​ annotations) layer information on top. So the order that you’d write will need to layer information at the end.
  3. Each plugin has
    • *context and provides access to any information that the plugin might need to do its job
    • *builder for the type of object that the plugin is intended to support for e.g. a ModelPropertyBuilderPlugin will have access to a ModelPropertyBuilder. This builder is what is used to build the model after all the plugins have had access to contribute/enrich the underlying object.
  4. Update any builder properties your plugin cares about
  5. Register the plugin as a @bean, so that the plugin registry can pick it up.

That is it!

8. Answers to common questions and problems

Q. Why does springfox ignore the http status code in the return value of a controller method?

  1. Reference #822

Q. What is the relationship between swagger-ui and springfox-swagger-ui?

  1. It can be a little confusing:

    • Swagger Spec is a specification.
    • Swagger Api - an implementation of that specification that supports jax-rs, restlet, jersey etc.
    • Springfox libraries in general - another implementation of the specification focused on the spring based ecosystem.
    • Swagger.js and Swagger-ui - are client libraries in javascript that can consume swagger specification.
    • springfox-swagger-ui - the one that you’re referring to, is just packaging swagger-ui in a convenient way so that spring services can serve it up.

Q. I use GSON and don’t use Jackson, What should I do?

  1. Thanks to @chrishuttonch for describing the solution to this issue
  I switched on the excludeFieldsWithoutExposeAnnotation() which meant that none of the objects would produce any data. To get around this I created several serialisers for the following classes:
.registerTypeAdapter(springfox.documentation.service.ApiListing.class, new SwaggerApiListingJsonSerializer())
.registerTypeAdapter(springfox.documentation.spring.web.json.Json.class, new SwaggerJsonSerializer())
.registerTypeAdapter(springfox.documentation.swagger.web.SwaggerResource.class, new SwaggerResourceSerializer())
.registerTypeAdapter(springfox.documentation.service.ResourceListing.class, new SwaggerResourceListingJsonSerializer())
.registerTypeAdapter(springfox.documentation.swagger.web.SwaggerResource.class, new SwaggerResourceSerializer())
.registerTypeAdapter(springfox.documentation.swagger.web.SecurityConfiguration.class, new SwaggerSecurityConfigurationSerializer())
.registerTypeAdapter(springfox.documentation.swagger.web.UiConfiguration.class, new SwaggerUiConfigurationSerializer());

Q. ObjectMapper weirdness in a spring-boot app?

  1. It is possible you’re experiencing one of the following issues

    1. NPE During startup?

        Running in debugger revealed that I had two instances of WebApplicationInitializers in my war. Spring is refreshing context with each one and is resulting in second instance of OptimizedModelPropertiesProvider without onApplicationEvent call. I was able to fix it by removing second WebApplicationInitializer in my code. Seems this is related to spring-boot issue #221 [1]
    2. Object Mapper Customizations Not Working?
        Sometimes there are multiple ObjectMapper in play and it may result in the customizations not working [2] Spring Boot in HttpMessageConverters first adds the Spring Boot configured MappingJackson2HttpMessageConverter and then it adds the default MappingJackson2HttpMessageConverter from Spring MVC. This causes the ObjectMapperConfigured event to fire twice, first for the configured converter (which is actually used) and then for the default converter. So when you f.e. set a custom property naming strategy then in ObjectMapperBeanPropertyNamingStrategy this is overwritten by the second event. The following code fixes this:
@Configuration
public class MyWebAutoConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        ObjectMapper objectMapper = null;
        for (HttpMessageConverter converter : converters) {
            if (converter instanceof MappingJackson2HttpMessageConverter) {
                MappingJackson2HttpMessageConverter jacksonConverter =
                        ((MappingJackson2HttpMessageConverter) converter);

                if (objectMapper == null) {
                    objectMapper = jacksonConverter.getObjectMapper();
                } else {
                    jacksonConverter.setObjectMapper(objectMapper);
                }
            }
        }
    }
}

Q. How do we use Java 8 types esply. LocalDateTime?

  1. The easiest way to to configure dates is via Docket#directModelSubstitute(LocalDateTime.class, String.class). If these are ISO 8601 dates that conform to a string format i.e. yyyy-MM-dd’T’HH:mm’Z'. However you won’t have any format or validation info.
  Use java.sql.Date works great for date precision and java.util.Date for date-time precision [3]

The way to correctly map the "Date" and "DateTime" types to their corresponding swagger types:

  • Substitute "Date" types (java.util.LocalDate, org.joda.time.LocalDate) by java.sql.Date.
  • Substitute "DateTime" types (java.util.ZonedDateTime, org.joda.time.LocalDateTime, …​) by java.util.Date.
docket
.directModelSubstitute(LocalDate.class, java.sql.Date.class)
.directModelSubstitute(LocalDateTime.class, java.util.Date.class)

Q. How does one use @ModelAttribute annotation. It doesn’t seem to render the model properties as scalar properties?

  1. In order for @ModelAttribute annotated types to be inferred the properties need to be bean properties. If the intent is immutability and passing in an object, the preferred approach is to make that a request body, in which case the immutability will follow the rules laid out by jackson to determine what constitutes a request "view" of the request object.

Getters/setters are a clean way to indicate what values can come in to a operation. While it may not be apparent in a trivial model with one level nesting; the design choice will become clear when we realize that model attributes can be arbitrarily nested. Consider (pseudo code in C# for brevity)

Person {String firstName {get;set;}
String lastName {get;set;}
Category category {get;set;}
Category {String name {get;set;}
String description {get;}

So one could set properties:

  • firstName
  • lastName
  • category.name

Now we don’t want category to be able to set description via the operation, how do we control/specify that? It makes it hard to reason about which fields in an object are not intended to be mutated. This is the reason we chose to limit it to objects that expose getters and setters.

  I know spring supports fields as well, and it will fall back to fields if setters are not found.

Q. How should we resolve multiple object mappers available as beans especially when using spring-hateoas?

  1. The idea is to provide a @Primary ObjectMapper. Based on answer provided by @prabhat1790 in issue #890
  private static final String SPRING_HATEOAS_OBJECT_MAPPER = "_halObjectMapper";

  @Autowired
  @Qualifier(SPRING_HATEOAS_OBJECT_MAPPER)
  private ObjectMapper springHateoasObjectMapper;

  @Primary
  @Bean
  @Order(value=Ordered.HIGHEST_PRECEDENCE)
  @DependsOn(SPRING_HATEOAS_OBJECT_MAPPER)
  public ObjectMapper objectMapper() {
    return springHateoasObjectMapper;
  }

and set the order of the other bean to lowest precedence.

Q. How do I use this library to aggregate swagger-enabled resources from multiple services?

  1. Logical explanation of how one might go about doing this is available in the swagger google group Additionally this comment further discusses issues with doing this.

Q. Why are my API params marked as required=false?

  1. This is because of how plugins work and how their priority layers information

    • @PathVariables are always marked as required.
    • @ApiParam is an optional annotation to describe additional meta-information like description etc.
    • @ApiParam#required() is defaulted to false, unless you set it to true.

Springfox uses plugins to layer information. There are a set of plugins that are spring specific that apply the inferred values on to the internal service models. The swagger annotation related metadata is layered on top of the spring-mvc descriptions. By definition, plugins don’t know and should not know about each other or previously inferred values (in your case required attribute).

So if you choose to augment the definitions with @ApiParam then you need to be explicit and set the value to true.

Q. How does one write a plugin to e.g. make default all types required and only some not required?

  1. To do this, you’d have to

    • add an alternate type rule for Optional<T> see genericModelSubstitutes in docket
    • implement your own ModelPropertyBuilderPlugin
    • and override the read only property if you find an Optional type. See here for an example.

Keep in mind that you need the plugin to fire after this plugin…​ so order it accordingly

Q. Why are all my operations not showing in the UI?

  1. This is a known limitation of swagger-spec. There is a work around for it but, swagger-ui won’t play nice with it. I have a PR which address that issue. Would be great if you vote up the PR and the underlying issue
  This PR has been closed!

Q. How would one partition apis based on versions?

  1. Excerpted from an explanation for issue 963…​

(springfox) uses the context path as the starting point.

What you really need to is to define a dynamic servlet registration and create 2 dockets .. one for api and one for api/v2. This SO post might help

    ...
      Dynamic servlet = servletContext.addServlet("v1Dispatcher", new DispatcherServlet(ctx1));
            servlet.addMapping("/api");
            servlet.setLoadOnStartup(1);

      Dynamic servlet = servletContext.addServlet("v2Dispatcher", new DispatcherServlet(ctx2));
            servlet.addMapping("/api/v2");
            servlet.setLoadOnStartup(1);

Q. How does one configure swagger-ui for non-springboot applications?

  1. Excerpted from issue 983…​

I was able to get it working by modifying the dispatcherServlet to listen on /* , but this prevented swagger-ui.htmlfrom being served. To fix this to let the swagger-ui.html bypass the dispatcherServlet i had to create a new servlet mapping:

        <servlet>
          <servlet-name>RestServlet</servlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
        </servlet>

        <servlet-mapping>
          <servlet-name>default</servlet-name>
            <url-pattern>/swagger-ui.html</url-pattern>
        </servlet-mapping>

        <servlet-mapping>
          <servlet-name>RestServlet</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>

Also had to let the webjar through the dispatcher servlet:

<mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"/>

Tricky to get working, but it works. Perhaps there is a better way to remap swagger-ui.html or let it pass through the dispatcherServlet.

  swagger-ui.html is the name of the swagger-ui page. While it cannot be changed one can configure the application such that landing on a particular URL re-directs the browser to the real swagger-ui location. [4]

For e.g. One could move Swagger UI under /documentation using this code.

        @Override
        public void addViewControllers(ViewControllerRegistry registry) {

                registry.addRedirectViewController("/documentation/v2/api-docs", "/v2/api-docs?group=restful-api");
                registry.addRedirectViewController("/documentation/swagger-resources/configuration/ui","/swagger-resources/configuration/ui");
                registry.addRedirectViewController("/documentation/swagger-resources/configuration/security","/swagger-resources/configuration/security");
                registry.addRedirectViewController("/documentation/swagger-resources", "/swagger-resources");
        }

        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
                 registry.
                         addResourceHandler("/documentation/swagger-ui.html**").addResourceLocations("classpath:/META-INF/resources/swagger-ui.html");
                registry.
                        addResourceHandler("/documentation/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        }

However, it still requires a redirect to /documentation/swagger-ui.html because the path name is hard-coded.

Q. How does one create rules to substitute list and array items?

  1. If the following types…​
    ToSubstitute[] array;
    List<ToSubstitute> list;

Need to look like this over the wire…​

    Substituted[] array;
    List<Substituted> list;

This is how the rules need to be configured

    rules.add(newRule(resolver.arrayType(ToSubstitute), resolver.arrayType(Substituted)))
    rules.add(newRule(resolver.resolve(List, ToSubstitute), resolver.resolve(List, Substituted)))

Q. How does one configure a docket with multiple protocols/schemes?

  1. Use the protocols method to configure the docket to indicate supported schemes.
    docket.protocols(newHashSet("http", "https"))

Q. How does one use springfox in a project with xml spring configuration?

  1. There is a demo application that describes how java-xml configuration needs to be setup.

Q. How does one override the host name?

  1. This should be available in v2.3 thanks to this PR by @cbornet. It is still in incubation but host name can be configured per docket
     docket.host("http://maybe-an-api-gateway.host");

Q. Infinite loop when springfox tries to determine schema for objects with nested/complex constraints?

  1. If you have recursively defined objects, I would try and see if providing an alternate type might work or perhaps even ignoring the offending classes e.g. order using the docket. ignoredParameterTypes(Order.class). This is usually found in Hibernate domain objects that have bidirectional dependencies on other objects.

Q. How are tags implemented in springfox?

Tags which are first class constructs just like operations, models etc. and what you see on operations are references to those Tags. The typical workflow is to register tags in a docket and use the tag definitions on operations(@ApiOperation)/controllers(@Api) to point to these registered tags (in the docket) by name.

The convenience we have in place just to reduce the amount of boiler plate for the developer is to provide a default description that happens to be the same as the tag name. So in effect we are synthesizing a pseudo Tag by referencing one on the operation.

By defining the Tag on the docket, we are referencing a real tag defined by you.

20. What can I try if configuration non-boot applications do not work as expected?

Thanks to @Pyohwan's suggestion @Configuration annotation may not working with @EnableSwagger2. So shouldn’t attach @Configration. So if you have a configuration class that pulls in the springfox configuration using the @EnableSwagger2 like below, try removing the @Configuration on this class as shown below.

@EnableSwagger2
public class SwaggerConfig {
...

and use @Import annotation on WebMvcConfigurerAdapter or similar configuration class.

@Configuration
@EnableWebMvc
@ComponentScan(...)
@Import(SwaggerConfig.class)
public class MvcConfig extends WebMvcConfigurerAdapter {
...


1. Thanks to @shasti421

2. thanks Jaap-van-Hengstum

3. thanks @cbronet

4. Thanks @chornyi

 

http://springfox.github.io/springfox/docs/current/#introduction

 

时间: 2024-10-16 12:35:35

Springfox Reference Documentation的相关文章

Spring Framework Reference Documentation 4.3.0.RELEASE

Spring Framework Reference Documentation 4.3.0.RELEASE Spring Framework Reference Documentation 4.3.0.RELEASE 中文版本 整理Spring Framework Reference Documentation 4.3.0.RELEASE 中文版本文档 想寻找中文版本的资源,但是发现网上基本没有,相关书籍也是极少 国内开源中国有针对4.1X版本的文档翻译 http://spring.oschi

TensorFlow教程之API DOC 6.1.17 TensorFlow C++ Session API reference documentation

本文档为TensorFlow参考文档,本转载已得到TensorFlow中文社区授权. TensorFlow C++ Session API reference documentation TensorFlow's public C++ API includes only the API for executing graphs, as of version 0.5. To control the execution of a graph from C++: Build the computati

Spring Data 官方文档》Reference Documentation至5.2. Examples Repository

文档结构 参考文档的这一部分讲解Spring Data Cassandra所提供的核心功能. Cassandra 支持 介绍 Cassandra 模块特性设置. Cassandra 资源库 介绍 Cassandra 所支持的资源. 5. Cassandra 支持 Cassandra 包含了非常广泛的特性, 其总结如下 Spring配置支持Cassandra驱动的实例类和副本集使用基于Java的@Configuration类或XML命名空间. CassandraTemplate帮助程序类,可提高执

How to generate links to the android Classes&amp;#39; reference in javadoc?

原文:http://stackoverflow.com/questions/2818204/how-to-generate-links-to-the-android-classes-reference-in-javadoc Javadoc relies on a file called package-list to determine what Java packages are documented below a given directory. For some reason, such

几款好的C/C++编译器(编译器而非IDE)

几个介绍IDE的博客: C/C++开发常用工具及系统编程 C/C++开发者必不可少的15款编译器+IDE C/C++圣战 大家说的都已经很多了,那么我在这里就不罗嗦口了,我着重讲下编译器. GCC(GNU Compiler Collection) 官方网站: https://gcc.gnu.org/ GCC有Windows移植版本,比较出名的就是MinGW和TDM-GCC MinGW :http://www.mingw.org/ TDM-GCC: http://tdm-gcc.tdragon.n

spring中DispatcherServlet的运行机制

servlet Spring中DispatcherServlet的运行机制 DispatcherServlet是spring的web框架(以下简称SpringWeb)中的核心servlet."Spring的web框架--象其它web框架一样--是一个请求驱动的web框架,其设计围绕一个能将请求分发到控制器的servlet,它也提供其它功能帮助web应用开发."----<Spring Framework 开发参考手册(中文版)>而在SpringWeb框架中这个servlet就

MDAC2.8 下载!

下载 最新版的MDAC(Microsoft Data Access Components)下载. ========================================== Microsoft Data Access Components (MDAC) PurposeThe Microsoft Data Access Components (MDAC) SDK documents the key technologies that enable Universal Data Acces

我的Android进阶之旅------&amp;gt;Android视频录制小例子

============================首先看看官网上关于视频捕捉的介绍================================ Capturing videos Video capture using the Android framework requires careful management of the Camera object and coordination with the MediaRecorder class. When recording vid

在Spring Boot项目中使用Spock框架

Spock框架是基于Groovy语言的测试框架,Groovy与Java具备良好的互操作性,因此可以在Spring Boot项目中使用该框架写优雅.高效以及DSL化的测试用例.Spock通过@RunWith注解与JUnit框架协同使用,另外,Spock也可以和Mockito(Spring Boot应用的测试--Mockito)协同使用. 在这个小节中我们会利用Spock.Mockito一起编写一些测试用例(包括对Controller的测试和对Repository的测试),感受下Spock的使用.