如何应对一般CXF请求处理程序输入参数?(How to deal with input parame

2019-07-29 13:34发布

我一直在做与Apache CXF(2.2.2版)JAX-RS一些工作。 我试图在CXF请求处理器引入数据验证层调用业务方法之前。 幸运的:),我对输入参数的请求处理器(DataValidationHandler)处理遇到的问题。 我可以通过在请求处理程序下面的代码行手动读取JSON对象。 但是,它的复制与CXF框架注册JSONProvider。 因为JSON对象输入流只能读一次,否则我们会遇到例外“java.io.EOFException的:没有内容映射到对象,由于输入的结束”。 此外,重复的JSON对象反序列化将影响性能。 下面的代码是你的参考样本。

阅读从手动HTTP主体JSON对象:

OperationResourceInfo ori = paramMessage.getExchange().get(OperationResourceInfo.class);
MultivaluedMap<String, String> values = new MetadataMap<String, String>();
List<Object> objList = JAXRSUtils.processParameters(ori, values, paramMessage);

在CXF的JAX-RS框架注册JSONProvider:

<bean id="JSONProvider" class="com.accela.govxml2.jaxrs.util.JSONProvider"></bean>

阅读JSON对象从输入流Java对象:

public Object readFrom(......){
    ObjectMapper objectMapper = new ObjectMapper();
    Object result = objectMapper.readValue(entityStream, TypeFactory.defaultInstance().constructType(genericType));
    Return result;
}

我对下面的代码行手动处理路径参数。

OperationResourceInfo ori = paramMessage.getExchange().get(OperationResourceInfo.class);
URITemplate t1 = ori.getClassResourceInfo().getURITemplate();
URITemplate t2 = ori.getURITemplate();
UriInfo uriInfo = new UriInfoImpl(paramMessage, null);
MultivaluedMap<String, String> map = new MetadataMap<String, String>();
t1.match(uriInfo.getPath(), map);
String str = map.get(URITemplate.FINAL_MATCH_GROUP).get(0);
t2.match(str, map);
String pathParameter= null;
if (map.containsKey("pathParam") && !ValidationUtil.isEmpty(map.get("pathParam")))
{
    pathParameter= map.get("pathParam").get(0);
}

我的问题是在这里:

  1. 如何处理一般用POST / PUT HTTP体的输入参数,请求处理程序?
  2. 如何避免性能问题,以有效地读取输入参数?
  3. 有什么办法来注入验证(处理器/拦截)参数读数之间的层CXF(JSONProvider)和业务方法调用?
  4. 是否有任何优雅的方式来处理路径参数?

谢谢你的帮助。 有任何意见和建议,将不胜感激。

问候,迪伦

Answer 1:

我已经找到了另一种方式来注入资料验证拦截入读参数阶段。 我们可以重复使用邮件内容,它通过JSONProvider反序列化框架中注册反序列化的输入模式。 它可以提高性能,因为只有反序列化输入模型一次。

public class DataValidationInInterceptor extends AbstractPhaseInterceptor<Message>
{
public DataValidationInInterceptor()
{
    super(Phase.READ);
}

@Override
public void handleMessage(Message message)
{
    OperationResourceInfo ori = message.getExchange().get(OperationResourceInfo.class);
    Method method = ori.getMethodToInvoke();
    Class<?>[] types = method.getParameterTypes();
    Type[] genericParameterTypes = method.getGenericParameterTypes();

    for (int i = 0; i < types.length; i++)
    {
        Class<?> type = types[i];
        List obj = (List) message.getContent(List.class);
        System.out.println(obj);
        System.out.println(type);
    }
}
}


Answer 2:

经过研究,我可以读两次基于以下问题的答案输入流( 读取流的两倍 )。

然而,JSON对象反序列化的表现仍然是我的问题。 谁拥有它更好的解决办法?

截距请求和来自CoyoteInputStream到ByteArrayInputStream进行改变消息的内容,所以可从该InputStream读取两次。

InputStream in = message.getContent(InputStream.class);
if (in != null)
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    IOUtils.copy(in, baos);
    byte[] bytes = baos.toByteArray();
    ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
    message.setContent(InputStream.class, bais);
}

读取JSON对象从输入流中的Java对象之前重置ByteArrayInputStream的:

public Object readFrom(......){
    ObjectMapper objectMapper = new ObjectMapper();
    if (entityStream.markSupported())
    {
        entityStream.reset();
    }
    Object result = objectMapper.readValue(entityStream, TypeFactory.defaultInstance().constructType(genericType));
    return result;
}


文章来源: How to deal with input parameter in CXF request handler in general?