覆盖由SpringDataREST自动创建的存储库端点
我有一个Spring项目,它依赖于覆盖由SpringDataREST自动创建的存储库端点,spring,spring-data-rest,Spring,Spring Data Rest,我有一个Spring项目,它依赖于Spring数据rest。我的项目中有相当多的存储库,它们spring-data-rest自动为创建restapi端点。到目前为止,这很适合我的需要。现在,我需要更改我所有存储库的一个端点的默认功能,特别是/BASE\u PATH/REPOSITORY。此路径以my db的所有记录的分页列表进行响应 现在我想为我所有的存储库重新实现这个端点。这就是我遇到的路障。我试过了 @RestController public class MyTableResource {
Spring数据rest
。我的项目中有相当多的存储库,它们spring-data-rest
自动为创建restapi端点。到目前为止,这很适合我的需要。现在,我需要更改我所有存储库的一个端点的默认功能,特别是/BASE\u PATH/REPOSITORY
。此路径以my db的所有记录的分页列表进行响应
现在我想为我所有的存储库重新实现这个端点。这就是我遇到的路障。我试过了
@RestController
public class MyTableResource {
private MyTableService myTableService;
@Autowired
public MyTableResource(MyTableService myTableService) {
this.myTableService = myTableService;
}
@GetMapping(value = "/api/v1/myTables", produces = MediaTypes.HAL_JSON_VALUE)
public ResponseEntity getMyTables(@QuerydslPredicate(root = MyTable.class) Predicate predicate) throws NoSuchMethodException {
// My custom implementation
}
}
现在这有点可行,但问题是我需要为所有存储库编写几乎相同的代码。我尝试了@GetMapping(value=“/api/v1/{repository}”,products=MediaTypes.HAL_JSON_value)
,但这也与我单独实现的/api/v1/notarepository
相匹配
此外,即使我使用@GetMapping(value=“/api/v1/{repository}”,products=MediaTypes.HAL_JSON_value)
我也希望使用{repository}
路径变量获得存储库对象(MyTable
)的句柄,在本例中,该变量将是myTables
简而言之,我想为我的所有存储库编写一个自定义控制器,因为每个存储库的逻辑都是相同的,同时确保根据名为的路径调用正确的存储库,同时确保我引入的任何路径变量都不会隐藏我编写的其他控制器类
我尝试了更多的东西
我试图从我的实体列表中自动获取分页的HATEOAS资源对象。为此,我发现我可以使用PagedResourceAssembler
@RestController
public class MyTableResource {
private MyTableService myTableService;
@Autowired
public MyTableResource(MyTableService myTableService) {
this.myTableService = myTableService;
}
@GetMapping(value = "/api/v1/myTables", produces = MediaTypes.HAL_JSON_VALUE)
public ResponseEntity getMyTables(@QuerydslPredicate(root = MyTable.class) Predicate predicate, PagedResourcesAssembler<Object> pagedResourcesAssembler) throws NoSuchMethodException {
// My custom implementation
return ResponseEntity.ok(pagedResourcesAssembler.toResource(myTableList);
}
}
这与中的报告不一样
如果我将@RestController
替换为RepositoryRestController
,但Predicate
会停止工作,如中所述
因此,我尝试使用@querydsldpredicate-RootResourceInformation-resourceInformation
而不是@querydspredicate(root=MyTable.class)谓词。这也不起作用,因为我的控制器端点中没有/{repository}
然后我尝试设置@GetMapping(value=“/{repository}”products=MediaTypes.HAL\u JSON\u value)
。这引发了映射冲突错误
因此,我完全无法确定下一步要做什么。您可以通过扩展RepositoryRestMvcConfiguration
来扩展Spring Data Rest提供的默认行为
RepositoryRestMvcConfiguration
有一个DelegatingHandlerMapping
bean,其中包含HandlerMapping
的列表。Spring迭代这个列表并尝试为请求找到一个处理程序。这个列表的顺序很重要。第一个先被抓起来执行死刑。因此,如果我们在已有的处理程序之前添加一个新的处理程序,那么将调用我们的HandlerMapping
您可以使用任何逻辑来查找请求的处理程序。在您的情况下,如果path变量是存储库名称,则会出现这种情况
以下代码添加了一个新的处理程序:
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
import org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@Configuration
public class CustomRestMvcConfiguration extends RepositoryRestMvcConfiguration {
public CustomRestMvcConfiguration(ApplicationContext context,
ObjectFactory<ConversionService> conversionService) {
super(context, conversionService);
}
@Override public DelegatingHandlerMapping restHandlerMapping() {
DelegatingHandlerMapping delegatingHandlerMapping = super.restHandlerMapping();
List<HandlerMapping> delegates = delegatingHandlerMapping.getDelegates();
delegates.add(0, new HandlerMapping() {
@Override public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//Your custom logic to decide if you should handle the request
//If you don't want to handle the request return null
return null;
}
});
return new DelegatingHandlerMapping(delegates);
}
}
import org.springframework.beans.factory.ObjectFactory;
导入org.springframework.context.ApplicationContext;
导入org.springframework.context.annotation.Configuration;
导入org.springframework.core.convert.ConversionService;
导入org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
导入org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping;
导入org.springframework.web.servlet.HandlerExecutionChain;
导入org.springframework.web.servlet.HandlerMapping;
导入javax.servlet.http.HttpServletRequest;
导入java.util.List;
@配置
公共类CustomRestMvcConfiguration扩展了RepositoryRestMvcConfiguration{
公共CustomRestMVC配置(ApplicationContext上下文,
ObjectFactory转换服务){
超级(上下文、转换服务);
}
@重写公共DelegatingHandlerMapping restHandlerMapping(){
DelegatingHandlerMapping DelegatingHandlerMapping=super.restHandlerMapping();
List delegates=delegatingHandlerMapping.getDelegates();
添加(0,新HandlerMapping(){
@Override public HandlerExecutionChain getHandler(HttpServletRequest请求)引发异常{
//您可以使用自定义逻辑来决定是否应处理请求
//如果不想处理请求,则返回null
返回null;
}
});
返回新的DelegatingHandlerMapping(委托);
}
}
希望这有帮助
注意:RepositoryRestHandlerMapping
是默认值,您可以在编写逻辑时检查它。这可能会有帮助
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
import org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@Configuration
public class CustomRestMvcConfiguration extends RepositoryRestMvcConfiguration {
public CustomRestMvcConfiguration(ApplicationContext context,
ObjectFactory<ConversionService> conversionService) {
super(context, conversionService);
}
@Override public DelegatingHandlerMapping restHandlerMapping() {
DelegatingHandlerMapping delegatingHandlerMapping = super.restHandlerMapping();
List<HandlerMapping> delegates = delegatingHandlerMapping.getDelegates();
delegates.add(0, new HandlerMapping() {
@Override public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//Your custom logic to decide if you should handle the request
//If you don't want to handle the request return null
return null;
}
});
return new DelegatingHandlerMapping(delegates);
}
}