Spring Data REST: projection representation of single resource

前端 未结 2 1878
孤街浪徒
孤街浪徒 2020-12-21 16:16

I have a simple UserRepository which exposed using Spring Data REST. Here is the User entity class:

@Document(collecti         


        
2条回答
  •  臣服心动
    2020-12-21 16:38

    I was able to create a ResourceProcessor class which applies projections on any resource as suggested in DATAREST-428. It works the following way: if projection parameter is specified in URL - the specified projection will be applied, if not - projection with name default will be returned, applied first found projection will be applied. Also, I had to add custom ProjectingResource which ignores the links, otherwise there are two _links keys in the returning JSON.

    /**
     * Projecting resource used for {@link ProjectingProcessor}. Does not include empty links in JSON, otherwise two 
     * _links keys are present in returning JSON.
     *
     * @param 
     */
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    class ProjectingResource extends Resource {
    
        ProjectingResource(final T content) {
            super(content);
        }
    }
    
    /**
     * Resource processor for all resources which applies projection for single resource. By default, projections
     * are not
     * applied when working with single resource, e.g. http://127.0.0.1:8080/users/580793f642d54436e921f6ca. See
     * related issue DATAREST-428
     */
    @Component
    public class ProjectingProcessor implements ResourceProcessor> {
    
        private static final String PROJECTION_PARAMETER = "projection";
    
        private final ProjectionFactory projectionFactory;
    
        private final RepositoryRestConfiguration repositoryRestConfiguration;
    
        private final HttpServletRequest request;
    
        public ProjectingProcessor(@Autowired final RepositoryRestConfiguration repositoryRestConfiguration,
                                   @Autowired final ProjectionFactory projectionFactory,
                                   @Autowired final HttpServletRequest request) {
            this.repositoryRestConfiguration = repositoryRestConfiguration;
            this.projectionFactory = projectionFactory;
            this.request = request;
        }
    
        @Override
        public Resource process(final Resource resource) {
            if (AopUtils.isAopProxy(resource.getContent())) {
                return resource;
            }
    
            final Optional> projectionType = findProjectionType(resource.getContent());
            if (projectionType.isPresent()) {
                final Object projection = projectionFactory.createProjection(projectionType.get(), resource
                        .getContent());
                return new ProjectingResource<>(projection);
            }
    
            return resource;
        }
    
        private Optional> findProjectionType(final Object content) {
            final String projectionParameter = request.getParameter(PROJECTION_PARAMETER);
            final Map> projectionsForType = repositoryRestConfiguration.getProjectionConfiguration()
                    .getProjectionsFor(content.getClass());
    
            if (!projectionsForType.isEmpty()) {
                if (!StringUtils.isEmpty(projectionParameter)) {
                    // projection parameter specified
                    final Class projectionClass = projectionsForType.get(projectionParameter);
                    if (projectionClass != null) {
                        return Optional.of(projectionClass);
                    }
                } else if (projectionsForType.containsKey(ProjectionName.DEFAULT)) {
                    // default projection exists
                    return Optional.of(projectionsForType.get(ProjectionName.DEFAULT));
                }
    
                // no projection parameter specified
                return Optional.of(projectionsForType.values().iterator().next());
            }
    
            return Optional.empty();
        }
    }
    
        

    提交回复
    热议问题