一次Spring Refactoring实战

用CXF作了一个调用AXL Web Services的Demo,
现在需要把它放到我的Web Application里面,最快的方法当然是Spring Inject.
于是很bt的try了一把spring Refactoring.
 
说起来其实CXF本身对Spring的支持就非常的好。
基于Spring扩展的cxf.xml,基于Spring的FactoryBean和Client.
可要命的是AXL的Web Services并不标准。
一个定制HTTP认证头的Interceptor,一个定制的TrustManager,把美观的cxf.xml弄得一无是处。
加上之前CXF菜鸟,只是照葫芦画瓢,这些因为都导致了这次refactoring的艰辛。。。(-,-,铺陈铺陈)
 
原始的Code

public class AXLClient
   public static void main(String[] args) throws Exception {
        URL wsdlUrl = AXLClient.class.getResource("AXLAPI.wsdl");
        QName SERVICE_NAME = new QName("http://www.cisco.com/AXLAPIService/", "AXLAPIService");
        Service service = Service.create(wsdlUrl, SERVICE_NAME);
        AXLPort port = service.getPort(AXLPort.class);
        BindingProvider provider = (BindingProvider) port;
        Map<String, Object> reqContext = provider.getRequestContext();
        reqContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://IPAddress:8443/axl/");
        Client client = ClientProxy.getClient(port);
        client.getOutInterceptors().add(new AXLInterceptor());
        //set SSL
        HTTPConduit http = (HTTPConduit) client.getConduit();
        TLSClientParameters  tls = new TLSClientParameters();
        tls.setDisableCNCheck(true);
        tls.setTrustManagers(new TrustManager[]{new MyTrustManager()});
        http.setTlsClientParameters(tls);
        HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
        httpClientPolicy.setAllowChunking(false);
        http.setClient(httpClientPolicy);
        GetPhoneReq req = new GetPhoneReq();
        req.setPhoneName("SEPXXXXXXXXX");
        System.out.println(port.getPhone(req));
    }
}

step 1
将"SEPXXXXXXXXX"替换为String ID
将public static void main() 修改为public voice getPhone(String ID);
然后Spring就可以注入了
<bean id="AXLClient" class="…"/>
娃哈哈,最后技术含量的就是这步了。。。
 
step 2
Spring的真髓就是IoC,"No new,All is injected"
于是有了这样四个Attributes
 private AbstractPhaseInterceptor<Message> authInterceptor;
 private TrustManager[] trustManagers;
 private Resource axlWsdl;
 private AXLPort axlPort;
 <bean id="axlService" class="com.cisco.twitter.axl.AXLServiceImpl">
  <property name="axlPort" ref="axlPort"/>
  <property name="axlWsdl"  value="classpath:AXLAPI.wsdl"/>
  <property name="authInterceptor"  ref="authInterceptor"/>
  <property name="trustManagers" >
   <list>
    <bean id="defaultTrustManager" class="com.cisco.twitter.axl.DefaultTrustManager"/>
   </list>
  </constructor-arg>
 </bean>
其中需要提到的是Spring的Resource真的很好用,直接classpath:XXX就可以调用我需要的资源文件了,方便一个字。
 
Step 3
其实这步应该水到渠成的。
CXF本来就支持Spring的配置集成。形如:
<bean id="axlPort" class="com.cisco.twitter.axl.model.AXLPort"
   factory-bean="axlClientFactory" factory-method="create"/>
   
 <bean id="axlClientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
   <property name="serviceClass" value="com.cisco.twitter.axl.model.AXLPort"/>
   <property name="address" value="https://100.100.3.71:8443/axl/"/>
 </bean>
通过JaxWsProxyFactoryBean这个工厂类,可以方便的生成Client类。
可是由于我一开始的实现是胡乱拼凑的,所以根本不知道这里Factory,Client最硬的是我Code中的哪个部分。
所以绕了很多弯路。
最后发现“Client client = ClientProxy.getClient(port);”以上的code都可以通过上面的Code取代。
 
Step5
//set SSL
HTTPConduit http = (HTTPConduit) client.getConduit();

