cxf

来源:互联网 发布:js 变量对象 编辑:程序博客网 时间:2024/05/22 06:51

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

maven引用cxf:

<dependency>    <groupId>org.apache.cxf</groupId>    <artifactId>cxf-rt-frontend-jaxws</artifactId>    <version>3.1.3</version></dependency><dependency>    <groupId>org.apache.cxf</groupId>    <artifactId>cxf-rt-transports-http</artifactId>    <version>3.1.3</version></dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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

 <!-- Web Service 配置  cxf -->    <servlet>          <servlet-name>CXFServlet</servlet-name>          <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>          <load-on-startup>1</load-on-startup>      </servlet>      <servlet-mapping>          <servlet-name>CXFServlet</servlet-name>          <url-pattern>/ws/*</url-pattern>      </servlet-mapping> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

服务端发布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;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

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

<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

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

是定义的拦截器

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

public class InMessageInterceptor extends AbstractPhaseInterceptor<Message>{    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);        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

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

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<Header> 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("用户名或密码不正确"));          }      }  }  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

客户端调用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("###", "####", "###"));
  • 1
  • 2
  • 3
  • 4
  • 5

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

接口调用:BISSoapEntryBISInvoke 为接口名称:BISSoapEntryBISInvoke tmsCancelPort = ProxyFactory.getTmsCancelPort(BISSoapEntryBISInvoke.class);ProxyFactory 工具类如下public class ProxyFactory {    public static <T> T getMobile(Class<T> 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> T getPort(Class<T> c, String address) {        return (T) getPort(c, address, null);    }    @SuppressWarnings("unchecked")    private static <T> T getPort(Class<T> 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<Entry<Object, Object>> 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;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130

备注: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<SoapMessage> {    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<Header> 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文档 <authHeader> <userName>zheng</userName>         * <password>1111</password> </authHeader>         */    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

备注: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+端口+通用地址部分相同

    <http:authorization>        <sec:UserName>ims</sec:UserName>        <sec:Password>ims</sec:Password>    </http:authorization>    <http:client AutoRedirect="true" Connection="Keep-Alive" /></http:conduit>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8


http:tlsClientParameters 




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



这里写图片描述