代码之家  ›  专栏  ›  技术社区  ›  Ayoub k

如何将弹簧座投影与自定义控制器一起使用

  •  1
  • Ayoub k  · 技术社区  · 6 年前

    我有下面的投影,它返回标记的名称:

    @Projection(types = NewsTag.class, name = "newsTag")
    public interface NewsTagProjection {
    
        @Value("#{target.tag.name}")
        String getName();
    }
    

    我在以下负责newstag模型的存储库中使用它:

    @RepositoryRestResource(excerptProjection = NewsTagProjection.class)
    public interface NewsTagRepository extends JpaRepository<NewsTag, Integer> {
    }
    

    因此,当我调用具有新闻标签列表的新闻库时:

    @RepositoryRestResource
    public interface NewsRepository extends JpaRepository<News, Integer> {
    }
    

    一切正常,它只返回带有NAE的标签列表。
    但是,如果我想使用具有相同端点的自定义控制器(比如说,我这样做是为了处理错误),它只返回没有标签列表的新闻,就像投影不存在一样。

    这里是控制器:

    @RepositoryRestController
    @RequestMapping("news")
    public class NewsController {
    
        private NewsService newsService;
        private PagedResourcesAssembler<News> pagedAssembler;
        private NewsResourceAssembler newsResourceAssembler;
    
        @Autowired
        public void setNewsService(NewsService newsService) {
            this.newsService = newsService;
        }
    
        @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
        @Autowired
        public void setPagedAssembler(PagedResourcesAssembler<News> pagedAssembler) {
            this.pagedAssembler = pagedAssembler;
        }
    
        @Autowired
        public void setNewsResourceAssembler(NewsResourceAssembler newsResourceAssembler) {
            this.newsResourceAssembler = newsResourceAssembler;
        }
    
        // Return all news with pagination
        @GetMapping
        public ResponseEntity<?> getAllNews(Pageable pageable) {
            Page<News> newsPage = this.newsService.getAllNews(pageable);
            return ResponseEntity.ok(this.pagedAssembler.toResource(newsPage, this.newsResourceAssembler));
        }
    }
    

    编辑 新闻资源汇编程序:

    @Service
    public class NewsResourceAssembler implements ResourceAssembler<News, Resource<News>> {
    
        private EntityLinks entityLinks;
    
        @Autowired
        public void setEntityLinks(EntityLinks entityLinks) {
            this.entityLinks = entityLinks;
        }
    
        @Override
        public Resource<News> toResource(News news) {
            Link self = entityLinks.linkFor(News.class).slash(news.getId()).withSelfRel();
            Link newsTags = entityLinks.linkFor(News.class).slash(news.getId()).slash("newsTags").withRel("newsTags");
            Link newsComments = entityLinks.linkFor(News.class).slash(news.getId()).slash("newsComments").withRel("newsComments");
            return new Resource<>(news, self, newsTags, newsComments);
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   drowny    6 年前

    如果要添加新闻的所有字段,可以操作的返回对象 责任 。所以我改了这个代码,你能应用到你的代码吗?

    NewsResourceAssembler.class 应该是这样的;

    @Service
    public class NewsResourceAssembler implements ResourceAssembler<News, Resource<NewsResource>> {
    
        private EntityLinks entityLinks;
    
        @Autowired
        public void setEntityLinks(EntityLinks entityLinks) {
            this.entityLinks = entityLinks;
        }
    
        @Override
        public Resource<NewsResource> toResource(News news) {
    
            Link self = entityLinks.linkFor(News.class).slash(news.getId()).withSelfRel();
            Link newsTags = entityLinks.linkFor(News.class).slash(news.getId()).slash("newsTags").withRel("newsTags");
            Link newsComments = entityLinks.linkFor(News.class).slash(news.getId()).slash("newsComments").withRel("newsComments");
    
            final NewsResource newsResource = new NewsResource();
            //set any fields to which do you wants to send client
            //newsResource.setExampleFields();
            //newsResource.setNewsTagList(news.getNewsTag()); //example code. Change according to your models
    
            return new Resource(newsResource, self, newsTags, newsComments);
        }
    }
    

    现在你需要 NewsResource.class ,所以应该是这样的;

    @JsonIgnoreProperties(ignoreUnknown = true)
    public class NewsResource extends ResourceSupport {
    
        //private fields of which do you wants
        //dont forget list of newstag field
        //ex : private List<NewsTagFields> newsTag = new ArrayList<>();
    
        //Also should write getter and setter methods
    }
    

    附言:别忘了注释行的规则。根据这一变化,您的客户应该分析对客户的传入响应。因为响应时,应该在主对象上更改一些链接rel。但是你的定制参数没有改变。

    编辑: 如果在你的 新闻资源.class -->字段 newsTag 应该是这样的( 请不要忘记设置资源汇编程序类中的所有标记! ;

    private List<NewsTagFields> newsTag = new ArrayList<>();
    

    现在您需要newstagfields.class。也可以使用这个类;

    public class NewsTagFields {
    
        private final String id;
        private final String name;
    
        public NewsTagFields(String id, String name) {
            this.id = id;
            this.name = name;
        }
    
        public String getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    }
    

    最后将此代码添加到 ResourceAssembler 添加新的NewstagFields列表; ( 此代码提供获取所有 新闻标签 并转换为列表 新闻标签字段 完全地。并添加到 新闻资源 发送到客户端 )

    final List<NewsTagFields> allNewsTag =
                    news.getNewsTag().stream()
                            .map(newsTag -> new NewsTagFields(newsTag.getId(), newsTag.getName()))
                            .collect(Collectors.toList());
            newsResource.setNewsTagList(allNewsTag);