JAXB。与损坏代码相同的工作代码示例。 (来源 github link)

JAXB. Example of working code identical to broken code. (src in github link)

https://github.com/akgithubtest/WhyIsItBroken

我不明白为什么 JAXB 使用的一个实例会抛出错误 class Common.Broken nor any of its super class is known to this context. 以及为什么另一个实例工作得很好。我已经将每个分解为视觉差异,甚至无法区分差异。我在这里错过了什么?

在Main.java,我有。这是一个简单的 http 服务器,监听两条路由:workingbrokenbroken 不起作用。 working 确实如此。

import Common.Broken;
import Common.Working;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

import java.io.IOException;
import java.net.InetSocketAddress;

public class Main {
    public static void main(String[] args) throws Exception {
        int port = 8888;
        HttpServer httpServer = HttpServer.create(new InetSocketAddress(port), 0);
        httpServer.createContext("/broken", new BrokenHandler());
        httpServer.createContext("/working", new WorkingHandler());
        httpServer.setExecutor(null);
        httpServer.start();
    }

    static class BrokenHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange httpExchange)
                throws IOException
        {
            try {
                Broken broken = new Broken();
                broken.age = 100;
                broken.id = 3;
                broken.name = "This doesn't work. Why?";

                ResponseHandler responseHandler = new ResponseHandler(broken);
                responseHandler.RespondBroken(httpExchange);
            } catch (Exception ex) {
                System.out.println(ex.getMessage());
            }
        }
    }

    static class WorkingHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange httpExchange)
                throws IOException
        {
            try {

                Working working = new Working();
                working.age = 100;
                working.id = 3;
                working.name = "This works";

                ResponseHandler responseHandler = new ResponseHandler(working);
                responseHandler.RespondWorking(httpExchange);
            } catch (Exception ex) {
                System.out.println(ex.getMessage());
            }
        }
    }
}

Common/Broken.java 中我有以下内容(与 Common/Working.java 相同,但 class 的名称和文件名为 Broken.

package Common;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;

@XmlRootElement (name = "broken")
public class Broken {

    @XmlElement public String name;
    @XmlElement public int age;
    @XmlAttribute public int id;

}

只是为了它(以防万一我遗漏了什么,这里是 Common/Working.java:

package Common;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;

@XmlRootElement (name = "working")
public class Working {

    @XmlElement public String name;
    @XmlElement public int age;
    @XmlAttribute public int id;

}

最后,我有一个响应处理程序。两者的功能几乎相同

import Common.Working;
import Common.Broken;
import com.sun.net.httpserver.HttpExchange;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.IOException;
import java.io.StringWriter;
import java.io.OutputStream;

public class ResponseHandler {

    public Broken broken;
    public Working working;

    private JAXBContext jaxbContext;
    private Marshaller marshaller;


    public ResponseHandler(Working working)
            throws JAXBException
    {
        this.working = working;
        this.Init();
    }

    public ResponseHandler(Broken broken)
            throws JAXBException
    {
        this.broken = broken;
        this.Init();
    }


    private void Init()
        throws JAXBException {
        this.jaxbContext = JAXBContext.newInstance(Working.class);
        this.marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty("com.sun.xml.bind.xmlDeclaration", Boolean.FALSE);
    }

    public void RespondWorking(HttpExchange httpExchange)
            throws JAXBException, IOException
    {
        java.io.StringWriter output = new StringWriter();
        this.marshaller.marshal(this.working, output);
        String response = output.toString();
        httpExchange.sendResponseHeaders(200, response.length());
        OutputStream outputStream = httpExchange.getResponseBody();
        outputStream.write(response.getBytes());
        outputStream.close();
    }

    public void RespondBroken(HttpExchange httpExchange)
            throws JAXBException, IOException
    {
        java.io.StringWriter output = new StringWriter();
        this.marshaller.marshal(this.broken, output);
        String response = output.toString();
        httpExchange.sendResponseHeaders(200, response.length());
        OutputStream outputStream = httpExchange.getResponseBody();
        outputStream.write(response.getBytes());
        outputStream.close();
    }
}

我找不到我在这里遗漏的东西。我要疯了吗? (src 在 github link).

这与您正在为采用 Working 的构造函数和采用 Broken.[=18= 的构造函数调用 Init() 方法这一事实有关]

Init() 方法中调用 JAXBContext.newInstance(Working.class);。当通过构造函数调用 Init() 方法时调用 Broken 应该是 JAXBContext.newInstance(Broken.class); 而不是,这就是它抛出该错误的原因。