gpt4 book ai didi

java - 如何处理 setter 在 JAXB 自动从请求正文解码时抛出的异常?

转载 作者:搜寻专家 更新时间:2023-10-31 19:55:37 25 4
gpt4 key购买 nike

我将以下 JSON 请求正文发送到我的 Controller :

{"Game": {"url": "asd"}}

其中 Game 是我的模型类,用 @XmlRootElement 注释(以及一些在此上下文中不重要的 JPA 注释)。

Controller :

@PUT
@Path("/{name}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createRow(
@PathParam("name") String name,
Game gameData) throws Exception{

Game.createRow(gameData); // + exception handling etc.
}

现在,我了解到当 Controller 方法的 Game gameData 参数被创建时,模型类中的 setter 被调用。需要注意的setter是:

public void setUrl(String url) throws Exception{
String regex = "^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
Pattern pattern = Pattern.compile(regex);

System.out.println("URL: " + url);
if ( url == null || url.length() == 0) {
throw new Exception("The url of the game is mandatory!");
} else {
Matcher matcher = pattern.matcher(url);
if (!matcher.matches()) {
throw new Exception("The url is invalid! Please check its syntax!");
} else {
this.url = url;
}
}
}

发生的事情是,在将 JSON 字符串反序列化为 Game 对象期间,The url is invalid! 异常被抛出,但仅在 TomEE 的控制台中>。我想做的是将这个错误发送给客户端。

如果我使用扩展 WebApplicationException 的异常而不是通用异常,那么我会在客户端中得到一个异常,但不是关于 url 有效性的异常。相反,在反序列化之后,gameData.url 为 NULL,当我尝试使用来自 gameData 的数据创建 Game 实例时,setter 将被调用为 gameToBeCreated.set(NULL),我会得到异常 Url is mandatory,实际上是从客户端发送了一个 URL,但语法错误。从客户端发送时它不是 NULL。

那么,我能否以某种方式拦截发生自动解码时抛出的异常并将它们转发给客户端?

最佳答案

使用 JAXB 拦截异常

A ValidationEventHandler用于拦截解码过程中发生的异常。如果你想收集所有发生的错误,你可以使用 ValidationEventCollector .

Java 模型

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Foo {

private String bar;

public String getBar() {
return bar;
}

public void setBar(String bar) {
throw new RuntimeException("Always throw an error");
}

}

演示

import java.io.StringReader;
import javax.xml.bind.*;
import javax.xml.bind.util.ValidationEventCollector;

public class Demo {

private static String XML = "<foo><bar>Hello World</bar></foo>";

public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Foo.class);

Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.unmarshal(new StringReader(XML));

ValidationEventCollector vec = new ValidationEventCollector();
unmarshaller.setEventHandler(vec);
unmarshaller.unmarshal(new StringReader(XML));
System.out.println(vec.getEvents().length);
}

}

输出

1

与 JAX-RS 集成

MessageBodyReader

您可以创建 MessageBodyReader 的实例您可以在哪里利用 ValidationEventHandler在解码过程中。下面的链接给出了如何实现 MessageBodyReader 的示例。 .

ContextResolver<Unmarshaller>

稍微高一点,你可以实现ContextResolver<Unmarshaller>并拥有 Unmarshaller返回有适当的ValidationEventHandler在上面。它看起来像下面这样:

import javax.ws.rs.core.*;
import javax.ws.rs.ext.*;
import javax.xml.bind.*;
import javax.xml.bind.helpers.DefaultValidationEventHandler;

@Provider
public class UnmarshallerResolver implements ContextResolver<Unmarshaller> {

@Context Providers providers;

@Override
public Unmarshaller getContext(Class<?> type) {
try {
ContextResolver<JAXBContext> resolver = providers.getContextResolver(JAXBContext.class, MediaType.APPLICATION_XML_TYPE);
JAXBContext jaxbContext;
if(null == resolver || null == (jaxbContext = resolver.getContext(type))) {
jaxbContext = JAXBContext.newInstance(type);
}
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setEventHandler(new DefaultValidationEventHandler());
return unmarshaller;
} catch(JAXBException e) {
throw new RuntimeException(e);
}
}

}

关于java - 如何处理 setter 在 JAXB 自动从请求正文解码时抛出的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20357832/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com