2015-11-01 105 views
0

調查Springfox和Swagger UI,但我面臨一個問題。我正在使用Spring Boot REST示例項目作爲我的PoC的基礎。我正在運行JDK 8並且該項目利用了Gradle。從Swagger UI測試API時出現Springfox 404錯誤

首先,這裏是項目的文件內容:

的build.gradle

buildscript { 
    repositories { 
     mavenCentral() 
    } 
    dependencies { 
     classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.7.RELEASE") 
    } 
} 

apply plugin: 'java' 
apply plugin: 'eclipse' 
apply plugin: 'idea' 
apply plugin: 'spring-boot' 

jar { 
    baseName = 'gs-rest-service' 
    version = '0.1.0' 
} 

repositories { 
    mavenCentral() 
    jcenter() 
} 

sourceCompatibility = 1.8 
targetCompatibility = 1.8 

dependencies { 
    compile("org.springframework.boot:spring-boot-starter-web") 
    compile("io.springfox:springfox-swagger2:2.2.2") 
    compile("io.springfox:springfox-swagger-ui:2.2.2") 
    testCompile("junit:junit") 
} 

task wrapper(type: Wrapper) { 
    gradleVersion = '2.3' 
} 

GreetingController.java

package hello; 

import java.util.concurrent.atomic.AtomicLong; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestParam; 
import org.springframework.web.bind.annotation.RestController; 

@RestController 
public class GreetingController { 

    private static final String template = "Hello, %s!"; 
    private final AtomicLong counter = new AtomicLong(); 

    @RequestMapping("/greeting") 
    public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) { 
     return new Greeting(counter.incrementAndGet(), 
          String.format(template, name)); 
    } 
} 

Greeting.java

package hello; 

public class Greeting { 

    private final long id; 
    private final String content; 

    public Greeting(long id, String content) { 
     this.id = id; 
     this.content = content; 
    } 

    public long getId() { 
     return id; 
    } 

    public String getContent() { 
     return content; 
    } 
} 

Application.java

package hello; 

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

import java.time.LocalDate; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.context.annotation.Bean; 
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.schema.ModelRef; 
import springfox.documentation.schema.WildcardType; 
import springfox.documentation.spi.DocumentationType; 
import springfox.documentation.spring.web.plugins.Docket; 
import springfox.documentation.swagger2.annotations.EnableSwagger2; 

import com.fasterxml.classmate.TypeResolver; 

@SpringBootApplication 
@EnableSwagger2 
public class Application { 

    public static void main(String[] args) { 
     SpringApplication.run(Application.class, args); 
    } 

    @Autowired 
    private TypeResolver typeResolver; 

    @Bean 
    public Docket greetingApi() { 
     return new Docket(DocumentationType.SPRING_WEB) 
      .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())) 
      .enableUrlTemplating(true); 
    } 

} 

這裏是我所面臨的問題。當我構建並運行應用程序時,我可以成功導航到Swagger UI頁面(http://localhost:8080/swagger-ui.html)。當我擴展問候控制器時,我看到了不同的方法並展開「get/greeting {?name}」。該獲取部分有以下內容:

Response Class (Status 200) 

Model 

{ 
    "content": "string", 
    "id": 0 
} 

Response Content Type: */* 

Parameters 
parameter = name, value = World, parameter type = query, data type = string 

當我點擊了「實戰」按鈕,我看到以下內容:

curl = curl -X GET --header "Accept: */*" "http://localhost:8080/greeting{?name}?name=World" 

request url = http://localhost:8080/greeting{?name}?name=World 

repsonse body = { 
    "timestamp": 1446418006199, 
    "status": 404, 
    "error": "Not Found", 
    "message": "No message available", 
    "path": "/greeting%7B" 
} 

response code = 404 

response headers = { 
    "server": "Apache-Coyote/1.1", 
    "content-type": "application/json;charset=UTF-8", 
    "transfer-encoding": "chunked", 
    "date": "Sun, 01 Nov 2015 22:46:46 GMT" 
} 

乍一看,它看起來像某種原因Springfox/Swagger無法正確替換{?name}的佔位符。我的問題是,如何將其配置爲這樣做,如果這實際上是問題,那麼我可以成功地從Swagger UI頁面測試該服務?

+0

是的,就像你在響應正文中看到的那樣,它試圖打開url'/ greeting%7B','%7B'是''''之前''name'}。嘗試在創建Docket時使用'enableUrlTemplating(false)'(您正在使用RequestParam而非PathVariable) –

回答

5

在您的Application類中,將enableUrlTemplating更改爲false將解決您的問題。

@Bean 
public Docket greetingApi() { 
    return new Docket(DocumentationType.SPRING_WEB) 
     //... 
     .enableUrlTemplating(false); 
} 

只是在該國旗上的一點點背景。該標誌將支持RFC 6570,沒有這些操作僅通過查詢字符串參數will not show up correctly per spec來區分。在swagger規範的下一次迭代中,有計劃來解決這個問題。這就是enableUrlTemplating被標記爲incubating feature的原因。