缘起:今天做springboot集成swagger文档的时候。 出现了404问题。
什么集成swagger 这不有手就行? 先加依赖:
<!--swagger 依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
添加 swagger配置类 SwaggerConfig
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2).
apiInfo(apiInfo()).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.zry.qiniu.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("接口文档")
.contact(new Contact("基于树莓派的动态图片捕捉系统", "", "1447051936@qq.com"))
.description("Api文档: 注意!! Date格式: yyyy-MM-dd HH:mm:ss")
.version("1.0")
.build();
}
}
浏览器访问: 啥404? what? 开始排查: 访问 http://localhost:8081/v2/api-docs 看一下swagger接口是否有数据 有数据说明配置没有问题。看来是静态资源被拦截了。 咱们就开放它的静态资源。 下面代码:
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/resources/")
.addResourceLocations("classpath:/static/")
.addResourceLocations("classpath:/pages/")
;
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
super.addResourceHandlers(registry);
}
}
再次访问 还是404? 没有啥变化。。。。 ??????????
再次研究排查: 对比之前的项目,我发现我这次的项目中多了个解决跨域问题的代码:
@Configuration public class WebApiConfig extends WebMvcConfigurationSupport {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH")
.allowCredentials(true).maxAge(3600);
}
把这个configuration注释掉就可以了。
原因:
这个自定义的类继承自WebMvcConfigurationSupport,如果你在IDE中搜索这个类的实现类,可以发现spring boot有一个子类EnableWebMvcConfiguration,并且是自动config的.我们知道,如果一个类用户自己在容器中生成了bean,spring boot就不会帮你自动config。所以,问题的原因是我们把spring boot自定义的那个bean覆盖了。
那么我想既然使用跨域又使用swagger该怎么办呢?只需加上下面的代码。
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/resources/")
.addResourceLocations("classpath:/static/")
.addResourceLocations("classpath:/pages/")
;
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
super.addResourceHandlers(registry);
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH")
.allowCredentials(true).maxAge(3600);
}
}
这样就可以了。
扩展跨域问题解决:
来自:https://cloud.tencent.com/developer/article/1924258
方法1:全局配置
定义配置类,添加@Configuration注解,实现WebMvcConfigurer接口,再重写addCorsMappings方法: 就是上面的代码。
方法2:局部跨域
Controller层在需要跨域的类或者方法上加上@CrossOrigin该注解即可。
@CrossOrigin(origins = "*",maxAge = 3600)
public class UserController {
final UserService userService;
@GetMapping("/getOne/{id}")
public User getOne(@PathVariable("id") Integer id) {
return userService.getById(id);
}
我们也可以设置更小的粒度,在方法上设置跨域:
@Controller
@RequestMapping("/shop")
public class ShopController {
@GetMapping("/")
@ResponseBody
@CrossOrigin(originPatterns = "http://localhost:8080")
public Map<String, Object> findAll() {
return DataSchool.getStudents();
}
}
方法3:定义跨域过滤器
1)编写过滤器
@Component
public class CORSFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Credentials", "true");
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {
response.getWriter().println("Success");
return;
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
2)注册过滤器
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}
|