CXF

webservice测试工具-SoapUi

Apache CXF 是一个开源的 Services 框架,CXF 帮助您利用 Frontend 编程 API 来构建和开发 Services .

maven引用cxf:

<dependency>
    <groupId>org.apache.cxfgroupId>
    <artifactId>cxf-rt-frontend-jaxwsartifactId>
    <version>3.1.3version>
dependency>
<dependency>
    <groupId>org.apache.cxfgroupId>
    <artifactId>cxf-rt-transports-httpartifactId>
    <version>3.1.3version>
dependency>

启用cxf,web.xml文件中添加配置如下:
备注:webservice访问路径为:项目访问地址/ws/地址

 
    <servlet>  
        <servlet-name>CXFServletservlet-name>  
        <servlet-class>org.apache.cxf.transport.servlet.CXFServletservlet-class>  
        <load-on-startup>1load-on-startup>  
    servlet>  
    <servlet-mapping>  
        <servlet-name>CXFServletservlet-name>  
        <url-pattern>/ws/*url-pattern>  
    servlet-mapping> 

服务端发布webservice接口相关知识如下:

webservice接口(主要使用注解),示例代码如下:

接口(interface)
@WebService(targetNamespace = "urn:sinopec:ecc:fi:tmsno:fx")
public interface TmsImsWebService {

    @WebMethod(operationName = "MT_TMS_ECC_FI_TMSYXNO")
    public String tmsNo(@WebParam(name = "TmsYxNo") String tmsNo, @WebParam(name = "CODE") String compCode,
            @WebParam(name = "YWRQ") String ywrq);
}

接口实现:

@WebService(endpointInterface = "com.pcitc.cbs.webService.TmsImsWebService", targetNamespace = "urn:sinopec:ecc:fi:tmsno:fx")
public class TmsImsWebServiceImpl implements TmsImsWebService {

    @Autowired
    private TmsConfirmRemainService tmsRemain;

    @Override
    public String tmsNo(String tmsNo, String compCode, String ywrq) {
        String sss = tmsRemain.getTmsStrNo(tmsNo, compCode, ywrq);
        return sss;
    }

}

定义接口之后需要发布接口:配置文件如下

<bean id="TmsImsWebServiceImpl" class="com.pcitc.cbs.webService.impl.TmsImsWebServiceImpl">
    bean>
    <jaxws:endpoint id="TmsImsWebService" implementor="#TmsImsWebServiceImpl"
        address="/tmsImsNo">
        <jaxws:inInterceptors>
            <ref bean="InMessageInterceptor" />
        jaxws:inInterceptors>
    jaxws:endpoint>

另一种发布方式:

<jaxws:server id="TmsImsWebService" address="/tmsImsNo"
        serviceClass="com.pcitc.cbs.webService.TmsImsWebService">
        <jaxws:serviceBean>
            <bean class="com.pcitc.cbs.webService.impl.TmsImsWebServiceImpl" />
        jaxws:serviceBean>
        <jaxws:inInterceptors>
            <ref bean="InMessageInterceptor" />
        jaxws:inInterceptors>
    jaxws:server>

备注:接口真正调用地址:
http://localhost:8080/fsscbs/ws/tmsImsNo
浏览器访问时因接口协议访问地址需加上后缀如下:
http://localhost:8080/fsscbs/ws/tmsImsNo?wsdl
其中

是定义的拦截器

webservice拦截器:
继承:AbstractPhaseInterceptor message有好多种

public class InMessageInterceptor extends AbstractPhaseInterceptor{

    protected Logger log;

    public InMessageInterceptor(){

        this(Phase.RECEIVE, InMessageInterceptor.class.getName());
    }

    public InMessageInterceptor(String logName){

        this(Phase.RECEIVE, logName); 
    }

    protected InMessageInterceptor(String phase, String logName)
    {
        super(phase); 
        log = Logger.getLogger(logName);
    }

    protected String modifyMessage(String message)
    {
        return message;
    }

    public void handleMessage(Message message) {
        try { 

            String serviceName="";
            Exchange exchange = message.getExchange(); 

            if(exchange!=null && exchange.getService()!=null)
                serviceName = exchange.getService().getName().toString();

            log.info("Service = " + serviceName);

            InputStream is = message.getContent(InputStream.class);  
            String encode = (String) message.get(Message.ENCODING);  
            String xml = IOUtils.toString(is, encode);    

            if (log.isInfoEnabled()) {  
                log.info("Service = " + serviceName + ", soap message = " + xml); 
            }

            xml = modifyMessage(xml);

            message.setContent(InputStream.class, new ByteArrayInputStream(xml.getBytes(encode)));  

        } 

        catch (Exception e) {
            if (log.isEnabledFor(Level.DEBUG))
                log.error("Error when split original inputStream. CausedBy : " + "\n" + e);
        }
    }
}

增加安全校验使用拦截器:

public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {  

    public AuthInterceptor() {  
        super(Phase.PRE_INVOKE); //拦截器在调用方法之前拦截SOAP消息  
    }  

    // 拦截器操作  
    @Override  
    public void handleMessage(SoapMessage msg) throws Fault {  
        System.out.println("come to auth interceptor...");  
        //获取SOAP消息的所有Header  
        List
headers = msg.getHeaders(); if(headers == null || headers.size() < 1) { throw new Fault(new IllegalArgumentException("没有Header,拦截器实施拦截")); } //获取Header携带是用户和密码信息 Header firstHeader = headers.get(0); Element element = (Element) firstHeader.getObject(); NodeList userNameElement = element.getElementsByTagName("userName"); NodeList passwordElement = element.getElementsByTagName("password"); if (userNameElement.getLength() != 1) { throw new Fault(new IllegalArgumentException("用户名格式不对")); } if (passwordElement.getLength() != 1) { throw new Fault(new IllegalArgumentException("用户密码格式不对")); } //获取元素的文本内容 String userName = userNameElement.item(0).getTextContent(); String password = passwordElement.item(0).getTextContent(); // 实际项目中, 应该去查询数据库, 该用户名,密码是否被授权调用该webservice if (!userName.equals("zheng") || !password.equals("123456")) { throw new Fault(new IllegalArgumentException("用户名或密码不正确")); } } }

客户端调用webservice接口相关知识如下:
使用jdk或者saopui生成客户端代码。
调用接口客户端代码如下:

JaxWsProxyFactoryBean svr = new JaxWsProxyFactoryBean();
        svr.setServiceClass(TmsImsWebService.class);
        svr.setAddress("http://localhost:8080/fsscbs/ws/tmsImsNo");
        TmsImsWebService hw = (TmsImsWebService) svr.create();
        System.out.println(hw.mtTMSECCFITMSYXNO("###", "####", "###"));

备注:上述代码可考虑写静态方法作为工具类使用,调用接口时调用工具类即可

接口调用:BISSoapEntryBISInvoke 为接口名称:
BISSoapEntryBISInvoke tmsCancelPort = ProxyFactory.getTmsCancelPort(BISSoapEntryBISInvoke.class);

ProxyFactory 工具类如下

public class ProxyFactory {

    public static  T getMobile(Class c) {
        String address = getAddress("Mobile_Url");
//      OutMessageInterceptor i = new OutMessageInterceptor();
        return getPort(c, address, null);
    }

    public static String getAddress(String propertyName) {
        PropertiesUtil util = new PropertiesUtil("cxf.properties");
        String address = util.getValue(propertyName);
        return address;
    }

    @SuppressWarnings("unused")
    private static String getAddress(String path, String propertyName) {
        PropertiesUtil util = new PropertiesUtil(path);
        String address = util.getValue(propertyName);
        return address;
    }

    // 获取WebService接口
    public static  T getPort(Class c, String address) {
        return (T) getPort(c, address, null);

    }

    @SuppressWarnings("unchecked")
    private static  T getPort(Class c, String address, Interceptor interceptor) {
        JaxWsProxyFactoryBean soapFactoryBean = new JaxWsProxyFactoryBean();
        soapFactoryBean.setAddress(address);
        soapFactoryBean.setServiceClass(c);
        if (interceptor != null) {
            if (interceptor instanceof OutMessageInterceptor) {
                soapFactoryBean.getOutInterceptors().add(interceptor);
            }

            if (interceptor instanceof InMessageInterceptor) {
                soapFactoryBean.getInInterceptors().add(interceptor);
            }
        }
        return (T) soapFactoryBean.create();

    }
}

PropertiesUtil 工具类操作properties文件:
package com.guo.hui.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

public class PropertiesUtil {

    private String fileName;

    public PropertiesUtil(String fileName) {
        this.fileName = fileName;
    }

    /**
     * 获得数据库配置信息
     * 
     * @return
     * @throws IOException
     */
    private Properties loadProperties() throws IOException {
        Properties p = null;
        InputStream inputStream = null;
        try {
            p = new Properties();
            Resource resource = new ClassPathResource(this.fileName);
            inputStream = resource.getInputStream();
            p.load(inputStream);
        } catch (IOException e) {
            if (inputStream != null) {
                inputStream.close();
            }
            throw e;
        }
        return p;
    }

    private Properties properties;

    // 获取值
    public String getValue(String key) {
        if (properties == null) {
            try {
                properties = this.loadProperties();
            } catch (IOException e) {
                System.out.print(e.getMessage());
            }
        }
        if (properties != null) {
            return properties.getProperty(key);
        }
        return null;
    }

    public Set> getData() {
        if (properties == null) {
            try {
                properties = this.loadProperties();
            } catch (IOException e) {
                System.out.print(e.getMessage());
            }
        }
        if (properties != null) {

            return properties.entrySet();
            // return properties.getProperty(key);
        }

        return null;
    }

}

