【问题标题】:How to set default value of exported as false in rest resource spring data rest如何在休息资源弹簧数据休息中将导出的默认值设置为假
【发布时间】:2017-11-01 21:01:26
【问题描述】:

我想使用 Spring Data 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);
....
}

但我不喜欢这样。还有其他更简单的方法可以避免这种冶金吗?

【问题讨论】:

    标签: java spring rest spring-data


    【解决方案1】:

    您应该为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())));
        }
    }
    

    并禁用要导出的 QuestionRepository:

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

    工作example

    【讨论】:

      【解决方案2】:

      您可以通过定义一个实现 Repository 的中间通用接口来实现这一点,并公开例如所有使用

      注释的 PagingAndSortingRepository 方法
      @RestController(exported = false).
      

      借助该来源:https://spring.io/blog/2011/07/27/fine-tuning-spring-data-repositories/,这是我的解决方案:

      首先,将 RepositoryDe​​tectionStrategy 设置为 ANNOTATED,以便公开的唯一存储库是那些带注释的 @RepositoryRestResource。这可以通过:

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

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

      要保证非公开,您必须使用 @RestResource(exported=false) 注释每个方法。这有点烦人,但一劳永逸(你可以复制粘贴,我采用 CrudRepository 和 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);
      
      }
      

      最好使用将默认值设置为 false 的参数,但在此之前,这是我找到的唯一安全方法。

      【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        扩展 Imran Tahir 的回答,这对我有帮助 - 谢谢 Imran! - 您可以通过将 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
        
        }
        

        【讨论】:

          猜你喜欢
          • 2018-12-16
          • 1970-01-01
          • 2018-07-13
          • 1970-01-01
          • 1970-01-01
          • 2014-02-28
          • 2014-02-02
          • 2015-04-22
          相关资源
          最近更新 更多