Webservice使用xfire发布及客户端调用

来源:互联网 发布:不需要网络的电脑游戏 编辑:程序博客网 时间:2024/05/16 09:38

 
             这几天研究了一下WebService的发布及调用,没做之前觉得挺难得,还好项目中有这样的实例自己学着做了一个使用Xfire发布并在另一个项目中调用,感觉做成了还是挺有成就感的,下面记录下实现的步骤有需要的同学可以试一下,也为自己以后使用留个备份。

第一步:先建立一个发布WebService的项目(项目使用SpringMvc架构搭建一个环境):

项目目录结构如下图所示

 

 

 

主要使用的类有,User.java,Tree.java,UserService.java,UserServiceImpl.java

下面将代码文件附上:

 

public class User {private String id;private String userName;private String password;private int age;private String sex;public User() {}public User(String id, String userName, String password, int age, String sex) {this.id = id;this.userName = userName;this.password = password;this.age = age;this.sex = sex;}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 int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getId() {return id;}public void setId(String id) {this.id = id;}@Overridepublic String toString() {return "User [id=" + id + ", userName=" + userName + ", password="+ password + ", age=" + age + ", sex=" + sex + "]";}}

 

 

public class Tree {private String id;private String childNode;private String treeName;public Tree(String id, String childNode, String treeName) {this.id = id;this.childNode = childNode;this.treeName = treeName;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getChildNode() {return childNode;}public void setChildNode(String childNode) {this.childNode = childNode;}public String getTreeName() {return treeName;}public void setTreeName(String treeName) {this.treeName = treeName;}}

 UserService接口,也就是我们要暴露出来的类供其他项目访问的。

public interface UserService {public String getUserByUserName(String userName);public String getTreeByTreeId(String id);public String selectUserById(String id);}

 实现类代码如下,我这里为了方便测试没有返回XML格式的字符串了,项目中一般返回的都是XML格式的数据到本地后在使用dom方式解析XML得到我们需要的数据。

@Servicepublic class UserServiceImpl implements UserService {@Overridepublic String getUserByUserName(String userName) {User user = new User("1", userName, "111111", 24, "女");return user.toString() + "方法==getUserByUserName==调用成功!";}@Overridepublic String getTreeByTreeId(String id) {Tree tree = new Tree("5", "子节点", "树节点");return tree.toString() + "方法==getTreeByTreeId==调用成功!";}@Overridepublic String selectUserById(String id) {User user = new User(id, "userName", "111111", 24, "女");return user.toString() + "方法==selectUserById==调用成功!";}}

 

 spring-webservice.xml 文件,这个文件是定义我们要发布出去的接口是什么,并且指定了接口的实现类是谁。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"><beans default-autowire="byName"><!-- ====================SpringXfire================= --><bean id="userServiceImpl" class="com.ebiz.service.impl.UserServiceImpl" /><bean id="addressingHandler" class="org.codehaus.xfire.addressing.AddressingInHandler" /><bean name="userService" class="org.codehaus.xfire.spring.ServiceBean"><property name="serviceBean" ref="userServiceImpl"></property><property name="serviceClass" value="com.ebiz.service.UserService"></property><property name="inHandlers"><list><ref bean="addressingHandler" /></list></property></bean></beans>

 

springMVC.xml文件配置,这个是spring的主要配置文件大家用过的应该都知道的

<?xml version="1.0" encoding="UTF-8"?><!--看到下面的beans这个元素标签没有,必须有标签的声明 --><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context.xsd    http://www.springframework.org/schema/mvc        http://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 对web包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 --><!-- <bean name="/hello" class="com.gyl_test.action.UserController"/> --><context:component-scan base-package="com.*" /><!-- 支持spring3.0新的mvc注解 --><mvc:annotation-driven /> <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/><!-- ViewResolver --><beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="viewClass"value="org.springframework.web.servlet.view.JstlView" /><property name="prefix" value="/WEB-INF/" /><property name="suffix" value=".jsp" /></bean><!-- 总错误处理-->  <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  <property name="defaultErrorView">     <value>/error/error</value>  </property>  <property name="defaultStatusCode">    <value>500</value>  </property>     <property name="warnLogCategory">    <value>org.springframework.web.servlet.handler.SimpleMappingExceptionResolver</value>  </property>     </bean> <import resource="classpath:org/codehaus/xfire/spring/xfire.xml" /><import resource="spring-webservice.xml" /></beans>

    下面要重点讲一下这个web.xml,这个文件的配置我是吃了亏的,目前为止还是不太懂

因为少了下面的代码所以调用的时候老是提示contextConfigLocation 这个没有能初始化,后来加了这一段就好了,有大神知道原因的可以给我解释下谢谢啦!

<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        <!-- 默认情况下加载的是/WEB-INF目录下的applicationContext.xml -->
    </listener>
   
    <!-- 指定spring需要的xml文件,用contextConfigLocation指定 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:spring-conf/springMVC.xml
        </param-value>
    </context-param>

