• 添加webservice调用日志


      之前想用spring的AOP给webservice添加切面的,但是使用around切面后,居然调用端得不到webservice的返回结果,而且报文的详细情况也不得而知,很是尴尬,所以偷了个懒。但是该做的还是要做,不要以后要求查看调用日志的时候,什么都拿不出,不是一个尴尬能搞定的。

      我使用的是基于cxf的webservice,所以添加调用日志的方法也是基于cxf的,其次是配合sping开发webservice。基本的webservice的实现,这里就不再说明。

     一、使用LoggingInInterceptor实现

      第一种方法,就是使用已经的实现的日志拦截,需要配置好log.properties。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:jaxws="http://cxf.apache.org/jaxws"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd ">
    
        <jaxws:endpoint implementor="com.test.DepartServiceImpl" address="/departService">
            <jaxws:inInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
            </jaxws:inInterceptors>
            <jaxws:outInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
            </jaxws:outInterceptors>
        </jaxws:endpoint>
        
    </beans>
      <jaxws:inInterceptors>是输入拦截器,在接口被调用的时候会被拦截。下面是接口被调用后的日志输出。
    ----------------------------
    ID: 1
    Address: http://localhost:8080/test/ws/departService?wsdl
    Encoding: UTF-8
    Http-Method: POST
    Content-Type: text/xml; charset=UTF-8
    Headers: {Accept=[*/*], cache-control=[no-cache], connection=[keep-alive], Content-Length=[221], content-type=[text/xml; charset=UTF-8], host=[localhost:18080], pragma=[no-cache], SOAPAction=[""], user-agent=[Apache CXF 2.7.7]}
    Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:findEmployees xmlns:ns2="http://cxf.test.com/"><arg0>张三</arg0><arg1></arg1></ns2:findEmployees></soap:Body></soap:Envelope>
    --------------------------------------
      <jaxws:outInterceptors>是输出拦截器,在接口调用完毕的时候被拦截。下面是接口调用完成后的日志输出。
    ---------------------------
    ID: 1
    Encoding: UTF-8
    Content-Type: text/xml
    Headers: {}
    Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:findEmployeesResponse xmlns:ns2="http://cxf.test.com/"><return><user_depart>IT</user_depart><user_name>张三</user_name><user_state>在职</user_state><user_tele></user_tele><user_type>普通员工</user_type></return></ns2:findEmployeesResponse></soap:Body></soap:Envelope>
    --------------------------------------

      我们可以看到基本的实现已经非常详细,甚至能看到一些重要基本的信息。如果这个方法还不能满足你的需求,那么请看后面。

     二、实现AbstractPhaseInterceptor

    import org.apache.cxf.interceptor.Fault;
    import org.apache.cxf.message.Message;
    import org.apache.cxf.phase.AbstractPhaseInterceptor;
    import org.apache.cxf.phase.Phase;
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.UnsupportedEncodingException;
    
    
    public class WebserviceLogInterceptor extends AbstractPhaseInterceptor<Message> {
    
        public WebserviceLogInterceptor(){
            super(Phase.RECEIVE);
        }
    
        @Override
        public void handleMessage(Message message) throws Fault {
            StringBuffer sb = new StringBuffer();
            //这里可以对流做处理,从流中读取数据,然后修改为自己想要的数据
            InputStream is = message.getContent(InputStream.class);
            String encoding = (String)message.get(Message.ENCODING);
            int len = 0;
            byte[] bytes = new byte[1024 * 4];
            try {
                while((len = is.read(bytes))!=-1){
                    sb.append(new String(bytes, 0, len, encoding));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(sb.toString());
          //在这里需要注意一点的是,如果修改后的soap消息格式不符合webservice框架格式,比如:框架封装后的格式为 //<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" <soap:Body> //<这里是调用服务端方法的命名空间><这是参数名称> //这里才是真正的消息 //</这里是调用服务端方法的命名空间></这是参数名称> //</soap:Body> //</soap:Envelope> try { message.setContent(InputStream.class, new ByteArrayInputStream(sb.toString().getBytes(encoding))); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } }

      配置文件添加对应的拦截器。

    <jaxws:endpoint implementor="com.test.cxf.impl.DepartServiceImpl" address="/departService">
            <jaxws:inInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
                <bean class="com.test.interceptor.WebserviceLogInterceptor" />
            </jaxws:inInterceptors>
        </jaxws:endpoint>

      需要注意的是,在处理完数据后,需要在写回到流中,不然接口无法的到参数。

    import org.apache.cxf.helpers.IOUtils;
    import org.apache.cxf.interceptor.Fault;
    import org.apache.cxf.io.CachedOutputStream;
    import org.apache.cxf.message.Message;
    import org.apache.cxf.phase.AbstractPhaseInterceptor;
    import org.apache.cxf.phase.Phase;
    
    import java.io.*;
    
    public class WebserviceLogInterceptor1 extends AbstractPhaseInterceptor<Message> {
    
        public WebserviceLogInterceptor1(){
            super(Phase.PRE_STREAM);
        }
    
        @Override
        public void handleMessage(Message message) throws Fault {
            StringBuffer sb = new StringBuffer();
            OutputStream os = message.getContent(OutputStream.class);
    
            message.setContent(OutputStream.class, new CachedOutputStream());
    
            message.getInterceptorChain().doIntercept(message);
    
            CachedOutputStream csnew = (CachedOutputStream) message.getContent(OutputStream.class);
            try {
                String encoding = (String)message.get(Message.ENCODING);
                InputStream in = csnew.getInputStream();
    
                int len = 0;
                byte[] bytes = new byte[1024 * 4];
                while((len = in.read(bytes))!=-1) {
                    sb.append(new String(bytes, 0, len, encoding));
                }
                System.out.println(sb.toString());
                //这里对xml做处理,处理完后同理,写回流中
                IOUtils.copy(new ByteArrayInputStream(sb.toString().getBytes(encoding)), os);
    
                os.flush();
    
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            message.setContent(OutputStream.class, os);
        }
    }

      同样的,在读取完数据后,仍需要写回到流中,不然调用端得不到结果。

  • 相关阅读:
    C# 串口操作系列(2) -- 入门篇,为什么我的串口程序在关闭串口时候会死锁 ?
    C# 串口操作系列(1) -- 入门篇,一个标准的,简陋的串口例子。
    嵌入式
    [转] Java程序员学C#基本语法两个小时搞定(对比学习)
    test
    LeetCode 【困难】数据库-第1412 :查找成绩处于中游的学生
    LeetCode 【困难】数据库-第1384 :按照年度列出销售总额(每个产品、每年、总销额)
    LeetCode 【困难】数据库-第1369 :获取最近第二次的活动
    LeetCode 【困难】数据库-第1336(超困难):每次访问的交易次数
    LeetCode 【困难】数据库-第1225:报告系统状态的连续日期
  • 原文地址:https://www.cnblogs.com/ginponson/p/5875432.html
Copyright © 2020-2023  润新知