域/存儲庫彈簧數據休息覆蓋庫(控制器VS AOP)
Project {
User owner;
}
//Querydsl repositories
@RepositoryRestResource
public interface ProjectRepository extends PagingAndSortingRepository<Project, Long>, QueryDslPredicateExecutor<Project>, QuerydslBinderCustomizer<QProject> {
default void customize(QuerydslBindings bindings, QProject project) {
(...)
}
}
Requeriment:根據經認證的用戶上下文 濾波數據:
- 如果用戶是
ROLE_PUBLIC
顯示項目根據predicate
和用戶是owner
。 - 如果用戶是
ROLE_ADMIN
根據predicate
過濾顯示項目。
我試圖解決throught幾種選擇:
選項1:覆蓋@RepositoryRestController
爲Spring DATA REST醫生說:
@RepositoryRestController
public class ProjectController {
@RequestMapping(value = "/projects", method = RequestMethod.GET)
@ResponseBody
public PagedResources<?> search(
@QuerydslPredicate(root=Project.class ,bindings =ProjectRepository.class) Predicate predicate,
@PageableDefault Pageable pageable, //
@AuthenticationPrincipal Principal principal) {
(...) // Update predicate wit user context
projectRepository.findAll(predicate,pageagle);
(...)
}
}
因爲@QueryDslPredicat此拋出異常不是RepositoryRestHandlerAdapter名單上( DATAREST-838):
Failed to instantiate [com.querydsl.core.types.Predicate]: Specified class is an interface
列表中最類似的argumentResolver是QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver
,但我不知道它是否對這個問題有用。
選項2:這個問題是一個典型的交叉問題,所以我嘗試應用AOP。定義建議和更新ARGS(謂語):
@Around("this(com.xxx.yyy.repository.ProjectRepository)")
public void filterProjectsByUser(final ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
// .. Find args Predicate, update it adding user profile expression and procceed.
pjp.proceed(args);
}
結果是不一樣的默認存儲庫的方法,而不是原來的JSON對象(_embedded,頁面,_links)的反應是:
{
"_links" : {
"profile" : {
"href" : "http://localhost:8087/api/profile/projects"
}
}
}
選項3 使用@RestController
:
@RestController
public class ProjectController {
@RequestMapping(value = "/projects/search", method = RequestMethod.GET)
@ResponseBody
public PagedResources<?> search(
@QuerydslPredicate(root=Project.class ,bindings =ProjectRepository.class) Predicate predicate,
@PageableDefault Pageable pageable, //
@AuthenticationPrincipal Principal principal) {
(...) // Update predicate wit user context
projectRepository.findAll(predicate,pageagle);
(...)
}
}
使用相同的路徑@RequestMapping("/projects",...)
也覆蓋其他端點(PUT,POST,...),這是不期望的。這迫使定義另一個端點("projects/search")
。 我認爲這個解決方法不夠優雅,需要新聞端點。我相信Spring Data REST存在更好的選擇。
問題:
- 有關如何解決這個requeriment任何建議嗎?
- 如何將AOP應用於Spring Data REST以解決橫切需求?
- 爲什麼@QuerydslPredicate在參數解析器?
Spring Data REST version 2.5。6
雖然已經解決,但我想獲得反饋和建議。我希望QueryDSLPredicate註解將被修復,文檔將會被更多關於這個問題的示例所改進。