axis2 使用json格式交互

 因为工作原因,最近对axis2框架进行一些的研究。因此对框架使用中的一些问题进行记录,方便以后回顾。

系统环境

    window7

    axis2  1.7.8 / 1.7.4

    jdk 1.8

    gson 2.8.2

    maven 3.5.0

  通过官网介绍,axis2原生支持json的方式有两种

  一种是基于XML Stream API(这种不符合需求,就没有多做了解)

  一种是使用纯json格式,请求与响应都是json格式,也是此次学习的目标。

  首先需要在axis2.xml配置

                  <messageBuilder contentType="application/json"
                                  class="org.apache.axis2.json.gson.JsonBuilder" />

                  <messageFormatter contentType="application/json"
                                    class="org.apache.axis2.json.gson.JsonFormatter" />

然后在services.xml配置

            <messageReceivers>
                <messageReceiver mep="http://www.w3.org/ns/wsdl/in-out"
                                 class="org.apache.axis2.json.gson.rpc.JsonRpcMessageReceiver"/>
                <messageReceiver mep="http://www.w3.org/ns/wsdl/in-only"
                                 class="org.apache.axis2.json.gson.rpc.JsonInOnlyRPCMessageReceiver"/>
            </messageReceivers>


启动项目,按照官方案例进行测试,会发现gson格式化出错。

java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 14

测试请求数据

{"echoUser":{"user":{"name":"My_Name","surname":"MY_Surname","middleName":"My_MiddleName","age":123,"address":{"country":"My_Country","city":"My_City","street":"My_Street","building":"My_Building","flat":"My_Flat","zipCode":"My_ZipCode"}}}}

查看源码发现axis2 是使用gson库来进行解析,对json格式是有要求的,官方案例或许是太久没有更新了

jsonReader.beginObject();
String messageName=jsonReader.nextName();     // get message name from input json stream
jsonReader.beginArray();

int i = 0;
for (Class paramType : paramClasses) {
    jsonReader.beginObject();
    argNames[i] = jsonReader.nextName();
    methodParam[i] = gson.fromJson(jsonReader, paramType);   // gson handle all types well and return an object from it
    jsonReader.endObject();
    i++;
}

jsonReader.endArray();
jsonReader.endObject();

重新设置json数据

{"request":[{"echoUser":{"user":{"name":"My_Name","surname":"MY_Surname","middleName":"My_MiddleName","age":123.0,"address":{"country":"My_Country","city":"My_City","street":"My_Street","building":"My_Building","flat":"My_Flat","zipCode":"My_ZipCode"}}}}]}

这个时候json已经可以正常解析了,但是还是返回异常。

java.lang.NullPointerException

查看日志



对于这种错误,在各种Google后也并没有找到相关资料后,只能自己查看源码。

对比源码 JsonRpcMessageReceiver 和 RPCMessageReceiver

可以看到 在设置响应数据时 outMessage有个属性没有赋值


找到原因后,就好办了,重新实现JsonRpcMessageReceiver 

services.xml重新配置为自己实现类

<messageReceiver mep="http://www.w3.org/ns/wsdl/in-out"
class="com.axis2.common.receiver.SimpleJsonRpcMessageReceiver"  />

重新进行测试

可以看到已经可以正常返回了json数据了 

{"response":{"surname":"admin","age":28}}

注: response这个参数是axis2 框架自动添加的,如果不喜欢可以自行实现JsonFormatter,


同理如果不喜欢请求json格式的限制,可自行实现Jsonutils,按照自己的风格定制。

以下是修改后的代码

public class JsonUtils {

    public static Object invokeServiceClass(JsonReader jsonReader,
                                            Object service,
                                            Method operation ,
                                            Class[] paramClasses ,
                                            int paramCount ) throws InvocationTargetException,
            IllegalAccessException, IOException  {

        Object[] methodParam = new Object[paramCount];
        Gson gson = new Gson();
        String[] argNames = new String[paramCount];

        if( ! jsonReader.isLenient()){
            jsonReader.setLenient(true);
        }

        int i = 0;
        for (Class paramType : paramClasses) {
            methodParam[i] = gson.fromJson(jsonReader, paramType);
            i++;
        }

        return  operation.invoke(service, methodParam);

    }

    public static Method getOpMethod(String methodName, Method[] methodSet) {
        for (Method method : methodSet) {
            String mName = method.getName();
            if (mName.equals(methodName)) {
                return method;
            }
        }
        return null;
    }

}


/**
 * @author: yc
 */
public class SimpleJsonRpcMessageReceiver extends JsonRpcMessageReceiver {

