1. 程式人生 > >CXF2.7整合spring發布webservice

CXF2.7整合spring發布webservice

localhost 掃描 接口 eclips mpls welcom 而且 icc 框架

---------==========--服務端發布webservice-=============--------

1.需要的jar包:

技術分享圖片

2.包結構

技術分享圖片

3.代碼

1.實體類

package cn.qlq.domain;

public class User {

    private String username;
    private String password;

    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; } @Override public String toString() { return
"User [username=" + username + ", password=" + password + "]"; } }

2.dao代碼:

package cn.qlq.dao;

import java.sql.SQLException;

import cn.qlq.domain.User;

public interface UserDao {
    /**
     * 保存用戶
     * 
     * @param user
     * @return
     * @throws SQLException
     
*/ public int saveUser(User user) throws SQLException; /** * 根據userId獲取user * * @param userId * @return */ public User getUserById(int userId); }

package cn.qlq.dao.impl;

import java.sql.SQLException;

import org.springframework.stereotype.Repository;

import cn.qlq.dao.UserDao;
import cn.qlq.domain.User;

@Repository
public class UserDaoImpl implements UserDao {

    public UserDaoImpl(){
        System.out.println("=====生成userDao=====");
    }
    
    @Override
    public int saveUser(User user) throws SQLException {
        System.out.println("保存用戶");
        return 0;
    }

    @Override
    public User getUserById(int userId) {
        // 模擬從數據庫取數據
        User u = new User();
        u.setUsername("qlq");
        u.setPassword("123456");
        return u;
    }

}

3.service代碼:

package cn.qlq.service;

import java.sql.SQLException;

import javax.jws.WebMethod;
import javax.jws.WebService;

import cn.qlq.domain.User;

@WebService
public interface UserService {
    /**
     * 保存用戶
     * 
     * @param user
     * @return
     * @throws SQLException
     */
    public int saveUser(User user) throws SQLException;

    /**
     * 根據userId獲取user
     * 
     * @param userId
     * @return
     */
    @WebMethod
    public User getUserById(int userId);
}

package cn.qlq.service.impl;

import java.sql.SQLException;

import javax.jws.WebService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.qlq.dao.UserDao;
import cn.qlq.domain.User;
import cn.qlq.service.UserService;

@Service
@WebService
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public int saveUser(User user) throws SQLException {
        System.out.println("----------------保存user----------");
        return 0;
    }

    @Override
    public User getUserById(int userId) {
        return userDao.getUserById(userId);
    }

}

4.配置文件

application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/jaxws http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">


    <!-- 引cxf的一些核心配置 -->
    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

    <!-- 自動掃描dao和service包(自動註入) -->
    <context:component-scan base-package="cn.qlq" />

    <jaxws:endpoint id="userWS" implementor="cn.qlq.service.impl.UserServiceImpl"
        address="/userws">
    </jaxws:endpoint>

</beans>

經測試:上面的import不需要也是可以的。

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>CXFTest</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <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>
</web-app>

5.啟動服務進行測試:

技術分享圖片

=========客戶端使用webservice:============

  無論哪種方式調用都會調用到發布的webservice的實現類的代碼(項目中的代碼)。也就是必須依賴tomcat服務器啟動才能訪問webservice的實現代碼,如果tomcat沒啟動將訪問不到wsdl。並且會報訪問不到wsdl與連接拒絕的錯誤。

  訪問方式基本上有三種,生成本地代碼、靜態代理、動態代理。

1.利用JDK自帶的工具生成代碼到本地的方式進行(不依賴於CXF框架)

C:\Users\liqiang\Desktop>cd webservice


C:\Users\liqiang\Desktop\webservice>wsimport http://localhost/CXFTest/WS/userws?
parsing WSDL...



Generating code...


Compiling code...

會將代碼生成到本地,如下:

技術分享圖片

打成jar包後使用:

