首页 > 解决方案 > javax.xml.bind.JAXBException: 类 java.util.ArrayList 或其任何超类在此上下文中都是已知的

问题描述

我正在编写一个 MVC Java 程序,使用 JAXB 生成 XML 并发送到显示 jsp。代码运行并且 XML 在浏览器中正确显示,但我仍然在 IDE 控制台中收到 JAXBException。

我在此处此处提到了有关该主题的几页。我已按照建议添加了 JAXB 注释,但错误并没有消失。

任何人都可以帮忙吗?

网络小服务程序

@WebServlet(name = "GetAllFilms", value = "/GetAllFilms")
public class GetAllFilms extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setCharacterEncoding("UTF-8");
        String jspDisplayString = "";

        String dataFormat = request.getParameter("format");
        if (dataFormat == null) dataFormat = "json";

        FilmDAO filmDAO = new FilmDAO();
        ArrayList<Film> allFilms = filmDAO.getAllFilms();

        request.setAttribute("films", allFilms);

        String viewJspFilePath = "";

        if (dataFormat.equals("json")) {
            response.setContentType("application/json");
            viewJspFilePath = "/WEB-INF/results/films-json.jsp";

            jspDisplayString = jsonGenerator(allFilms);

        } else if (dataFormat.equals("xml")) {
            response.setContentType("text/xml");
            viewJspFilePath = "/WEB-INF/results/films-xml.jsp";

            try {
                jspDisplayString = xmlGenerator(allFilms);
            } catch (JAXBException e) {
                e.printStackTrace();
            }

        } else {
            response.setContentType("text/plain");
            viewJspFilePath = "/WEB-INF/results/films-string.jsp";

            jspDisplayString = stringGenerator(allFilms);
        }

        RequestDispatcher dispatcher =
                request.getRequestDispatcher(viewJspFilePath);
        dispatcher.include(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

    private String xmlGenerator(ArrayList<Film> allFilms)
            throws JAXBException, FileNotFoundException {

        FilmList filmList = new FilmList();
        filmList.setFilmList(allFilms);

        JAXBContext jaxbContext = JAXBContext.newInstance(FilmList.class);
        Marshaller marshaller = jaxbContext.createMarshaller();

        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        StringWriter stringWriter = new StringWriter();
        marshaller.marshal(allFilms, stringWriter);

        return stringWriter.toString();
    }
}

电影模型类(带有 JAXB 注释)

package model_beans;

@XmlRootElement(name = "film")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = { "id", "title", "year", "director", "stars", "review" })

public class Film {

    public Film() {

    }

    public Film(int id, String title, int year, String director, String stars,
                String review) {
        super();
        this.id = id;
        this.title = title;
        this.year = year;
        this.director = director;
        this.stars = stars;
        this.review = review;
    }

    int id;
    String title;
    int year;
    String director;
    String stars;
    String review;

    *getters / setters excluded for ease of reading*

    @Override
    public String toString() {
        return "Film [id=" + id + ", title=" + title + ", year=" + year
                + ", director=" + director + ", stars=" + stars + ", review="
                + review + "]";
    }
}

FilmList 模型类(带有 JAXB 注释)

package model_beans;

@XmlRootElement(namespace = "model_beans")
@XmlAccessorType(XmlAccessType.FIELD)
public class FilmList {

    @XmlElementWrapper(name = "filmList")
    @XmlElement(name = "film")
    private ArrayList<Film> filmList;

    public ArrayList<Film> getFilmList() {
        return filmList;
    }

    public void setFilmList(ArrayList<Film> filmList) {
        this.filmList = filmList;
    }
}

JSP XML 数据格式

<?xml version="1.0" encoding="UTF-8"?>
<%--@elvariable id="films" type="model_beans.Film"--%>
<%@taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core"%>
<films>
  <headings>
    <heading>Film ID</heading>
    <heading>Title</heading>
    <heading>Year</heading>
    <heading>Director</heading>
    <heading>Stars</heading>
    <heading>Review</heading>
  </headings>
  <c:forEach items="${films}" var="f">
    <film>
      <id>${f.id}</id>
      <title>${f.title}</title>
      <year>${f.year}</year>
      <director>${f.director}</director>
      <stars>${f.stars}</stars>
      <review>${f.review}</review>
    </film>
  </c:forEach>
</films>

堆栈跟踪

javax.xml.bind.JAXBException: class java.util.ArrayList nor any of its super class is known to this context.
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:567)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:467)
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236)
    at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:116)
    at controller_servlets.GetAllFilms.xmlGenerator(GetAllFilms.java:125)
    at controller_servlets.GetAllFilms.doGet(GetAllFilms.java:68)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

标签: javajaxb

解决方案


修改FilmList类如下,

  1. @XmlRootElement注释添加到类
  2. 从类中删除@XmlElementWrapper注释

电影列表.java

    @XmlRootElement(name="filmList")
    public class FilmList {

        private ArrayList<Film> listFilm;

        @XmlElement(name = "film")
        public ArrayList<Film> getFilmList() {
            return listFilm;
        }

        public void setFilmList(ArrayList<Film> listFilm) {
            this.listFilm = listFilm;
        }
    }

电影.java

@XmlRootElement(name = "film")
@XmlType(propOrder = { "id", "title", "year", "director", "stars", "review" })
public class Film {

    public Film() {

    }

    public Film(int id, String title, int year, String director, String stars,
                String review) {
        super();
        this.id = id;
        this.title = title;
        this.year = year;
        this.director = director;
        this.stars = stars;
        this.review = review;
    }

    int id;
    String title;
    int year;
    String director;
    String stars;
    String review;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public String getDirector() {
        return director;
    }

    public void setDirector(String director) {
        this.director = director;
    }

    public String getStars() {
        return stars;
    }

    public void setStars(String stars) {
        this.stars = stars;
    }

    public String getReview() {
        return review;
    }

    public void setReview(String review) {
        this.review = review;
    }

    @Override
    public String toString() {
        return "Film [id=" + id + ", title=" + title + ", year=" + year
                + ", director=" + director + ", stars=" + stars + ", review="
                + review + "]";
    }
}

Marshaller.java

public class Marshaller {

    public static void main(String[] args) {
    
        ArrayList<Film> listFilm = new ArrayList<>();
        StringWriter stringWriter = new StringWriter();
        FilmList filmList = new FilmList();

        Film film = new Film();
        film.setDirector("a");
        film.setId(1);
        film.setReview("b");
        film.setStars("c");
        film.setTitle("e");
        film.setYear(2020);
        listFilm.add(film);
        filmList.setFilmList(listFilm);
    
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(FilmList.class);
            javax.xml.bind.Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true);
            jaxbMarshaller.marshal(filmList, stringWriter);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        System.out.println(stringWriter);
    }
}

输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<filmList>
    <film>
        <id>1</id>
        <title>e</title>
        <year>2020</year>
        <director>a</director>
        <stars>c</stars>
        <review>b</review>
    </film>
</filmList>

已编辑

出现以下错误的原因是 和 使用了相同的名称( filmList) 。因此,请将名称更改为@XmlRootElementArrayList<Film>ArrayList<Film>listFilm

笔记。请设置@XmlElement注释以获取方法

最后编辑

在上面的 servlet 中,您尝试(allFilms)在 xmlGenerator 方法中编组 java 集合( Film 列表)。

marshaller.marshal(allFilms, stringWriter);

但无法编组集合,并且 java 集合类没有 JAXB 注释。

在您的情况下,创建了该FilmList对象,但它不用于编组。我认为这是你的错误。请编组filmList如下

marshaller.marshal(filmList, stringWriter);

推荐阅读