TLSClientParameters  tls = new TLSClientParameters();
tls.setDisableCNCheck(true);
tls.setTrustManagers(new TrustManager[]{new MyTrustManager()});
http.setTlsClientParameters(tls);
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setAllowChunking(false);
http.setClient(httpClientPolicy);
 
Spring中的实例默认是Singleton的。
以上的Code是对Request的定制,只需要执行一次就可以了。
于是可以把这段code放在构造函数中。
相应的修改是把Spring配置中的property修改成constructor-arg
因为构造函数需要其中的属性。
 
Step6
建立接口,好习惯,要保持。
public interface AXLService {
 public String getDeviceIdByPhoneNumber(String phoneNumber);
}
 
最后的结果

public interface AXLService {
 /**
  *
  * @param phoneNumber
  * @return
  */
 public String getDeviceIdByPhoneNumber(String phoneNumber);
}
public class AXLServiceImpl implements AXLService {
 private AbstractPhaseInterceptor<Message> authInterceptor;
 private TrustManager[] trustManagers;
 private Resource axlWsdl;
 private AXLPort axlPort;
    protected final Log log = LogFactory.getLog(getClass());
 
 public AXLServiceImpl(AXLPort axlPort,Resource axlWsdl,
   AbstractPhaseInterceptor<Message> authInterceptor,
   TrustManager[] trustManagers){
  this.axlPort = axlPort;
  this.axlWsdl = axlWsdl;
  this.authInterceptor = authInterceptor;
  this.trustManagers = trustManagers;
  
  Client client = ClientProxy.getClient(axlPort);
        //set the auth string
        client.getOutInterceptors().add(this.authInterceptor);
        //set the own trustManager
        HTTPConduit http = (HTTPConduit) client.getConduit();
        TLSClientParameters  tls = new TLSClientParameters();
        tls.setDisableCNCheck(true);
        tls.setTrustManagers(this.trustManagers);
        http.setTlsClientParameters(tls);
        HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
        //set the content-length
        httpClientPolicy.setAllowChunking(false);
        http.setClient(httpClientPolicy);
  
 }
    /**
     * @param args the command line arguments
     */
    public String getDeviceIdByPhoneNumber (String phoneNumber) {
        ExecuteSQLQueryReq req = new ExecuteSQLQueryReq();
        req.setSql("select d.name from device d,devicenumplanmap m, numplan n "+
          "where d.pkid = m.fkdevice and m.fknumplan=n.pkid and n.dnorpattern=’"+
          phoneNumber+"’");
        try{
         ExecuteSQLQueryRes result = axlPort.executeSQLQuery(req);
         //the only user of the line
         if (result.getReturn().getRow().size() == 1 ){
          return ((Row)result.getReturn().getRow().get(0)).getName();
         }
         return null;
        }
        catch(SOAPFaultException e){
         log.warn("Failed to connect Call Manager." + e);
         return null;
        }
    }
}
<bean id="authInterceptor" class="com.cisco.twitter.axl.AuthInterceptor">
  <property name="ccmuser" value="ccmadmin"/>
  <property name="password" value="ipcbuadmin"/>
 </bean>
 <bean id="axlPort" class="com.cisco.twitter.axl.model.AXLPort"
   factory-bean="axlClientFactory" factory-method="create"/>
   
 <bean id="axlClientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
   <property name="serviceClass" value="com.cisco.twitter.axl.model.AXLPort"/>
   <property name="address" value="https://XXXX:8443/axl/"/>
 </bean>
 
 <bean id="axlService" class="com.cisco.twitter.axl.AXLServiceImpl">
  <constructor-arg index="0" ref="axlPort"/>
  <constructor-arg index="1" value="classpath:AXLAPI.wsdl"/>
  <constructor-arg index="2" ref="authInterceptor"/>
  <constructor-arg index="3">
   <list>
    <bean id="defaultTrustManager" class="com.cisco.twitter.axl.DefaultTrustManager"/>
   </list>
  </constructor-arg>
 </bean>


 



Tags: Java, refactoring, spring

无觅相关文章插件,快速提升流量