使用WAS CE V2.1开发基于JAX-WS的RESTful Web Service

一、什么是REST

REST是REpresentational State Transfer的缩写,代表分布式超媒体系统(如World Wide Web)上的一种软件架构体系,并不仅仅是创建Web Service的一种方法。它最早由Roy Fielding于2000年在其博士论文"Architectural Styles and the Design of Network-based Software Architectures"中提出,并定义了一些基本原则,简单的说,放到World Wide Web上,就是所有的应用程序对象和功能都可以抽象为一种资源(Resource),并通过URI来定位并使用。因此,我们可以把符合REST原则的系统称为RESTful,也就是说,REST是一种架构风格,而不是一个标准,你永远不会看到W3C发布一个叫REST的Specification。

RESTful Web Service与基于SOAP和WSDL的Web Service有着很多的不同,它有着以下特点:

  • 将Web Service作为一种资源,并通过URI来定位
  • 使用HTTP中的POST, GET, PUT 和 DELETE 方法来代表对资源的CREATE, READ, UPDATE, DELETE (CRUD) 操作
  • 使用无状态通信
  • 传输 XML 或者 JSON

在 JAX-WS中提供了对开发和部署一个RESTful的Web Service的基本支持,即通过实现Provider接口使得Web Serivce可以对传输的XML消息进行完全的控制,因此我们可以在WAS CE中使用JAX-WS开发一个RESTful的Web Service。

对RESTful Web Service提供完整支持的JAX-RS Specification将会加入Java EE 6.0的大家庭中,当前的WAS CE V2.1.x是遵循Java EE 5.0的企业级应用服务器,因此,若想使用JAX-RS开发RESTful Web Service,请关注WAS CE的后续版本。
 

二、开发环境设置

本文基于WAS CE的最新版本V2.1.1.2开发一个RESTful的Web Service,在开始编写代码之前,请确认如下的开发环境:

  • Sun JDK V5.0
  • Eclipse IDE for Java EE Developers - Ganymede
  • WASCE Eclipse Plug-in (WEP) V2.1.1.2

此外,WAS CE使用Axis2-1.3作为JAX-WS引擎,但是由于其存在一个已知的关于HTTP Content-Type Header的问题(在Axis2-1.4中才解决),所以我们需要将JAX-WS引擎切换成Apache CXF (WAS CE使用版本为V2.0.8)。不用担心,WAS CE的模块化架构,使这个过程十分简单,过程如下:

  1. 启动 WAS CE
     
  2. 打开 Web Console:http://localhost:8080/console
     
  3. 进入 Application -> Plugins 页面,点击 Add Repository
    21647773_200905142044531.jpg
     
  4. 由于WAS CE V2.1.1.2是基于Geronimo V2.1.4开发,所以我们也可以使用Geronimo的Server plug-ins。在New Repository中输入:
    http://geronimo.apache.org/plugins/geronimo-2.1.4/  然后点击Add Repository.
    21647773_200905142044532.jpg
     
  5. 选择刚刚添加的Repository,然后点击Show Plugins in selected repository
    21647773_200905142045351.jpg
     
  6. 勾选上以下plug-ins并且点击install按钮。
    21647773_200905142045352.jpg
     
  7. 在以上CXF相关的Plugin安装完成之后, 我们需要更新WAS CE的配置文件,以使得WAS CE在启动时加载CXF以代替Axis2。(注意:在更改配置文件前先要停止WAS CE服务器)
     
  8. 停止WAS CE后,打开/var/config/config.xml

    去掉以下四个module的condition属性:

    condition="…"/>
    condition="…"/>
    condition="…"/>
    condition="…"/>


    增加load属性,axis2相关的为false,cxf相关的为true:

    load="false"/>
    load="false"/>
    load="true"/>
    load="true"/>

     
  9. 重新启动WAS CE服务器。
     

