[英]Spring Boot - Swagger Documentation doesn't work
我有一个 REST API 项目构建和 Spring 引导,我想记录我所有的端点。 我已经实施了 swagger 来完成它并且成功了,但是最近我的项目不再运行了,配置与创建项目时的配置相同并且 Swagger 是有效的。
尝试运行项目时出现此错误:
WARN 17868 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
....
ERROR 17868 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
我究竟做错了什么?
这是我的项目配置:
主要的
package com.red.api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
@PropertySource(value = "classpath:application.properties")
@PropertySource(value = "classpath:propiedades.properties")
public class BackRedApplication {
public static void main(String[] args) {
SpringApplication.run(BackRedApplication.class, args);
}
@Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
密码.xml
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.0-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.red.api</groupId>
<artifactId>RED</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>RED</name>
<description>RED</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20200518</version>
</dependency>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.8.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>io</artifactId>
<version>7.1.9</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>kernel</artifactId>
<version>7.1.9</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>7.1.9</version>
</dependency>
</dependencies>
...
配置Class
package com.red.api.configuracion;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Configuracion {
@Bean
public RestTemplate rest() {
return new RestTemplate();
}
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
@Bean
public Docket redApi() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.basePackage("com.co.dejsoftware.red.ws"))
.paths(PathSelectors.any()).build();
}
}
Controller
package com.red.api.ws;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.red.api.interfaces.InterfaceSeguridad;
@RestController
@CrossOrigin
@RequestMapping("/seguridad")
public class WsSeguridad {
private Logger logger = LogManager.getLogger(WsSeguridad.class);
@Autowired
private InterfaceSeguridad servicioSeguridad;
@PostMapping(path="/getToken", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> getToken(@RequestHeader(name = "user") String usuario,
@RequestHeader(name = "pwd") String contrasena) {
try {
return ResponseEntity.ok(servicioSeguridad.getToken(usuario, contrasena));
} catch (Exception e) {
logger.error(e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}
界面
package com.red.api.interfaces;
import org.springframework.http.ResponseEntity;
public interface InterfaceSeguridad {
public ResponseEntity<Object> getToken(String usuario, String contrasena);
}
执行
package com.red.api.implementacion;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import com.red.api.interfaces.InterfaceSeguridad;
@Service
public class ServicioSeguridad implements InterfaceSeguridad {
private Logger logger = LogManager.getLogger(ServicioSeguridad.class);
public ResponseEntity<Object> getToken(String usuario, String contrasena) {
try {
System.out.println("usuario... " + usuario);
System.out.println("contrasena... " + contrasena);
JSONObject item = new JSONObject();
item.put("description", "Success...");
item.put("usuario", usuario);
item.put("contrasena", contrasena);
String jsonResponse = new JSONObject().put("exito", item).toString();
return ResponseEntity.ok(jsonResponse);
}catch (Exception e) {
logger.error(e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}
问题似乎是 Spring Boot 从 Ant Path Matching 切换到使用PathPatternParser
,请参见
Springfox 插件有一段时间没有积极维护,因此无法处理与PathPatternParser
请求映射。 至少在 3.0.0 版本中。
如果坚持在Spring Boot >= 2.6的情况下继续使用Springfox,可以尝试通过设置强制使用Ant Path Matching
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
强制执行器上的蚂蚁路径匹配是一个单独的问题。 它通过注入在WebMvcEndpointHandlerMapping
更改之前自动配置的WebMvcEndpointManagementContextConfiguration
:
@Bean
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(
WebEndpointsSupplier webEndpointsSupplier,
ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
WebEndpointProperties webEndpointProperties, Environment environment) {
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
allEndpoints.addAll(webEndpoints);
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
String basePath = webEndpointProperties.getBasePath();
EndpointMapping endpointMapping = new EndpointMapping(basePath);
boolean shouldRegisterLinksMapping = shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath),
shouldRegisterLinksMapping);
}
private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment,
String basePath) {
return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath)
|| ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
}
可能有一种更聪明的方法,首先将执行器排除在 Springfox 分析之外。
你的里程可能会有所不同。 切换到 springdoc 可能是更有价值的方法。
我有一个类似的问题,我试图升级到 Spring 2.6.6。
我建议使用 openapi generator >= 5.4.0 因为它删除了 springfox 作为默认文档提供者
https://github.com/OpenAPITools/openapi-generator/pull/11181修复https://github.com/OpenAPITools/openapi-generator/issues/10409
springdoc 是默认的
有关 spring 引导生成器选项的更多信息,请参阅https://openapi-generator.tech/docs/generators/spring/并搜索 documentationProvider
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.