xfire集成spring構建webservice

前言:xfire、spring都是比較流行的技術,這裏就再也不贅述他們各自的優勢;本文着重介紹xfire和spring的整合,不會作太深刻的探究。web

服務端spring

1. web.xml配置瀏覽器

spring配置部分:contextConfigLocation定義配置文件路徑,能夠指定全局的配置文件路徑。tomcat

<!-- spring配置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
           /WEB-INF/xfire-servlet.xml
      </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- spring配置 -->

XFire配置部分:xfire配置1使用spring的DispatcherServlet類來做爲xfire的處理類,DispatcherServlet的配置文件名默認爲[servletname]-servlet,位於WEB-INF目錄下,也能夠經過namespace參數來指定或者經過contextConfigLocation參數自定義配置文檔的位置;這種配置方式只能經過服務名.ws的方式訪問,方便隱藏其它的服務接口;xfire配置2使用xfire的XFireSpringServlet類來做爲xfire的處理類,這種配置方式能夠直接經過接口名訪問,也能夠訪問全部的服務接口。安全

<!-- XFire 配置 1 使用spring的DispatcherServlet做爲xfire的處理類,好處是能夠自定義服務的名稱並隱藏全部提供的其它接口,客戶端只能經過服務名.ws的方式訪問-->
    <servlet>
        <!-- 配合Spring容器中XFire一塊兒工做的Servlet -->
        <servlet-name>xfireServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!-- WebApplicationContext命名空間,默認值是[servlet-name]-servlet,對應DispatcherServlet的定義檔名稱,位於 
                /WEB-INF下,也能夠經過contextConfigLocation參數自定義位置 -->
            <param-name>namespace</param-name>
            <param-value>xfire-servlet</param-value>
        </init-param>
        
        <!-- 經過contextConfigLocation參數自定義位置
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                   /WEB-INF/xfire-servlet.xml
              </param-value>
        </init-param>-->
        
    </servlet>
    <servlet-mapping>
        <servlet-name>xfireServlet</servlet-name>
        <!-- 在這個URI下開放Web Service服務 -->
        <url-pattern>*.ws</url-pattern>
    </servlet-mapping>
    <!-- XFire 配置1 -->
    
    <!-- XFire 配置2 使用xfire的XFireSpringServlet做爲xfire的處理類,能夠直接使用接口類名來訪問開放的服務,也能夠查看全部開發的服務接口 -->
    <servlet>
        <!-- 配合Spring容器中XFire一塊兒工做的Servlet -->
        <servlet-name>xfireServlet2</servlet-name>
        <servlet-class>org.codehaus.xfire.spring.XFireSpringServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>xfireServlet2</servlet-name>
        <!-- 在這個URI下開放Web Service服務 -->
        <url-pattern>/service/*</url-pattern>
    </servlet-mapping>
    <!-- XFire 配置2 -->

2.xfire-servlet配置app

首先須要引入xfire.xml的配置;第二部分用來定義訪問的服務名,若使用XFireSpringServlet做爲servlet時無需此配置,直接經過接口名訪問;第三部分咱們經過XFireExporter將業務類導出爲Web Service,對於任何導出器,咱們都須要引入XFire環境,即serviceFactory和xfire,這是標準的配置。ServiceFactory是XFire的核心類,它能夠將一個POJO生成爲一個Web Service。在本實例中,咱們經過定義一個baseWebService,其他的webService配置都將該bean做爲父bean,這樣能夠簡化Spring的配置,不須要屢次引入serviceFactory和xfire,這其中的inHandlers參數用來定義xfire的SOAP的截取處理類,能夠添加多個,用來完成一些安全驗證等功能;最後一部分用來定義業務接口,他們都須要將baseWebService做爲父bean。this

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

    <import resource="classpath:org/codehaus/xfire/spring/xfire.xml" />

    <!-- 定義訪問的url 使用XFireSpringServlet做爲servlet時無需此配置 -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="urlMap">
            <map>
            
                <entry key="/helloworld.ws">
                    <ref bean="HelloWorldService" />
                </entry>
                
            </map>
        </property>
    </bean>

    <!-- 使用XFire導出器 咱們經過XFireExporter將業務類導出爲Web Service,對於任何導出器,
        咱們都須要引入XFire環境,即serviceFactory和xfire,這是標準的配置。ServiceFactory是
        XFire的核心類,它能夠將一個POJO生成爲一個Web Service。在本實例中,咱們經過定義一個
        baseWebService,其他的webService配置都將該bean做爲父bean,這樣能夠簡化Spring的配置,
        不須要屢次引入serviceFactory和xfire。-->
    <bean id="baseWebService" class="org.codehaus.xfire.spring.remoting.XFireExporter"
        lazy-init="false" abstract="true">
        <!-- 引用xfire.xml中定義的工廠 -->
        <property name="serviceFactory" ref="xfire.serviceFactory" />
        <!-- 引用xfire.xml中的xfire實例 -->
        <property name="xfire" ref="xfire" />
        <!-- 安全驗證 -->
        <property name="inHandlers" ref="AuthenticationHandler"></property>
    </bean>

    <!-- 安全認證 -->
    <bean id="AuthenticationHandler" class="com.AuthenticationHandler"></bean>

    <bean id="HelloWorldServiceImpl" class="com.impl.HelloWorldServiceImp" />
    <bean id="HelloWorldService" parent="baseWebService">
        <!-- 業務服務bean -->
        <property name="serviceBean" ref="HelloWorldServiceImpl" />
        <!-- 業務服務bean的窄接口類 -->
        <property name="serviceClass" value="com.HelloWorldService" />
    </bean>

</beans>

3.AuthenticationHandler安全驗證類url

webservice是一種開放的服務的,但有時候咱們須要控制用戶的訪問,這裏咱們採用handler的方式來截取訪問的SOAP報文來判斷其中是否包含驗證信息,這樣就能夠完成一個簡單的安全校驗;繼承AbstractHandler類實現invoke方法,經過MessageContext獲取請求的報文信息頭中是否包含咱們須要的用戶名、密碼等驗證信息,相應的咱們就須要就客戶端調用時放入這些信息,客戶端驗證類ClientPasswordHandler咱們在下面的客戶端部分介紹。spa

public class AuthenticationHandler extends AbstractHandler {

    public void invoke(MessageContext cfx) throws Exception {
        if (cfx.getInMessage().getHeader() == null) {// 是否有驗證信息
            throw new org.codehaus.xfire.fault.XFireFault("請求必須包含驗證信息",
                    org.codehaus.xfire.fault.XFireFault.SENDER);
        }
        Element token = cfx.getInMessage().getHeader()
                .getChild("AuthenticationToken");// AuthenticationToken爲自定義元素值
        if (token == null) {
            throw new org.codehaus.xfire.fault.XFireFault("請求必須包含身份驗證信息",
                    org.codehaus.xfire.fault.XFireFault.SENDER);
        }
        String username = token.getChild("Username").getValue();
        String password = token.getChild("Password").getValue();
        try {
            // 進行身份驗證 ,只有test@test的用戶爲受權用戶
            if (username.equals("test") && password.equals("test"))
                System.out.println("身份驗證經過");
            else
                throw new Exception();
        } catch (Exception e) {
            throw new org.codehaus.xfire.fault.XFireFault("非法的用戶名和密碼",
                    org.codehaus.xfire.fault.XFireFault.SENDER);
        }
    }

}

四、完整這些配置和接口的類的開發後服務端的工做就完成了,在tomcat中運行這個demo,在瀏覽器中輸入對應的url當出現「Invalid SOAP request.」字樣是表示接口能夠正常訪問了,在url後添加?wsdl能夠得到更詳細的接口信息,以下圖:code

image image image

客戶端

1.ClientPasswordHandler安全驗證類

客戶端安全驗證類也要繼承AbstractHandler類實現invoke方法,以Element的方式構建驗證信息添加到SOAP的報文頭信息中,而後添加這個類到客戶端訪問的服務接口的請求中,就會在被服務端的AuthenticationHandler類截獲完成安全驗證。

public class ClientPasswordHandler extends AbstractHandler {
    private String username = null;
    private String password = null;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public ClientPasswordHandler(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public void invoke(MessageContext context) throws Exception {
        // 爲SOAP Header構造驗證信息
        Element el = new Element("header");//標頭
        context.getOutMessage().setHeader(el);
        Element auth = new Element("AuthenticationToken");//自定義元素
        Element username_el = new Element("Username");
        username_el.addContent(username);
        Element password_el = new Element("Password");
        password_el.addContent(password);
        auth.addContent(username_el);
        auth.addContent(password_el);
        el.addContent(auth);
    }

}

 

二、訪問服務端接口類

GetServiceBean類用來獲取服務端接口對象,添加客戶端驗證類;ClientTest經過調用GetServiceBean獲取服務端接口對象,而後就能夠像使用本地類同樣調用其中的方法了(以下圖),這裏一個顯而易見的要求就是客戶端要保留服務端的接口類、對象類才能完成調用。

public class GetServiceBean {

    private static XFireProxyFactory factory = new XFireProxyFactory();

    public static Object getBean(String serviceUrl, Class<?> serviceClass)
            throws MalformedURLException {
        Service service = new ObjectServiceFactory().create(serviceClass);
        Object object = factory.create(service, serviceUrl);
        Client client = ((XFireProxy) Proxy.getInvocationHandler(object))
                .getClient(); // 獲取訪問服務的客戶端
        client.addOutHandler(new ClientPasswordHandler("test", "test"));// 添加客戶端驗證類
       return object;
    }

}
public class ClientTest {

    public static void main(String[] args) throws Exception {
        HelloWorldService service = (HelloWorldService) GetServiceBean.getBean(
                "http://localhost/xfireserver/helloworld.ws",
                HelloWorldService.class);

        System.out.println(service.hello("小明"));
        Person person = new Person();
        person = service.getPerson();
        System.out
                .println("id:" + person.getId() + " name:" + person.getName());
        List<Person> students = new ArrayList<Person>();
        students = service.getList();
        for (int i = 0; i < students.size(); i++) {
            Person per = students.get(i);
            System.out.println("id:" + per.getId() + " name:" + per.getName());
        }
    }

}

image 

結語:我的理解會有偏駁和不對的地方,歡迎你們批評指正!

demo下載地址:http://pan.baidu.com/s/1eQxRjeM

相關文章
相關標籤/搜索