    private static final Log log = LogFactory.getLog(SimpleJsonRpcMessageReceiver.class);
    @Override
    public void invokeBusinessLogic(MessageContext inMessage, MessageContext outMessage) throws AxisFault {
        Object tempObj = inMessage.getProperty(JsonConstant.IS_JSON_STREAM);
        boolean isJsonStream;
        if (tempObj != null) {
            isJsonStream = Boolean.valueOf(tempObj.toString());
        } else {
            // if IS_JSON_STREAM property  is not set then it is not a JSON request
            isJsonStream = false;
        }
        if (isJsonStream) {
            Object o = inMessage.getProperty(JsonConstant.GSON_XML_STREAM_READER);
            if (o != null) {
                GsonXMLStreamReader gsonXMLStreamReader = (GsonXMLStreamReader)o;
                JsonReader jsonReader = gsonXMLStreamReader.getJsonReader();
                if (jsonReader == null) {
                    throw new AxisFault("JsonReader should not be null");
                }
                Object serviceObj = getTheImplementationObject(inMessage);
                AxisOperation op = inMessage.getOperationContext().getAxisOperation();
                String operation = op.getName().getLocalPart();
                invokeService(jsonReader, serviceObj, operation , outMessage, inMessage);
            } else {
                throw new AxisFault("GsonXMLStreamReader should be put as a property of messageContext " +
                        "to evaluate JSON message");
            }
        } else {
            // call RPCMessageReceiver if inputstream is null
            super.invokeBusinessLogic(inMessage, outMessage);
        }
    }

    public void invokeService(JsonReader jsonReader, Object serviceObj, String operation_name,
                              MessageContext outMes, MessageContext inMessage) throws AxisFault {
        String msg;
        Class implClass = serviceObj.getClass();
        Method[] allMethods = implClass.getDeclaredMethods();
        Method method = JsonUtils.getOpMethod(operation_name, allMethods);
        Class[] paramClasses = method.getParameterTypes();
        try {
            int paramCount = paramClasses.length;
            //20180601 修改  不限制json格式,只要是json就可以
            Object retObj = JsonUtils.invokeServiceClass(jsonReader, serviceObj, method, paramClasses, paramCount);

            SOAPFactory fac = getSOAPFactory(inMessage);
            SOAPEnvelope envelope = fac.getDefaultEnvelope();
            // handle response
            outMes.setProperty(JsonConstant.RETURN_OBJECT, retObj);
            outMes.setProperty(JsonConstant.RETURN_TYPE, method.getReturnType());
            //20180601 修改 原框架代码不赋值 会导致空指针,
            outMes.setEnvelope(envelope);
        } catch (IllegalAccessException e) {
            msg = "Does not have access to " +
                    "the definition of the specified class, field, method or constructor";
            log.error(msg, e);
            throw AxisFault.makeFault(e);

        } catch (InvocationTargetException e) {
            msg = "Exception occurred while trying to invoke service method " +
                    (method != null ? method.getName() : "null");
            log.error(msg, e);
            throw AxisFault.makeFault(e);
        } catch (IOException e) {
            msg = "Exception occur while encording or " +
                    "access to the input string at the JsonRpcMessageReceiver";
            log.error(msg, e);
            throw AxisFault.makeFault(e);
        }
    }

测试代码

/**
 * @author: yc
 */
public class ClientTest {

    private static String url = "http://localhost:8082/xxx/services/xxx/xxx";
    private static String contentType = "application/json";
    private static String charSet = "UTF-8";
    private static Gson gson = new Gson();

    public static void main(String[] args) throws IOException {
        Map<String, String> map = new HashMap<String, String>();
        map.put("name", "admin");
        map.put("pw", "123456");
        String req = gson.toJson(map);
        post(req);

    }


    public static String post(String message) throws UnsupportedEncodingException {
        String response = "";
        PostMethod post = new PostMethod(url);
        RequestEntity entity = new StringRequestEntity(message , contentType, charSet);
        post.setRequestEntity(entity);
        HttpClient httpclient = new HttpClient();
        try {
            int result = httpclient.executeMethod(post);
            System.out.println("Response status code: " + result);
            System.out.println("Response head: " + gson.toJson(post.getResponseHeaders()));
            System.out.println("Response body: ");
            response = new String(post.getResponseBody(), "utf-8");
            System.out.println(response);
            return response;
        } catch (HttpException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            post.releaseConnection();
        }
        return response;
    }
}

猜你喜欢

转载自blog.csdn.net/smuggledgoods/article/details/80612858