C:\Users\liqiang\Desktop\webservice>jar cvf wstest.jar ./
已添加清單
正在添加: cn/(輸入 = 0) (輸出 = 0)(存儲了 0%)
正在添加: cn/qlq/(輸入 = 0) (輸出 = 0)(存儲了 0%)
正在添加: cn/qlq/service/(輸入 = 0) (輸出 = 0)(存儲了 0%)
正在添加: cn/qlq/service/GetUserById.class(輸入 = 605) (輸出 = 376)(壓縮了 37%)
正在添加: cn/qlq/service/GetUserByIdResponse.class(輸入 = 763) (輸出 = 424)(壓縮了 44%)
正在添加: cn/qlq/service/impl/(輸入 = 0) (輸出 = 0)(存儲了 0%)
正在添加: cn/qlq/service/impl/SQLException.class(輸入 = 788) (輸出 = 422)(壓縮了 46%)
正在添加: cn/qlq/service/impl/UserService.class(輸入 = 1050) (輸出 = 507)(壓縮了 51%)
正在添加: cn/qlq/service/impl/UserServiceImplService.class(輸入 = 2369) (輸出 = 1050)(壓縮了
正在添加: cn/qlq/service/ObjectFactory.class(輸入 = 3124) (輸出 = 1009)(壓縮了 67%)
正在添加: cn/qlq/service/package-info.class(輸入 = 242) (輸出 = 195)(壓縮了 19%)
正在添加: cn/qlq/service/SaveUser.class(輸入 = 656) (輸出 = 384)(壓縮了 41%)
正在添加: cn/qlq/service/SaveUserResponse.class(輸入 = 694) (輸出 = 411)(壓縮了 40%)
正在添加: cn/qlq/service/SQLException.class(輸入 = 1036) (輸出 = 525)(壓縮了 49%)
正在添加: cn/qlq/service/User.class(輸入 = 798) (輸出 = 434)(壓縮了 45%)

導入eclipse中測試:

技術分享圖片

測試代碼:

import cn.qlq.service.User;
import cn.qlq.service.impl.UserService;
import cn.qlq.service.impl.UserServiceImplService;

public class TestWS {

    public static void main(String[] args) {
        UserServiceImplService us = new UserServiceImplService();
        UserService userService = us.getUserServiceImplPort();
        User user = userService.getUserById(0);
        System.out.println(user.getUsername()+"\t"+user.getPassword());
    }
    
}

結果:

qlq 123456

2.第二種方式:靜態代理:(依賴於CXF框架,而且需要將接口寫在對應包下---與webservice保持一致)

目錄結構:

技術分享圖片

jar包:

技術分享圖片

測試類:

import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import cn.qlq.domain.User;
import cn.qlq.service.UserService;

public class TestWS {

    public static void main(String[] args) throws Exception {
        // 創建WebService客戶端代理工廠
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        // 判斷是否拋出異常
        factory.getOutInterceptors().add(new LoggingInInterceptor());
        // 註冊webservice接口
        factory.setServiceClass(UserService.class);
        // 配置webservice地址
        factory.setAddress("http://localhost/CXFTest/WS/userws?wsdl");
        // 獲得接口對象
        UserService service = (UserService) factory.create();
        // 調用接口方法
        User user = service.getUserById(5);
        // 關閉接口連接
        System.out.println(user.getUsername() + "\t" + user.getPassword());
    }

}

結果:

qlq 123456

3.動態調用:(推薦這種)

import javax.xml.namespace.QName;

import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

public class TestWS {

    public static void main(String[] args) throws Exception {

        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();

        org.apache.cxf.endpoint.Client client = dcf.createClient("http://localhost/CXFTest/WS/userws?wsdl"); // url為調用webService的wsdl地址

        QName name = new QName("http://service.qlq.cn/", "getUserById");// namespace是命名空間,methodName是方法名

        int userId = 1;

        Object[] objects;
        try {
            objects = client.invoke(name, userId);// 第一個參數是上面的QName,第二個開始為參數,可變數組
            System.out.println(objects[0].toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

} 

參數解釋:

技術分享圖片

註意:如果上面報錯:

  org.apache.cxf.common.i18n.UncheckedException: No operation was found with the name

我們需要將targetNamespace和namespace保持一致,如下:

技術分享圖片

我們需要將實現類和接口放在同一個包下,或者對服務端的接口實現類中的@WebService添加targetNamespace,其值為接口包名的倒置,例如上面我的配置為:

package cn.qlq.service.impl;

import java.sql.SQLException;

import javax.jws.WebService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.qlq.dao.UserDao;
import cn.qlq.domain.User;
import cn.qlq.service.UserService;

@Service
@WebService(targetNamespace = "http://service.qlq.cn")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public int saveUser(User user) throws SQLException {
        System.out.println("----------------保存user----------");
        return 0;
    }

    @Override
    public User getUserById(int userId) {
        System.out.println("----------------獲取user----------" + userId);
        return userDao.getUserById(userId);
    }

}

結果:

技術分享圖片

  至此webservice的發布與使用基本完成,明天還會在項目中實際發布webservice,以及測試webservice類改變運用上面三種方式訪問webservice的結果。

CXF2.7整合spring發布webservice