三、开发一个简单的RESTful Web Service

  1. 在Eclipse中创建一个Dynamic Web Project作为Web Service的宿主:
    选择File->New->Dynamic Web Project
    输入Project Name为HelloRestfulService
     
  2. 右击Java Resources: src,新建一个class,其中package, Name, Interfaces如下设置:
    21647773_200905142045353.jpg
     
  3. 加入如下代码:

    package  com.ibm.wasce.samples.jaxws.rest;

    import  java.io.ByteArrayInputStream;
    import  javax.annotation.Resource;
    import  javax.servlet.ServletRequest;
    import  javax.xml.parsers.DocumentBuilder;
    import  javax.xml.parsers.DocumentBuilderFactory;
    import  javax.xml.transform.Source;
    import  javax.xml.transform.dom.DOMSource;
    import  javax.xml.transform.stream.StreamSource;
    import  javax.xml.ws.BindingType;
    import  javax.xml.ws.Provider;
    import  javax.xml.ws.WebServiceContext;
    import  javax.xml.ws.WebServiceProvider;
    import  javax.xml.ws.handler.MessageContext;
    import  javax.xml.ws.http.HTTPBinding;
    import  javax.xml.ws.http.HTTPException;  
    import  org.w3c.dom.Node;
    import  org.w3c.dom.NodeList;
    import  org.xml.sax.InputSource;

    @WebServiceProvider
    @BindingType (value = HTTPBinding. HTTP_BINDING )
    public   class  HelloWorld   implements  Provider {
        @Resource
        protected  WebServiceContext  wsContext ;

        public  Source invoke(Source source) {
            try  {
                String targetName =  null ;

                if  (source ==  null ) {
                    //Get: Getting input from query string
                    MessageContext mc =  wsContext .getMessageContext();
                    String query = (String) mc.get(MessageContext. QUERY_STRING );
                    System. out .println( "Query String = "  + query);
                    ServletRequest req = (ServletRequest) mc.get(MessageContext. SERVLET_REQUEST );
                    targetName = req.getParameter( "target" );
                }  else  {
                    //POST: Getting input from input box
                    Node n =  null ;
                    if  (source  instanceof  DOMSource) {
                        n = ((DOMSource) source).getNode();
                    }  else   if  (source  instanceof  StreamSource) {
                        StreamSource streamSource = (StreamSource) source;
                        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
                        InputSource inputSource =  null ;
                        if  (streamSource.getInputStream() !=  null ) {
                            inputSource =  new  InputSource(streamSource.getInputStream());
                        }  else   if  (streamSource.getReader() !=  null ) {
                            inputSource =  new  InputSource(streamSource.getReader());
                        }
                        n = builder.parse(inputSource);
                    }  else  {
                        throw   new  RuntimeException( "Unsupported source: "  + source);
                    }
                    NodeList children = n.getChildNodes();
                    for  ( int  i = 0; i < children.getLength(); i++) {
                        Node child = children.item(i);
                        if  (child.getNodeName().equals( "people" )) {
                            targetName = child.getAttributes().getNamedItem( "target" ).getNodeValue();
                            break ;
                        }
                    }
                }
                 
               
    String body =  ""
                        +  ""  +  this .sayHello(targetName) +  ""
                        +  "" ;
                return   new  StreamSource( new  ByteArrayInputStream(body.getBytes()));
     
           
    }  catch  (Exception e) {
                e.printStackTrace();
                throw   new  HTTPException(500);
            }
        }
      
        private  String sayHello(String target){
            return   "Hello "  + target;
        } 
    } 

     
      
    让我们看一看代码中的几个关键点:
    a) @WebServiceProvider 表明这个Web Service实现了Provider接口,可以对XML消息进行完全的处理。
    b) Provider 是这类Web Service都要实现的接口,它只有一个方法需要实现,即:
        public abstract java.lang.Object invoke(java.lang.Object arg0);
    c) Source 是交换信息的载体:
        当Source对象为空时,表示是一个GET Request。因为这种情况下,所有信息是被拼成一个URI的参数,并传到这个URI对应的Web Service。
        否则,是一个POST Request,其内容会包括在一个Source对象内;
        另外,Response的内容也要放到一个Source对象内。
     
  4. 编写web.xml
    为了使我们前面编写的Web Service能够成功部署到WAS CE中,我们需要将如下内容加入到web.xml中:


        Hello
        com.ibm.wasce.samples.jaxws.rest.HelloWorld


        Hello
        /Hello

    注意,这里只是借用了和标签来帮助暴露Web Service,并不是真是要求这个Web Service必须要实现HttpServlet接口。
     
  5. 部署,运行并测试这个Web Service
    右击这个HelloRestfulService工程,选择Run As -> Run on Server,会将其部署到WAS CE中,当Status栏变为Synchronized时,在Console中会有类似如下信息显示:
    21647773_200905142045354.jpg
     
    通过访问如下地址,测试使用GET方式调用RESTful Web Service返回的结果:
    http://localhost:8080/HelloRestfulService/Hello?target=Rex
    21647773_200905142045561.jpg
     

