2010-03-08 传智播客—WebService(一)

       WebService课程由徐培成老师主讲,依然发扬传智播客的特点——深入理论和实践。今天老徐讲的原理的专业术语比较多,但我只做WebService的应用总结。如果你的JavaJavaWeb基础好些,我想你看到WebService的应用,自然就能想到它的实现原理。

 

       WebService又是一种高级应用,与之前学习的StrutsSpringHibernate等框架不同。WebService是面向服务的架构(SOA),看起来像是比SSH框架要大。那么它到底是做什么用的?什么才是面向服务的架构?

 

       让我们来看一种需求,集团公司可能具有多种WEB应用。比如,前年开发了个进销存系统、去年开发了一个ERP、今年又开发了一个OA。现在这家集团公司需要将这三个系统整合,难道需要重新编码将它们整合吗?而这三个系统又是用不同语言编写的,这种成本对公司来说无疑是一种浪费。WebService可以很好的解决这种需求。

 

       WebService是可以进行跨语言、跨平台、分布式系统间整合的方案,WebService像是一条线将这些系统穿起来——企业服务总线(ESB)。WebService使用简单对象访问协议(SOAP)使用http协议传输xml数据(xml是最常用的,也有其他格式数据。)来完成系带间的整合。

 

       什么是整合?当然是功能和数据的整合,也就是一个系统可以调用另一个系统的WebService接口来完成数据的交互。这样我们就需要知道,提供WebService服务功能的应用公开了哪些接口,我们可以通过WebService描述文档(WSDL)得知。WSDL不需要我们手动编写,JavaWebService实现可以为我们自动生成。JDK1.6新增支持WebService,但还不够成熟。所以我们使用Apache第三方开源组织提供的WebService实现——Axis

 

        Axis的当前版本是Java版本,它的C++版本正在开发中。Axis是一个功能强大的soap引擎,关于它们的详细信息在此就不做介绍了。下面,让我们来编写一个例子程序,以了解WebService的应用流程。

 

一、编写支持WebServiceWEB应用

       1.创建工程

       Project Name:TestWebService

       Target runtime:Apache Tomcat V6.0

       其他的默认

 

       2.添加AxisJar

       axisjar包目录lib子目录中的所有jar文件添加到工程中。

 

       3.配置web.xml

       axiswebapps子目录中有一个axisWeb应用,我们直接使用它的web.xml文件内容。

 

       4.添加功能类

package com.changcheng.webservice;

 

import com.changcheng.webservice.entity.User;

 

public class TestWebService {

         /**

          * 基本数据的远程

          * @param words

          * @return

          */

         public String hello(String words) {

                   return "WebService say: hello " + words;

         }

        

         /**

          *

          * @param user

          * @return

          */

         public User update(User user){

                   System.out.println(user);

                   user.setName("new_name_haha");

                   user.setPassword("new_password_123");

                   return user;

         }

}

       其中使用到的User实体类在此就不列出了。

 

       5.部署WebService

       我们可以将需要公开的类文件复制到WEB应用目录下,并修改文件后缀名为jws。把类文件更名并放到WEB目录下?这样做并不好,它被暴露了。

 

       所以在这里我们使用一个常量的部署方法,在工程中(根目录)添加一个deploy.wsdd文件:

<!-- 部署描述符 -->

<deployment xmlns="http://xml.apache.org/axis/wsdd/"

    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

    <!-- 定义处理器 -->

    <handler name="track" type="java:com.changcheng.webservice.handler.LogHandler">

        <parameter name="filename" value="d:/MyService.log" />

    </handler>

 

    <!-- 定义服务,并且在服务中使用处理器 -->

    <service name="HandlerService" provider="java:RPC">

        <requestFlow>

            <handler type="track" />

        </requestFlow>

        <parameter name="className" value="com.changcheng.webservice.TestWebService" />

        <parameter name="allowedMethods" value="*" />

    </service>

