更新:最终我尝试了这里建议的所有内容并且似乎取得了一些进展,但我的API已经过度设计用于预期目的而且我已经没时间了,所以我切换到硬编码&#34 ;学生名单"在我的GET /学生电话的字符串响应中,这对于我需要它的概念证明来说已经足够了。
我正在开发一个简单的REST服务,它使用XML来处理学生记录。
当我对学生进行GET时,我得到了:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<students>
<student>
<grade>B</grade>
<name>Jane</name>
</student>
...
</students>
但是,我希望输出为:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student-list>
<student>
<grade>B</grade>
<name>Jane</name>
</student>
...
</student-list>
这是我的 Student.java 代码段:
@XmlRootElement(name = "student")
public class Student {
private String name;
private String grade;
public Student() {
}
public Student(String name, String grade) {
super();
this.name = name;
this.grade = grade;
}
// getters/setters ...
}
我尝试将XmlRootElement更改为&#34; student-list&#34;,但这会使列表中的每个子元素成为学生列表类型,并忽略顶级元素列表。
该项目使用带有StudentsResource类的JAX-RS,我尝试在该资源类上设置XmlRootElement名称,但这不影响任何输出。
它似乎是根据StudentsResource类自动命名顶级列表,我无法弄清楚如何覆盖此名称。
我一直在梳理这方面的文档,但Java现在不是我最强的语言,所以我无法理解这些部分如何适合JAXB和JAX-RS。
任何想法,或推动正确的方向?
编辑:添加了StudentsResource.java代码段
@Path("/student")
public class StudentsResource {
// this is a mapper class
@Context
UriInfo uriInfo;
@Context
Request request;
StudentService studentService;
public StudentsResource() {
studentService = new StudentService();
}
@GET
@Produces("text/xml;charset=utf-8")
public List<Student> getStudents() {
return studentService.getStudentAsList();
}
...
}
根据Mateen Momin的反馈,我现在通过GET / student上的REST服务输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<studentDao_Students>
<student>
<name>Jane</name>
<grade>B</grade>
</student>
...
</studentDao_Students>
我有一个StudentDao,它被StudentService包装,最终由资源类调用,以使HTTP调用成为可能。我已将我的学生课程移到StudentDao,这让我意识到StudentService实际上正在编组,这里有更新的片段:
StudentDao.java :
public enum StudentDao {
instance;
private Map<String, Student> students = new HashMap<String, Student>();
private StudentDao() {
//pre-populate for testing purposes
Student student = new Student("John", "A");
students.put("John", student);
student = new Student("Jane", "B");
students.put("Jane", student);
student = new Student("TESTUSER", "F");
students.put("TESTUSER", student);
}
public Map<String, Student> getStudents() {
return students;
}
@XmlRootElement(name="student")
@XmlAccessorType(XmlAccessType.FIELD)
public static class Student {
private String name;
private String grade;
public Student() {
}
public Student(String name, String grade) {
super();
this.name = name;
this.grade = grade;
}
// getters/setters here...
}
}
StudentService.java :
@XmlRootElement(name = "student-list")
@XmlAccessorType(XmlAccessType.FIELD)
public class StudentService {
StudentDao studentDao;
public StudentService() {
studentDao = StudentDao.instance;
}
// CRUD methods here which call the StudentDao HashMap
}
StudentsResource.java :
@Path("/student")
public class StudentsResource {
@Context
UriInfo uriInfo;
@Context
Request request;
StudentService studentService;
public StudentsResource() {
studentService = new StudentService();
}
@GET
@Produces("text/xml;charset=utf-8")
public List<Student> getStudents() {
return studentService.getStudentAsList();
}
// other HTTP calls, POST,PUT,etc. here
}
我创建了一个main函数来查看如果指定JAXBContext会发生什么:
主要用于测试控制台输出:
public class Main {
public static void main(String[] args) {
StudentService studentDao = new StudentService();
StudentDao.Student stu1 = new StudentDao.Student();
stu1.setName("marc");
stu1.setGrade("A");
StudentDao.Student stu2 = new StudentDao.Student();
stu2.setName("jacob");
stu2.setGrade("B");
StudentDao.Student stu3 = new StudentDao.Student();
stu3.setName("anthony");
stu3.setGrade("A");
studentDao.createStudent(stu1);
studentDao.createStudent(stu2);
studentDao.createStudent(stu3);
try {
File file = new File("out.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(StudentService.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(studentDao, file);
jaxbMarshaller.marshal(studentDao, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
当我运行这个main函数来查看输出时我实际上得到了这个,当然它与REST输出不匹配:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student-list>
<studentDao>instance</studentDao>
</student-list>
这似乎很有希望,但我似乎无法在REST调用中覆盖顶级类名,这最终是我需要的。
我在这里做错了什么其他的想法?
答案 0 :(得分:1)
学生班
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "student-list")
@XmlAccessorType(XmlAccessType.FIELD)
public class Students{
//students
@XmlElement(name = "student")
public ArrayList<Student> studentsLst;
//getters and setters
public ArrayList<Student> getStudentsLst() {
return studentsLst;
}
public void setStudentsLst(ArrayList<Student> studentsLst) {
this.studentsLst = studentsLst;
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class Student {
private String name;
private String grade;
public Student() {
}
public Student(String name, String grade) {
super();
this.name = name;
this.grade = grade;
}
// getters/setters ...
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
}
}
主要方法 / marshaller使用:
public static void main(String[] args) {
Students.Student stu1 = new Students.Student();
stu1.setName("marc");
stu1.setGrade("A");
Students.Student stu2 = new Students.Student();
stu2.setName("jacob");
stu2.setGrade("B");
Students.Student stu3 = new Students.Student();
stu3.setName("anthony");
stu3.setGrade("A");
ArrayList<Students.Student> studentsLst = new ArrayList<>();
studentsLst.add(stu1);
studentsLst.add(stu2);
studentsLst.add(stu3);
Students students = new Students();
students.setStudentsLst(studentsLst);
try {
File file = new File("C:\\file.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Students.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(students, file);
jaxbMarshaller.marshal(students, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
生成的输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student-list>
<student>
<name>marc</name>
<grade>A</grade>
</student>
<student>
<name>jacob</name>
<grade>B</grade>
</student>
<student>
<name>anthony</name>
<grade>A</grade>
</student>
</student-list>
PS:由于您使用的是REST,因此上面给出的 main方法可以用于您的FYI。使用此主要方法相应地构建您的studentService.getStudentAsList()
方法。 (我的假设是它几乎可以提供相同的xml。):)