ssm+cxf3.0

近期需要使用webService,所以看了一下目前比较常用的几个webservie框架,经过比较,最终决定使用能和spring无缝结合的cxf框架。~~从此走上了不归路了

  1. 先上,maven引用,因为好久没有使用ssm框架了,所以直接就上ssm了,当练手了~

  
    3.1.12
  

  
    
      junit
      junit
      3.8.1
      test
    

    
    
      mysql
      mysql-connector-java
      5.1.37
      runtime
    
    
      c3p0
      c3p0
      0.9.1.2
    

    
    
      org.mybatis
      mybatis
      3.3.0
    
    
      org.mybatis
      mybatis-spring
      1.2.3
    
    
    
    
      org.springframework
      spring-core
      4.1.7.RELEASE
    
    
      org.springframework
      spring-beans
      4.1.7.RELEASE
    
    
      org.springframework
      spring-context
      4.1.7.RELEASE
    
    
    
      org.springframework
      spring-jdbc
      4.1.7.RELEASE
    
    
      org.springframework
      spring-tx
      4.1.7.RELEASE
    
    
    
      org.springframework
      spring-web
      4.1.7.RELEASE
    
    
      org.springframework
      spring-webmvc
      4.1.7.RELEASE
    
    
    
      org.apache.cxf
      cxf-rt-frontend-jaxws
      ${cxf.version}
    
    
      org.apache.cxf
      cxf-rt-transports-http
      ${cxf.version}
    
  
  1. 创建spring-dao.xml、mybatis-config.xml、jdbc.properties....反正就是ssm框架那一套,作为本文非主要内容,不做讲解了,主要讲一下cxf的配置——创建spring-cxf.xml



    
    

  
        
        
            
        
       
    



  1. 接下来是web.xml
 
  
    contextConfigLocation
    
    classpath:spring-*.xml
  
  
    org.springframework.web.context.ContextLoaderListener
  


  
  
    seckill-dispatcher
    org.springframework.web.servlet.DispatcherServlet
    
    
      contextConfigLocation
      classpath:spring-*.xml
    
  

  
    seckill-dispatcher
    
    /
  


  
  
    cxf
    org.apache.cxf.transport.servlet.CXFServlet
  
  
    cxf
    /ws/*
  
  1. 紧接着是要创建将要发布的接口和类
@WebService
@MTOM  //开启MTOM功能之后,能够发送文件信息
public interface BaseService {
    
     String sayHello(@XmlMimeType(value = "application/octet-stream") DataHandler name);
     //@XmlMimeType(value = "application/octet-stream")如果发送文件,这个是死格式,而且必须声明
}
  1. 然后是实现它,这个地方有个坑,就是如果你想传入文件进来,那么必须用InputStream.read(byte[] b)的方式获取文件,不然文件就是乱码(猜想了一下,因为cxf传输文件的类型必须是DataHandler,而这个类型是byte数组的),还有一个坑,就是必须把targetNamespace给写出来,value是类所在包名反过来(这个没怎么懂必须要这样的目的,暂时先按照教程来吧)
@WebService(endpointInterface="com.ssm.service.BaseService",targetNamespace="http://service.ssm.com/")
public class BaseServiceImpl implements BaseService {
   

    public String sayHello(DataHandler name) {
        InputStream sn = null;
        OutputStream bw = null;
        try{
            bw = new FileOutputStream("d:/dsd.jpg");
            sn = name.getInputStream();

            byte[] bytes = new byte[1024];
            int i=-1;
            while ((i=sn.read(bytes))!=-1){
                bw.write(bytes,0,i);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                sn.close();
                bw.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        return "ok";
    }


}

  1. 好了,这就是最简单的cxf服务端配置方式了,装上tomcat测试一下看看有没有发布成功吧

路径: http://localhost:9090/ws/business?wsdl

简单的说一下路径为什么是这个,前面的就不说了,主要说说为什么是/ws,这个实在web.xml中定义的,在servlet-mapping中的url上,/business就是在spring-cxf.xml中定义的了,在发布时定义的——jaxws:endpoint的address指定了url最终路径。

  1. 简单的创建一个客户端访问一下吧(采用JaxWsDynamicClientFactory的方式访问,有点和服务端完全解耦,不依靠服务端的任何文件)
  JaxWsDynamicClientFactory dynamicClient = JaxWsDynamicClientFactory.newInstance();
        Client client = dynamicClient.createClient("http://localhost:9090/ws/business?wsdl");


        DataHandler dataHandler = new DataHandler( new FileDataSource(new File("98226cffc175d.jpg")));

        Object[] o = client.invoke("sayHello",dataHandler);

一下为加入账号密码验证

  1. 服务端现在加入账号验证(在接受时拦截,查看账号密码,匹配)
import java.util.List;

import javax.xml.soap.SOAPException;

import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class AuthIntercetpr extends  AbstractPhaseInterceptor {
    private static final String USERNAME="root";
    private static final String PASSWORD="admin";

    public AuthIntercetpr() {
        //定义在哪个阶段进行拦截
        super(Phase.PRE_PROTOCOL);
    }



    public void handleMessage(SoapMessage soapMessage) throws Fault {
        List
headers = null; String username=null; String password=null; try { headers = soapMessage.getHeaders(); } catch (Exception e) { } if (headers == null) { throw new Fault(new IllegalArgumentException("找不到Header,无法验证用户信息")); } //获取用户名,密码 for (Header header : headers) { SoapHeader soapHeader = (SoapHeader) header; Element e = (Element) soapHeader.getObject(); NodeList usernameNode = e.getElementsByTagName("username"); NodeList pwdNode = e.getElementsByTagName("password"); username=usernameNode.item(0).getTextContent(); password=pwdNode.item(0).getTextContent(); if( StringUtils.isEmpty(username)||StringUtils.isEmpty(password)){ throw new Fault(new IllegalArgumentException("用户信息为空")); } } //校验用户名密码 if(!(username.equals(USERNAME) && password.equals(PASSWORD))){ SOAPException soapExc = new SOAPException("认证失败"); throw new Fault(soapExc); } } }
  1. spring-cxf.xml修改为

    
    
      
        
        
            
        
      
            
        
        
    
  1. 客户端也要加入拦截器
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.namespace.QName;
import java.util.List;

public class LoginInterceptor extends AbstractPhaseInterceptor {
    private String username="root";
    private String password="admin";
    public LoginInterceptor(String username, String password) {
        //设置在发送请求前阶段进行拦截
        super(Phase.PREPARE_SEND);
        this.username=username;
        this.password=password;
    }

    @Override
    public void handleMessage(SoapMessage soapMessage) throws Fault {
        List
headers = soapMessage.getHeaders(); Document doc = DOMUtils.createDocument(); Element auth = doc.createElementNS("http://service.ssm.com/","SecurityHeader"); Element UserName = doc.createElement("username"); Element UserPass = doc.createElement("password"); UserName.setTextContent(username); UserPass.setTextContent(password); auth.appendChild(UserName); auth.appendChild(UserPass); headers.add(new Header(new QName("SecurityHeader"),auth)); } }
  1. 在请求时加入拦截器
  JaxWsDynamicClientFactory dynamicClient = JaxWsDynamicClientFactory.newInstance();
        Client client = dynamicClient.createClient("http://localhost:9090/ws/business?wsdl");

        //加入拦截器
        client.getOutInterceptors().add(new LoginInterceptor("root","admin"));

        DataHandler dataHandler = new DataHandler(
                new FileDataSource(new File("C:\\Users\\lht\\Desktop\\a\\a.jpg")));
        Object[] o = client.invoke("sayHello",dataHandler);
        System.out.println();

留下点问题,看看等什么时候去研究一下

  1. 因为这个还是传统的SOAP方式,什么时候看一下REST风格WebService,据说很厉害的样子
  2. ...

你可能感兴趣的:(ssm+cxf3.0)