   我个人觉得这个我已经在配置SpringMvc的时候加载了,但是不知道为啥不加还是不行。

<?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>springMVC</display-name>  <servlet>  <servlet-name>springMVC</servlet-name>  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  <init-param>        <param-name>contextConfigLocation</param-name>        <param-value>classpath:spring-conf/springMVC.xml</param-value>    </init-param>  <!-- <load-on-startup>2</load-on-startup> -->  </servlet>     <servlet-mapping>  <servlet-name>springMVC</servlet-name>  <url-pattern>*.do</url-pattern>  </servlet-mapping>    <listener>        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>        <!-- 默认情况下加载的是/WEB-INF目录下的applicationContext.xml -->    </listener>        <!-- 指定spring需要的xml文件,用contextConfigLocation指定 -->    <context-param>        <param-name>contextConfigLocation</param-name>        <param-value>            classpath:spring-conf/springMVC.xml        </param-value>    </context-param>    <!-- xfire BEGIN --><servlet><servlet-name>XFireServlet</servlet-name><servlet-class>org.codehaus.xfire.spring.XFireSpringServlet</servlet-class></servlet><!-- <servlet-mapping><servlet-name>XFireServlet</servlet-name><url-pattern>/servlet/XFireServlet/*</url-pattern></servlet-mapping> --><servlet-mapping><servlet-name>XFireServlet</servlet-name><url-pattern>/services/*</url-pattern></servlet-mapping> <!-- xfire END -->    <!--获取session-->  <listener>      <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>  </listener>  <display-name>gyl_test</display-name>  <welcome-file-list>     <welcome-file>index.jsp</welcome-file>     <welcome-file>commons/hello.jsp</welcome-file>  </welcome-file-list></web-app>

 

    发布项目的代码基本就好了,然后我们看下发布的效果如图:

    发布的wsdl地址是:http://localhost:8080/gyl_test/services/UserService?wsdl

   

 

 如果你看到这个页面就代表你发布wsdl已经成功了!

 

第二步:新建一个调用wsdl的web项目名称叫:WebServiceTest

我这里用二种方式来调用一下我们发布的wsdl接口

第一种比较死板,而且要求比较高,我说的要求是指对于接口发布项目的源代码的依赖性比较强,使用第一种方式调用必须要得到源代码的接口类UserService.java 将他放到自己调用接口的项目中来使用。(是不是比较麻烦,如果接口项目是别人写的而你又没有源代码就比较麻烦了)。

第二种是使用JAW-WS方式来调用接口,其实原理就是使用jdk6.0自带的工具wsimport.exe 生成客户端代码(这个会生成一些接口调用必须的一些java类,有了这些类就可以直接调用接口的方法),当然这个代码和接口项目的源码是不一样的,但是已经能满足我们客户端调用的需求啦!代码如下:

 

 

 

public class TestAction {public static void main(String[] args) {// 调用方式一:/* * String url = * "http://localhost:8080/gyl_test/services/UserService?wsdl"; url = * "http://localhost:8080/gyl_test/services/UserService"; *  * Service service = new * ObjectServiceFactory().create(UserService.class, null, * "http://localhost:8080/gyl_test/services/UserService?wsdl", null); * XFireProxyFactory serviceFactory = new XFireProxyFactory(); *  * try { *  * UserService userService = (UserService) serviceFactory.create( * service, url); String msg = userService.getUserByUserName("hello"); * System.out.println("++++" + msg); *  * msg = userService.getTreeByTreeId("测试Tree"); * System.out.println("-------------" + msg + "-------------"); *  * msg = userService.selectUserById("测试UserId"); * System.out.println("-------------" + msg + "-------------"); } catch * (Exception e) { e.printStackTrace(); } */// 调用方式二:UserService server = new UserService();UserServicePortType spt = server.getUserServiceHttpPort();System.out.println(spt.getUserByUserName("远程调用"));}}

 

 

下面简单介绍下wsimport.exe 工具怎么使用,网上又很多,我简单说明一下,首先进入到你本机jdk的bin目录下,我本机的目录是这样的 D:\java\lib\jdk1.6.0_18\bin:

打开cmd----> cd D:\java\lib\jdk1.6.0_18\bin 回车----> 然后输入 d:    

这样就进入了jdk的bin目录如图所示

 

 

 然后输入命令:wsimport  -keep -d d:\ -s  d:\WorkSpace\WebServiceTest\src http://localhost:8080/gyl_test/services/UserService?wsdl

这个命令里面 -d 后面指示的是class文件存放的地方 可以随便写一个 例如 d:\(D盘根目录下),-s后面是源文件存放的目录也就是生成的java文件 这个建议选择项目的src目录 我这里选择d:\WorkSpace\WebServiceTest\src 最后面的是我们的wsdl地址,运行命令如图所示:

wsimport命令执行前WebServiceTest项目结构图

 

 

 wsimport命令执行结果截图

 

 

 wsimport命令执行后WebServiceTest项目结构图

 

 

 WSDL调用成功截图如下:

 

这一步需要注意的是在调用项目中不能加入xfire-all-1.2.6.jar和xfire-jsr181-api-1.0-M1.jar 包否则调用过程中会抱一个错误,

webservice: Could not initialize Service NoSuchMethodException getPortClassMap()

导致错误的原因是类加载的问题,因为xfire的包在tomcat/webapps/app/web-inf的lib下,其加载顺序高于由根classloader加载的jdk中的javax.xml.ws.spi.Provider,所以在创建Service的代理的时候没有使用jdk自带的javax.xml.ws.spi.Provider,而是使用了xfire包中的javax.xml.ws.spi.Provider导致了错误。(这个也是本人亲身尝试)

 

实例比较简单重在阐述这么一个实现过程,希望大牛们看到不要笑话我,有说的不对的地方还请指教,平时比较懒散哈哈技术总结比较少。

最后附件中附上要用的Xfire组件jar包。

 

 

 

原创粉丝点击