簡體   English   中英

一般如何處理CXF請求處理程序中的輸入參數?

[英]How to deal with input parameter in CXF request handler in general?

我一直在使用apache CXF(版本2.2.2)JAX-RS做一些工作。 我想在調用業務方法之前在CXF請求處理程序中引入數據驗證層。 幸運:),我在請求處理程序(DataValidationHandler)中遇到輸入參數處理問題。 我可以通過請求處理程序中的代碼行手動讀取JSON對象。 但它與在CXF框架中注冊的JSONProvider重復。 因為JSON對象輸入流只能被讀取一次,否則我們將遇到異常“java.io.EOFException:由於輸入結束而沒有內容映射到Object”。 此外,重復的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. 如何在請求處理程序中處理http體的POST / PUT輸入參數一般?
  2. 如何有效地避免性能問題來讀取輸入參數?
  3. 有沒有辦法在CXF(JSONProvider)的參數讀取和業務方法調用之間注入驗證(處理程序/攔截器)層?
  4. 有沒有優雅的方法來處理路徑參數?

謝謝你的幫助。 任何意見和建議將不勝感激。

問候,迪倫

我找到了另一種將DataValidation Interceptor注入讀取參數階段的方法。 我們可以從消息內容中重用反序列化的輸入模型,該模型由在框架中注冊的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);
    }
}
}

經過研究,我可以根據以下問題的答案讀取輸入流兩次( 讀取流兩次 )。

但是,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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM