有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在rest资源spring数据rest中将导出的默认值设置为false

我想使用spring数据rest的RestResource注释。正如您所知,默认情况下,它公开所有CRUD方法。但我只需要findAll方法。一种方法是将所有其他方法的导出值设置为false,如下所示:

@RestResource(path="questions")
public interface QuestionRepository extends CRUDRepository<Question,Long> {

@RestResource(exported = false)
void delete(Long id);

@RestResource(exported = false)
void create(Question q);
....
}

但我不喜欢这样。有没有其他更简单的方法可以避免这种情况


共 (4) 个答案

  1. # 1 楼答案

    您可以通过定义一个实现存储库的中间通用接口来实现这一点,并公开(例如)所有带注释的分页和排序存储库方法

    @RestController(exported = false).
    

    在这个来源的帮助下:https://spring.io/blog/2011/07/27/fine-tuning-spring-data-repositories/,以下是我的解决方案:

    首先,将RepositoryDetectionStrategy设置为ANNOTATED,这样暴露的存储库只有那些标注了@RepositoryRestResource的存储库。这可以通过以下方式实现:

    @Component
    public class SpringRestConfiguration extends 
    RepositoryRestConfigurerAdapter {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
    config.setRepositoryDetectionStrategy(RepositoryDetectionStrategy.RepositoryDetectionStrategies.ANNOTATED);
    }
    }
    

    定义通用Rest存储库。它必须只实现存储库接口,该接口是空的,而不是CRUDEPository或PagingAndSortingRepository,因此您可以准确地控制将公开哪些方法,而公开的方法不取决于您正在使用或将要使用的Spring数据版本

    为了保证不公开,必须用@RestResource(exported=false)对每个方法进行注释。这有点烦人,但可以一次性完成(你只需复制粘贴,我采用Crudepository和PagingAndSorting中定义的所有te方法):

    @RepositoryRestResource
    @NoRepositoryBean
    public interface RestRepositoryMethodExportedFalse<T, ID extends Serializable> 
    extends Repository<T, ID> {
    
    /**
     * Returns all entities sorted by the given options.
     * 
     * @param sort
     * @return all entities sorted by the given options
     */
    @RestResource(exported = false)
    Iterable<T> findAll(Sort sort);
    
    /**
     * Returns a {@link Page} of entities meeting the paging restriction
     * provided in the {@code Pageable} object.
     * 
     * @param pageable
     * @return a page of entities
     */
    @RestResource(exported = false)
    Page<T> findAll(Pageable pageable);
    
    /**
     * Saves a given entity. Use the returned instance for further operations as
     * the save operation might have changed the entity instance completely.
     * 
     * @param entity
     * @return the saved entity
     */
    @RestResource(exported = false)
    <S extends T> S save(S entity);
    
    /**
     * Saves all given entities.
     * 
     * @param entities
     * @return the saved entities
     * @throws IllegalArgumentException
     *             in case the given entity is {@literal null}.
     */
    @RestResource(exported = false)
    <S extends T> Iterable<S> save(Iterable<S> entities);
    
    /**
     * Retrieves an entity by its id.
     * 
     * @param id
     *            must not be {@literal null}.
     * @return the entity with the given id or {@literal null} if none found
     * @throws IllegalArgumentException
     *             if {@code id} is {@literal null}
     */
    @RestResource(exported = false)
    T findOne(ID id);
    
    /**
     * Returns whether an entity with the given id exists.
     * 
     * @param id
     *            must not be {@literal null}.
     * @return true if an entity with the given id exists, {@literal false}
     *         otherwise
     * @throws IllegalArgumentException
     *             if {@code id} is {@literal null}
     */
    @RestResource(exported = false)
    boolean exists(ID id);
    
    /**
     * Returns all instances of the type.
     * 
     * @return all entities
     */
    @RestResource(exported = false)
    Iterable<T> findAll();
    
    /**
     * Returns all instances of the type with the given IDs.
     * 
     * @param ids
     * @return
     */
    @RestResource(exported = false)
    Iterable<T> findAll(Iterable<ID> ids);
    
    /**
     * Returns the number of entities available.
     * 
     * @return the number of entities
     */
    @RestResource(exported = false)
    long count();
    
    /**
     * Deletes the entity with the given id.
     * 
     * @param id
     *            must not be {@literal null}.
     * @throws IllegalArgumentException
     *             in case the given {@code id} is {@literal null}
     */
    @RestResource(exported = false)
    void delete(ID id);
    
    /**
     * Deletes a given entity.
     * 
     * @param entity
     * @throws IllegalArgumentException
     *             in case the given entity is {@literal null}.
     */
    @RestResource(exported = false)
    void delete(T entity);
    
    /**
     * Deletes the given entities.
     * 
     * @param entities
     * @throws IllegalArgumentException
     *             in case the given {@link Iterable} is {@literal null}.
     */
    @RestResource(exported = false)
    void delete(Iterable<? extends T> entities);
    
    /**
     * Deletes all entities managed by the repository.
     */
    @RestResource(exported = false)
    void deleteAll();
    
    }
    

    然后,只需在最终存储库中扩展自定义中间存储库,并使用您的示例唯一地覆盖您想要公开的方法(您可以自动完成,以便快速完成):

    @RestResource(path="questions")
    public interface QuestionRepository extends RestRepositoryMethodExportedFalse<Question,Long>{
    
    /**
     * Here is the only method I expose
     */
    @RestResource(exported = true)
    @Override
    Question findOne(Long id);
    
    }
    

    最好使用一个参数来设置exported to false的默认值,但在这成为可能之前,这里是我找到的唯一安全的方法

  2. # 2 楼答案

    有一个简单而标准的解决方案,我尝试过,发现它在spring boot 2.0.2中工作 如下图所示编写一个配置类,并设置ExposeRepositoryMethodsByDefault(false),这样就完成了:)

    @Component
    public class SpringRestConfiguration extends RepositoryRestConfigurerAdapter {
        @Override
        public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
            config.setRepositoryDetectionStrategy(RepositoryDetectionStrategy.RepositoryDetectionStrategies.ANNOTATED);
            config.setExposeRepositoryMethodsByDefault(false);
        }
    }
    
  3. # 3 楼答案

    为了延续伊姆兰·塔希尔的回答,他帮助了我——谢谢伊姆兰!——通过将ExposeRepositoryMethodsByDefault设置为false,可以覆盖整个存储库

    @Component
    public class SpringRestConfiguration extends RepositoryRestConfigurerAdapter {
        @Override
        public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
          config.setExposeRepositoryMethodsByDefault(false);
        }
    }
    

    现在可以从配置文件中设置检测策略。(在我的例子中是YAML)

    spring:
      data:
        rest:
          base-path: /api/base/path
          detection-strategy: annotated
    

    然后在您的存储库中,只将@RestResource添加到您需要启用的(被覆盖的)方法中:

    @RepositoryRestResource(collectionResourceRel = "someThing", path = "someThing")
    @PreAuthorize("hasRole('ROLE_ADMIN') OR hasRole('ROLE_USER')")
    public interface SomeThingRepository extends PagingAndSortingRepository<SomeThing, Long> {
    
        @Override
        @RestResource
        Page<Some> findAll(Pageable pageable);
    
        @Override
        @RestResource
        Optional<Some> findById(Long aLong);
    
        // All other methods are not exposed
    
    }
    
  4. # 4 楼答案

    您应该为GET /questions请求实现一个自定义控制器,该控制器将只返回findAll方法的结果,例如:

    @RequiredArgsConstructor
    @BasePathAwareController
    @RequestMapping("/questions")
    public class QuestionController {
    
        private final @NonNull QuestionRepository repository;
        private final @NonNull PagedResourcesAssembler<Question> assembler;
        private final @NonNull EntityLinks links;
    
        @GetMapping
        ResponseEntity<?> get(Pageable pageable) {
            return ResponseEntity.ok(assembler.toResource(repository.findAll(pageable),
                    (ResourceAssembler<Question, ResourceSupport>) question -> 
                        new Resource<>(question,
                        links.linkToSingleResource(question).withSelfRel())));
        }
    }
    

    并禁用要导出的问题存储库:

    @RepositoryRestResource(exported = false)
    public interface QuestionRepository extends JpaRepository<Question, Long> {
    }
    

    工作example