如何在JAX-RS中通过工厂方法从REST请求JSON体读取数据对象?
问题解决方法
出现415错误的核心原因:默认情况下Jersey使用EclipseLink MOXy(JAXB实现)作为JSON消息体解析器,它要求实体类必须有无参构造器或显式指定JAXB工厂方法,而你自定义的valueOf方法并不被它识别。@HeaderParam/@QueryParam是通过JAX-RS的参数转换器机制工作,该机制会自动寻找接收单个String参数的valueOf静态方法,所以能正常运行。
下面是几种可行的解决方案:
方案一:改用Jackson处理JSON解析(推荐)
因为你已经引入了Jackson 2.14.2,直接配置Jersey使用Jackson的消息体解析器,同时利用Jackson的注解支持不可变对象:
1. 确保依赖正确
如果是Maven项目,添加Jackson的JAX-RS提供者依赖:
<dependency> <groupId>com.fasterxml.jackson.jaxrs</groupId> <artifactId>jackson-jaxrs-json-provider</artifactId> <version>2.14.2</version> </dependency>
2. 修改实体类,添加Jackson注解
用@JsonCreator标记构造器,@JsonProperty指定JSON字段与构造参数的映射:
public class MyDataObj { private final int a; @JsonCreator public MyDataObj(@JsonProperty("a") int a) { this.a = a; } public int getA() { return a; } }
这样Jackson会直接通过带参构造器创建对象,无需无参构造,也不用自己写valueOf方法。
方案二:用Jackson注解指定工厂方法
如果想保留valueOf作为工厂方法,修改实体类如下:
public class MyDataObj { private final int a; private MyDataObj(int a) { this.a = a; } @JsonCreator public static MyDataObj valueOf(@JsonProperty("a") int a) { return new MyDataObj(a); } public int getA() { return a; } }
@JsonCreator会告诉Jackson调用这个静态方法来创建对象,@JsonProperty用来绑定JSON中的a字段到方法参数。
方案三:配置JAXB工厂方法(不推荐,若必须用MOXy)
如果坚持使用默认的EclipseLink MOXy,可以通过JAXB注解指定工厂方法:
1. 创建工厂类
public class MyDataObjFactory { public static MyDataObj createMyDataObj(int a) { return new MyDataObj(a); } }
2. 在实体类上添加JAXB注解
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) @XmlType(factoryClass = MyDataObjFactory.class, factoryMethod = "createMyDataObj") public class MyDataObj { @XmlElement(name = "a") private int a; public MyDataObj(int a) { this.a = a; } public int getA() { return a; } }
这种方式需要额外编写工厂类,且仅适用于JAXB解析器,不如Jackson方案灵活。
内容的提问来源于stack exchange,提问作者rawcode
相关产品推荐
相关产品推荐