</deployment>

 

       首先将工程部署到Tomcat服务器上,并启动Tomcat服务器。然后在工程上右键-->Run As...-->Run Configurations...,新建一个JavaApplication。在main页面中,project指定为我们的TestWebServiceMainClass指定为org.apache.axis.client.AdminClient。在Arguments页面下设置Program arguments-l http://localhost:8080/TestWebService/servlet/AxisServlet deploy.wsdd。点击Run按钮。

 

       完成上面的操作后,AdminClient会为我们部署在TomcatTestWebServiceWEB-INF目录下生成一个server-config.wsdd文件,它是提供给Axis使用的配置文件。

 

       我们需要将向server-config.wsdd文件的HandlerService元素添加一个beanMapping子元素:

 <service name="HandlerService" provider="java:RPC">

  <requestFlow>

   <handler type="track"/>

  </requestFlow>

  <parameter name="allowedMethods" value="*"/>

  <parameter name="className" value="com.changcheng.webservice.TestWebService"/>

  <beanMapping qname="myNS:User" xmlns:myNS="urn:pojo:ws:changcheng:com" languageSpecificType="java:com.changcheng.webservice.entity.User"/>

 </service>

 

       其中的添加的处理器是WebService的一项功能,在远程调用指定的方法时,会先由处理器进行处理。

package com.changcheng.webservice.handler;

 

import java.io.FileOutputStream;

import java.io.PrintWriter;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.apache.axis.AxisFault;

import org.apache.axis.Handler;

import org.apache.axis.MessageContext;

import org.apache.axis.handlers.BasicHandler;

 

/**

 * 日志处理器,类似于web中的filter

 */

public class LogHandler extends BasicHandler {

         private static final long serialVersionUID = 3227593680689235885L;

 

         public void invoke(MessageContext arg0) throws AxisFault {

                   try {

                            Handler serviceHandler = arg0.getService();

                            // 提取配置文件(server-config)的配置信息

                            String filename = (String) getOption("filename");

                            //

                            FileOutputStream fos = new FileOutputStream(filename);

                            PrintWriter writer = new PrintWriter(fos);

                            // getOption()类似于request.getAttribute("")

                            // 获得在handler对象中存放的访问次数

                            Integer numAccesses = (Integer) serviceHandler

                                               .getOption("accesses");

                            // 如果首次访问

                            if (numAccesses == null)

                                     numAccesses = new Integer(0);

                            // 次数 ++

                            numAccesses = new Integer(numAccesses.intValue() + 1);

                            //

                            Date date = new Date();

                            // 对日期进行格式化

                            SimpleDateFormat sdf = new SimpleDateFormat();

                            sdf.applyPattern("yyyy-MM-dd hh:mm:ss");

                            String result = sdf.format(date) + ": service "

                                               + arg0.getTargetService() + " accessed " + numAccesses

                                               + " time(s).";

                            // 将访问次数写入到handler对象中(request.setAttribute(..));

                            serviceHandler.setOption("accesses", numAccesses);

                            writer.println(result);

                            writer.close();

                   } catch (Exception e) {

                            throw AxisFault.makeFault(e);

                   }

         }

}

 

 

二、编写运程调用WebServiceWEB应用的Java工程

      

       1.添加上面WEB工程中所用到的Axisjar

 

       2.编写测试类:

package com.changcheng.client;

 

import java.net.URL;

import javax.xml.namespace.QName;

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

import org.apache.axis.encoding.ser.BeanDeserializerFactory;

import org.apache.axis.encoding.ser.BeanSerializerFactory;

import org.junit.Test;

import com.changcheng.webservice.entity.User;

 

public class TestMain {

 

         // 测试一般方法

         @Test

         public void hello() throws Exception{

                   Service s = new Service();

                   Call call = (Call) s.createCall();

                   String url = "http://localhost:8080/TestWebService/services/HandlerService";

                   call.setTargetEndpointAddress(new URL(url));

                   call.setOperationName("hello");

                   Object res = call.invoke(new Object[] { "itcast" });

                   System.out.println(res);

         }

        

        

         // 测试实体方法

         @Test

         public void update() throws Exception {

                   Service s = new Service();

                   Call call = (Call) s.createCall();

                   String url = "http://localhost:8080/TestWebService/services/HandlerService";

                   call.setTargetEndpointAddress(new URL(url));

                   call.setOperationName("update");

                   // 客户端同样需要对pojo进行注册.以确保也能够进行序列化和反序列化.

                   Class clazz = User.class;

                   // 限定名必须和服务器端注册限定名保持一致,严格区分大小写

                   QName qname = new QName("urn:pojo:ws:changcheng:com", "User");

                   // 注册类型映射,以便传递pojo对象

                   call.registerTypeMapping(clazz, qname, new BeanSerializerFactory(clazz,

                                     qname), new BeanDeserializerFactory(clazz, qname));

                   //

                   User user = new User();

                   user.setName("itcast");

                   user.setPassword("abcd");

                   Object res = call.invoke(new Object[] { user });

                   System.out.println(res);

         }

}

 

       3.运行测试

 

       总结完成!

 

你可能感兴趣的:(2010-03-08 传智播客—WebService(一))