四、开发一个简单的RESTful Web Service Client

  1. 创建一个Dynamic Web Project作为Client
    选择 File->New->Dynamic Web Project
    输入 Project Name为HelloRestfulClient
     
  2. 新建一个testget.jsp,加入如下内容:


      Target Name:
     

    这个JSP用来为HelloGetMethodRequester Servlet提供参数。
     
  3. 创建HelloGetMethodRequester Servlet,加入如下内容:

    protected void  doPost(HttpServletRequest request, HttpServletResponse response)  throws  ServletException, IOException {
        PrintWriter ut = response.getWriter();
        String target = request.getParameter( "target" );
              
       
    String queryRequest =  "http://localhost:8080/HelloRestfulService/Hello?target="  + target;
        GetMethod method =  new  GetMethod(queryRequest);
        HttpClient client =  new  HttpClient();
        int  statusCode = client.executeMethod(method);
        if  (statusCode != 200) {  //HttpStatus.SC_OK
            System. err .println( "Method failed: "  + method.getStatusLine());
        }
              
       
    try  {
           
    DocumentBuilder builder= DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document queryResponse = builder.parse(method.getResponseBodyAsStream());
            XPath xPath = XPathFactory.newInstance().newXPath();
            NodeList nodes = (NodeList) xPath.evaluate( "/return" , queryResponse, XPathConstants. NODESET );
            for  ( int  i = 0; i < nodes.getLength(); i++) {
                // Get each xpath expression as a string
                String str = (String) xPath.evaluate( "HelloWorldResponse" , nodes.item(i), XPathConstants. STRING );
                out.println( "Service return: "  + str);
            }
        }  catch  (Exception e) {
            e.printStackTrace();
        }
    } 

     
     
    在这个Servlet中我们用到了commons-codec-1.3.jar和commons-httpclient-3.0.1.jar两个包,因此我们需要将它们加入到Build Path中:
    21647773_200905142045356.jpg
     
    这两个包在WAS CE的如下目录中可以找到:
    \repository\commons-codec\commons-codec\1.3\commons-codec-1.3.jar
    \repository\commons-httpclient\commons-httpclient\3.0.1\commons-httpclient-3.0.1.jar
     
    让我们看一看这段Servlet代码中的一些关键点:
    a) 首先创建了一个HttpClient对象,并运行了GetMethod,即使用GET请求如下URI:
        "http://localhost:8080/HelloRestfulService/Hello?target=" + target
    b) 如果成功返回,即statusCode为200,则可以从method对象中得到返回的结果:
        method.getResponseBodyAsStream()
    c) 因为返回的结果为自定义的一段XML文档,所以我们可以使用XPath来处理并输出到页面上。
     
  4. 编写部署计划geronimo-web.xml
    为使这个Web Client能够成功部署到WAS CE中,我们还需要在geronimo-web.xml的中加入如下依赖:


       
            commons-codec
            commons-codec
            1.3
            jar
       
       
            commons-httpclient
            commons-httpclient
            3.0.1
            jar
       

     
  5. 部署和运行
    右击这个HelloRestfulClient工程,选择Run As -> Run on Server,会将其部署到WAS CE中,当Status栏变为Synchronized时,表示部署成功。
    在浏览器中打开如下页面:http://localhost:8080/HelloRestfulClient/testget.jsp
    21647773_200905142045355.jpg
     
    输入"Rex",并点击Submit,可得到如下结果:
    21647773_200905142045357.jpg
      

五、总结

本文介绍了REST的基本概念,以及如何在WAS CE V2.1.1.2下开发一个RESTful Web Service和一个使用GET方式的Client。如果读者朋友有兴趣的话,也可以尝试扩展这个Client,如增加testpost.jsp和HelloPostMethodRequester Servlet两个文件:
 - testpost.jsp包括一个文件上载框,用以上传一个XML文件;
 - HelloPostMethodRequester Servlet用于将XML文件以POST方式传送给HelloWorld这个Service。
事实上,我们的HelloWorld RESTful Web Service已经具备了处理接收一个XML文件的能力。
 

六、资源链接


fj.pngREST01.JPG

fj.pngREST02.JPG

fj.pngREST03.JPG

fj.pngREST04.JPG

fj.pngREST05.JPG

fj.pngREST06.JPG

fj.pngREST09.JPG

fj.pngREST08.JPG

fj.pngREST10.JPG

fj.pngREST07.JPG

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/21647773/viewspace-598174/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/21647773/viewspace-598174/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值