如何从spring-data-rest entityController中排除OPTIONS,HEAD和PATCH方法

时间:2016-10-07 12:56:37

标签: spring spring-data-rest springfox

我正在使用spring-data-rest-webmvc:jar:2.5.3.RELEASE来编写REST API并在springfox-data-rest-2.6.0中呈现资源。招摇使得所有方法都存在于RestEntityController中。我使用@RestResource(exported = false)在存储库级别中排除了一些方法。但是,swagger加载了所有其他HTTP方法,如OPTIONS,HEAD和PATCH,我无法从RepositoryRestResource中排除。

如何使用仅包含我的CRUD和搜索方法的干净资源渲染我的招摇?需要在使用spring-data-rest配置或使用springfox配置时支持此功能。

5 个答案:

答案 0 :(得分:5)

在深入研究springfox文档并放弃一些死胡同的想法之后,我想出了两个可能解决您问题的解决方案。根据您的需要涂抹并混合。

提示#1 - 使用RequestHandlerSelectors

进行过滤

告诉springfox你想在swagger-ui中显示哪些方法端点。因此,您可以设置RequestHandlerSelector来扫描您的整个应用程序,一个特定的包或您使用共享注释注释的类和方法。

//Example for the method scan based on springfox's @ApiOperation annotation

@Bean
public Docket api() {    
    return new Docket(DocumentationType.SWAGGER_2)          
      .select()                                       
      .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)).paths(PathSelectors.any())
      .build();
}



// Within your dao or repository class
public interface QueuedMessageDao extends CrudRepository<QueuedMessage, Integer> {
    @ApiOperation(value = "This method finds all messages that are queued with the recipient's email address")
    List<QueuedMessage> findByRecipientEmail(String email); 
}

这会从你的招摇文档中切断很多弹簧数据休息开销。但是,您仍会(令人惊讶地)在您的swagger-ui中看到不需要的HTTP方法,例如技术GET端点的HEADOPTIONS/<entity>/search方法。我说技术,因为这些端点只是为了发现其他端点,它们不会为您提供来自实体的数据。

提示#2 - 使用PathSelectors

进行过滤

如果您想要摆脱swagger中的技术/<entity>/search端点,可以使用正则表达式排除它们,过滤掉所有搜索端点,但保留与您相关的端点。要在实体中仍然拥有搜索的业务端点,您只需要设置一个隐式GET端点。

//Example for the method scan based on springfox's @ApiOperation annotation

@Bean
public Docket api() {    
    return new Docket(DocumentationType.SWAGGER_2)          
      .select()                                       
      .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)).paths(PathSelectors.regex("^(?!(/.*(/search)$)).*$"))
      .build();
}

// Within your dao or repository class
public interface QueuedMessageDao extends CrudRepository<QueuedMessage, Integer> {

    @ApiOperation(value = "this generates a business search endpoint")
    List<QueuedMessage> findById(int id);

    @ApiOperation(value = "This method finds all messages that are queued with the recipient's email address")
    List<QueuedMessage> findByRecipientEmail(String email); 
}

现在你摆脱了搜索端点,但仍然在你的招摇文档中进行业务搜索。 希望这有帮助!

答案 1 :(得分:2)

我遇到了和你一样的问题,我只想通过Swagger UI向我的客户展示CRUD操作。在深入研究Springfox文档之后,我创建了自己的谓词来过滤端点,仅用于CRUD操作,检查所请求的方法。

@Bean
public Docket api() { 
    return new Docket(DocumentationType.SWAGGER_2)  
        .select()                                  
            .apis(customRequestHandlers())
            .build();
}

private Predicate<RequestHandler> customRequestHandlers() {     
    return new Predicate<RequestHandler>() {
        @Override
        public boolean apply(RequestHandler input) {
            Set<RequestMethod> methods = input.supportedMethods();
            return methods.contains(RequestMethod.GET)  
                || methods.contains(RequestMethod.POST)
                || methods.contains(RequestMethod.PUT)
                || methods.contains(RequestMethod.DELETE);
        }
    };
}

答案 2 :(得分:1)

创建自定义拦截器:

public class MyInterceptor extends HandlerInterceptorAdapter{    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            //let's disable OPTIONS and HEAD
            if (request.getMethod().equalsIgnoreCase("OPTIONS") || request.getMethod().equalsIgnoreCase("HEAD")) {            
                response.sendError(HttpServletResponse.SC_FORBIDDEN, "Unauthorized Request");
                return false;
            } else {
                return true;
            }
        }
    }

然后将其添加到配置

@Configuration
@EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter {
     @Override
        public void addInterceptors(InterceptorRegistry registry){
            registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
        }
} 

答案 3 :(得分:0)

使用SpringPox排除特定的HttpMethods非常简单,它的ApiSelectorBuilder接受Guavas Predicates。

此代码段将排除api-docs和swagger-ui.html中OPTIONS,HEAD或PATCH的所有方法。

@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(Predicates.not(requestHandler -> {
                // exclude all methods being OPTIONS, HEAD or PATCH
                final Set<RequestMethod> methods = requestHandler.getRequestMapping().getMethodsCondition().getMethods();
                return !Collections.disjoint(methods, Arrays.asList(RequestMethod.OPTIONS, RequestMethod.HEAD, RequestMethod.PATCH));
            }))
            .build();
}

这可以轻松扩展为另外排除常见/错误控制器。

@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(Predicates
                    .and(
                            // exclude /errors
                            Predicates.not(requestHandler -> requestHandler.getRequestMapping().getPatternsCondition().getPatterns().contains("/error")),
                            // exclude all methods being OPTIONS, HEAD or PATCH
                            Predicates.not(requestHandler -> !Collections.disjoint(requestHandler.getRequestMapping().getMethodsCondition().getMethods(),
                                    Arrays.asList(RequestMethod.OPTIONS, RequestMethod.HEAD, RequestMethod.PATCH)))
                    )
            )
            .build();
}

答案 4 :(得分:0)

对于spring数据,我们可以在此处过滤http方法:

    private Predicate<RequestHandler> httpRequestHandler() {

    return p -> p.supportedMethods().contains(RequestMethod.GET)
            || p.supportedMethods().contains(RequestMethod.POST);
   }


    @Bean
    public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
            .groupName("test-api")
            .apiInfo(apiInfo())
            .select()
            .apis(httpRequestHandler())
            .paths(PathSelectors.any()).build()
            .securitySchemes(Arrays.asList(securityScheme()))
            .securityContexts(Arrays.asList(securityContext()));
    }