简体   繁体   English

Spring Hateoas xml序列化有关使用ResourceAssemblerSupport构建的资源列表

[英]Spring hateoas xml serialization for list of resources built with ResourceAssemblerSupport

I am trying to support XML responses for my Spring HATEOAS based application. 我正在尝试为基于Spring HATEOAS的应用程序支持XML响应。 JSON responses work fine as well as XML for a single resource. JSON响应以及XML对于单个资源都可以正常工作。 The problem starts with the list of the resources. 问题始于资源列表。 Spring MVC controller cannot serialize the list built with help of ResourceAssemblerSupport derived class. Spring MVC控制器无法序列化借助ResourceAssemblerSupport派生类构建的列表。 The controller throws "org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation" for the curl command 控制器为curl命令抛出“ org.springframework.web.HttpMediaTypeNotAcceptableException:找不到可接受的表示形式”

curl -k -i -H "Accept:application/xml" -H "Media-Type:application/xml" -X GET http://127.0.0.1:8080/admin/roles*

My HATEOAS resource is a wrapper around entity class: 我的HATEOAS资源是实体类的包装:

@XmlRootElement
@XmlSeeAlso(RoleModel.class)
public class RoleResource  extends ResourceSupport {
    public RoleModel role;

}

The controller is simple: 控制器很简单:

@RequestMapping(method = RequestMethod.GET)
   public @ResponseBody HttpEntity<List<RoleResource>> getAllRoles() 
        throws ObjectAccessException, ObjectNotFoundException {
    List<RoleModel> resp = rolesManagement.getRoles();

    return new ResponseEntity<List<RoleResource>>(roleResourceAssembler.toResources(resp),
            HttpStatus.OK);
}

Resource assembler class: 资源汇编器类:

@Configuration
public class RoleResourceAssembler extends ResourceAssemblerSupport<RoleModel, RoleResource> {

public RoleResourceAssembler() {
    super(RolesRestController.class, RoleResource.class);
}

@Bean 
public RoleResourceAssembler roleResourceAssembler(){
   return new RoleResourceAssembler();
}

@Override
public RoleResource toResource(RoleModel role) {
    RoleResource res = instantiateResource(role); 
    res.role = role;
    try {
        res.add(linkTo(methodOn(RolesRestController.class).getRole(role.getRoleId())).withSelfRel());
    } catch (ObjectAccessException | ObjectNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return res;
}

}

When I avoid ResourceAssemblerSupport and build my resources manually like this: 当我避免使用ResourceAssemblerSupport并手动构建资源时,如下所示:

@XmlRootElement
@XmlSeeAlso(RoleModel.class)
public class RolesList {
    private List<Resource<RoleModel>> roles;

...
}
@RequestMapping(method = RequestMethod.GET)
public @ResponseBody HttpEntity<RolesList> getAllRoles() 
        throws ObjectAccessException, ObjectNotFoundException {
    List<RoleModel> resp = rolesManagement.getRoles();

    List<Resource<RoleModel>> roles =new ArrayList<>(); 
    for (RoleModel model: resp) {
        Resource<RoleModel> res =  new Resource<RoleModel>(model);
        res.add(linkTo(methodOn(RolesRestController.class).getRole(model.getRoleId())).withSelfRel());
        roles.add(res);
    }
    RolesList list = new RolesList();
    list.setRoles(roles);

    return new ResponseEntity<RolesList>(list,
            HttpStatus.OK);
}

XML serialization works. XML序列化工作。 I guess I could avoid using resource assembler and build my resources manually, but that makes the code not as clean and modular. 我想我可以避免使用资源汇编器并手动构建资源,但这会使代码不那么干净和模块化。 I wonder if it is still possible to use ResourceAssemblerSupport as resource builder and return the list of resources as XML 我想知道是否仍然可以使用ResourceAssemblerSupport作为资源生成器并将资源列表返回为XML

A resource assembler is for converting one pojo/entity/whatever to 1 hateoas resource. 资源组装器用于将一个pojo /实体/任何对象转换为1个hateoas资源。 You are trying to convert a list to a list. 您正在尝试将列表转换为列表。

If you assembler was 如果您的汇编程序是

public class RoleResourceAssembler extends ResourceAssemblerSupport<List<RoleModel>, RolesResource> {

and RolesResource was something that you wanted...it should work. 而RolesResource是您想要的东西……应该可以工作。

However i would suggest you look at using the PagedResourceAssembler which takes a page of "things" and uses an assembler to create a page of resources. 但是我建议您使用PagedResourceAssembler,它使用“事物”页面并使用汇编器来创建资源页面。 The page can be the full collection or just a page in the collection. 该页面可以是完整集合,也可以只是集合中的页面。 Here's a simple one for categories: 这是一个简单的类别:

public HttpEntity<PagedResources<CategoryResource>> categories(
    PagedResourcesAssembler<Category> pageAssembler,
    @PageableDefault(size = 50, page = 0) Pageable pageable
){

    Page<Category> shopByCategories = categoryService.findCategories(pageable);        

    PagedResources<CategoryResource> r = pageAssembler.toResource(shopByCategories,
            this.categoryAssembler);

    return new ResponseEntity<PagedResources<CategoryResource>>(r, HttpStatus.OK);
}

But..i've had some problems with jackson marshaling the PagedResources as XML...works fine for JSON. 但是..我在杰克逊封送PagedResources为XML时遇到了一些问题...对于JSON来说效果很好。

It seems that with ResourceAssemblerSupport it is impossible to marshal list of HATEOAS resources to XML. 似乎,有了ResourceAssemblerSupport,就不可能将HATEOAS资源列表整理为XML。 The reason is because the list of resources returned by toResources() method of the class extending ResourceAssemblerSupport has no @XmlRootElement and JAXB fails to marshal it. 原因是因为扩展ResourceAssemblerSupport的类的toResources()方法返回的资源列表没有@XmlRootElement,并且JAXB无法将其编组。 I had to create classes like 我不得不创建像