备注:String address = getAddress(“TMS_Status_ServiceUrl”);

TMS_Status_ServiceUrl是读取配置文件(properties)地址:
TMS_Status_ServiceUrl={webserviceroot}/webservices/##{webserviceroot} el表达式去maven项目pom文件中的地址,是接口能适应不同运行环境(生产,预生产,测试等)
pom中的配置:IP+端口+通用地址部分
http://IP:port/#

客户端可设置拦截器,记录日志或者增加用户密码,示例代码如下:

import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.hpzc.model.exception.BizException; //自定义异常类


public class AddHeaderInterceptor extends AbstractPhaseInterceptor {

    private String userName;
    private String password;

    public AddHeaderInterceptor(String userName, String password) {
        super(Phase.PREPARE_SEND);
        this.userName = userName;
        this.password = password;
    }

    @Override
    public void handleMessage(SoapMessage msg) throws BizException {

        List
headers = msg.getHeaders(); // 创建Document对象 Document document = DOMUtils.createDocument(); Element element = document.createElement("authHeader"); // 配置服务器端Head信息的用户密码 Element userNameElement = document.createElement("userName"); userNameElement.setTextContent(userName); System.out.println(userNameElement.getElementsByTagName("userName")); Element passwordElement = document.createElement("password"); passwordElement.setTextContent(password); element.appendChild(userNameElement); element.appendChild(passwordElement); headers.add(new Header(new QName(""), element)); /** * 生成的XML文档 zheng * 1111 */ } }

备注:userNameElement.setTextContent(userName);
passwordElement.setTextContent(password); 可能会报错.报错可能原因是xml-api.jar包冲突.

org.w3c.dom.Element 缺少 setTextContent 方法
  org.w3c.dom.Element没有setTextContent方法 的编译错。
  主要是 xercesImpl.jar 和 xml-apis.jar的Element版本太老造成的,setTextContent是DOM3中的方法。
  但在pom文件中,未发现有直接引用这两个jar包的地方。好在eclipse maven插件功能强大,在Project Explorer的Maven Dependencies中
  找到了xml-api.jar,然后右键->Maven->Exclude Maven artifact,弹出窗口,提示会在当前pom文件中的hibernate-core依赖中,排除掉
  xml-api.jar,确认后,pom文件被修改,更新Maven Dependencies,重新编译,问题解决

假设访问接口时增加了http校验也就是访问接口时先验证则可以增加如下配置,通过验证。
cxf配置文件中增加如下配置,可以增加用户/密码
配置文件增加验证:pom中的配置:IP+端口+通用地址部分相同

    
        ims
        ims
    
    



http:tlsClientParameters




._EXPORT_.
._EXPORT1024_.
._WITH_DES_.
._WITH_AES_.
._WITH_NULL_.
._DH_anon_.



CXF_第1张图片

你可能感兴趣的:(cxf)