Java Spring hateoas xml序列化,用于使用ResourceAssemblerSupport构建的资源列表
我正在尝试为基于SpringHateOAS的应用程序支持XML响应。对于单个资源,JSON响应和XML一样工作良好。问题从资源列表开始。Spring MVC控制器无法序列化借助ResourceAssemblerSupport派生类生成的列表。控制器抛出org.springframework.web.HttpMediaTypeNotAcceptableException:找不到curl命令的可接受表示形式Java Spring hateoas xml序列化,用于使用ResourceAssemblerSupport构建的资源列表,java,xml,spring-mvc,jaxb2,spring-hateoas,Java,Xml,Spring Mvc,Jaxb2,Spring Hateoas,我正在尝试为基于SpringHateOAS的应用程序支持XML响应。对于单个资源,JSON响应和XML一样工作良好。问题从资源列表开始。Spring MVC控制器无法序列化借助ResourceAssemblerSupport派生类生成的列表。控制器抛出org.springframework.web.HttpMediaTypeNotAcceptableException:找不到curl命令的可接受表示形式 curl -k -i -H "Accept:application/xml" -H "Med
curl -k -i -H "Accept:application/xml" -H "Media-Type:application/xml" -X GET http://127.0.0.1:8080/admin/roles*
我的HATEOAS资源是实体类的包装器:
@XmlRootElement
@XmlSeeAlso(RoleModel.class)
public class RoleResource extends ResourceSupport {
public RoleModel role;
}
控制器很简单:
@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);
}
资源汇编程序类:
@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;
}
}
当我避免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序列化工作正常。我想我可以避免使用资源汇编程序并手动构建资源,但这会使代码不那么干净和模块化。我想知道是否仍然可以使用ResourceAssemblerSupport作为资源生成器,并以XML的形式返回资源列表资源汇编器用于将一个pojo/实体/任何东西转换为一个hateoas资源。您正在尝试将列表转换为列表 如果你是一个装配工
public class RoleResourceAssembler extends ResourceAssemblerSupport<List<RoleModel>, RolesResource> {
而RoleResource是你想要的东西……它应该会起作用
不过,我建议您考虑使用PagedResourceAssembler,它获取一页内容,并使用汇编程序创建一页资源。页面可以是完整集合,也可以只是集合中的一个页面。下面是一个简单的类别:
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);
}
但是..我在jackson将PagedResources封送为XML时遇到了一些问题…对于JSON来说效果很好。似乎有了ResourceAssemblerSupport,就不可能将HATEOAS资源列表封送为XML。原因是扩展ResourceAssemblerSupport的类的toResources方法返回的资源列表没有@XmlRootElement,JAXB无法封送它。我必须创建像这样的类
@XmlRootElement
public class Roles {
private List<RoleResource> roleResource;
....
}
@XmlRootElement
public class RoleResource extends ResourceSupport {
private RoleModel role;
...
}
并手动构建我的资源列表。当我尝试使用SpringHateOAS资源包装器时,也出现了同样的问题
Resource<RoleModel> resource = new Resource<>();
由于Spring的资源类没有使用@XmlRootElement注释,因此如果您的唯一要求是生成org.springframework.hateoas.Link和marshall作为XML的链接,REST控制器无法将其封送到XML,以下内容可能会有所帮助 将链接项添加到模型类
@XmlRootElement(name="Role")
public class Roles
{
Link link;
<your Roles content>
...
}
将基类包装在列表中,以提供支持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>
}
控制器代码大致如下:
@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);
}
另一件奇怪的事情是,通过ResourceAssemblerSupport生成的单个资源被序列化为atom而不是普通XML:ResourceAssemblerSupport有两个方法:toResource和toResources。后者将Iterable作为参数并返回资源列表。我认为这是我应该使用的。你是对的。我错过了ResourceAssembler和ResourceAssembler支持的细微差别。返回一个资源列表感觉很奇怪,在我看来,返回一个嵌入其他资源的资源要好得多。那么,这解决了你的问题吗?还是这些类仍然没有正确封送?@willOEM不,我没有。问题不在于ResourceAssemblerSupport,而在于JAXB没有处理Java的列表,因为它没有用XmlRootElement注释。由于toResources of ResourceAssemblerSupport返回资源列表,JAXB无法封送它。我的解决方案是不使用ResourceAssemblerSupport,而是使用具有XMLRootElementThank的列表类手动构建资源。我得到了你的解决方案。仅供参考,我还发现XStream可以使用资源汇编程序正确封送资源和资源对象,而无需额外配置或注释,但它们仍然是atom格式的。@您是如何使用XStream获得atom的?对我来说,它可以分解为常规XML。根据规范,HATEOS XML应该是atom。