 @XmlRootElement
    public class Roles {    
    private List<RoleResource> roleResource;
    ....
}

@XmlRootElement
public class RoleResource  extends ResourceSupport {
    private RoleModel role;
    ...
}

and manually build my resource list. 并手动建立我的资源列表。 The same problem occurred when I tried to use to use Spring HATEOAS resource wrapper like 当我尝试使用像这样的Spring HATEOAS资源包装器时,发生了相同的问题

Resource<RoleModel> resource = new Resource<>();

Since Spring's Resource class is not annotated with @XmlRootElement REST controller is unable to marshal it to XML 由于Spring的Resource类未使用@XmlRootElement注释,因此REST控制器无法将其编组为XML

If your only requirement is to generate links with org.springframework.hateoas.Link and marshall as XML, the following may help. 如果您唯一的要求是使用org.springframework.hateoas.Link生成链接并将其编组为XML,则以下内容可能会有所帮助。

Add a Link item to your model class. 将链接项添加到模型类。

@XmlRootElement(name="Role")
public class Roles
{
   Link link;
   <your Roles content>
   ...
}

Wrap the base class in a list in order to provide a base tag which supports XML marshalling. 将基类包装在列表中,以提供支持XML编组的基标记。

@XmlRootElement(name="Roles")
public class RolesList
{
   private List<Roles> rolesList;
   ...
   <constructors>
   ...
   @XmlElement(name="Role")
   public List<Roles> getRolesList()
   {
      return rolesList;
   }

   <set/get/add methods>
}

Your controller code becomes (roughly): 您的控制器代码大致变为:

@RequestMapping(method = RequestMethod.GET)
public @ResponseBody HttpEntity<RolesList> getAllRoles() 
   throws ObjectAccessException, ObjectNotFoundException
{
   RolesList resp = new RolesList(rolesManagement.getRoles());
   for (Roles r: resp)
   {
       r.setLink(linkTo(methodOn(RolesRestController.class).getRole(model.getRoleId())).withSelfRel());
   }
   return new ResponseEntity<RolesList>(resp,HttpStatus.OK);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM