编写轻量级WebService服务器

44 篇文章 2 订阅
41 篇文章 0 订阅

标题:编写轻量级WebService服务器
作者:Lee353086(kagula)
日期:2007-12-15

目的:通过示例代码和其它样例文件,你将了解[1]如何解析和生成soap信息[2]简单的http server端编程

阅读对象:
    java程序员

环境:
[1]IBM JAVA JDK(From WebSphere6.1安装包)
[2]MyEclipse5.1.x


内容:
    java源代码(含大量注解)和xml样例文件。

注意:
    NHttpServer.java文件,根据
    http://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha6/module-nio/src/examples/org/apache/http/examples/nio/NHttpServer.java
    文件修改而来。

必须信赖包:
    [1]saaj.jar(可以使用Axis1.4发行包中的saaj.jar)
    [2]httpcore-4.0-alpha6.jar、httpcore-nio-4.0-alpha6.jar等包来自http://jakarta.apache.org/httpcomponents/
   
正文:
第一部份:NHttpServer.java源文件清单
---------------------------------------------------------------------------------------------------------------------------
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.util.Iterator;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.nio.DefaultServerIOEventDispatch;
import org.apache.http.impl.nio.reactor.DefaultListeningIOReactor;
import org.apache.http.nio.NHttpConnection;
import org.apache.http.nio.protocol.BufferingHttpServiceHandler;
import org.apache.http.nio.protocol.EventListener;
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.nio.reactor.ListeningIOReactor;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import org.apache.http.util.EntityUtils;

public class NHttpServer {

    public static void main(String[] args) throws Exception {
     Log log=LogFactory.getLog("NHttpServer");
     
     //设置Http服务器根目录.begin
     args=new String[1];
     args[0]="WebRoot";
//     设置Http服务器根目录.end
     
        if (args.length < 1) {
            log.error("Please specify document root directory");
            System.exit(1);
        }
       
        /**
         * 设置Http Server参数
         */
        HttpParams params = new BasicHttpParams(null);
        params
            .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 30*60*1000)
            .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
            .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
            .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
            .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "Jakarta-HttpComponents-NIO/1.1");

        /**
         * Httpproc拦截器
         */
        BasicHttpProcessor httpproc = new BasicHttpProcessor();
        httpproc.addInterceptor(new ResponseDate());
        httpproc.addInterceptor(new ResponseServer());
        httpproc.addInterceptor(new ResponseContent());
        httpproc.addInterceptor(new ResponseConnControl());
       
        BufferingHttpServiceHandler handler = new BufferingHttpServiceHandler(
                httpproc,
                new DefaultHttpResponseFactory(),
                new DefaultConnectionReuseStrategy(),
                params);
       
        // Set up request handlers
        HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
        reqistry.register("*", new HttpFileHandler(args[0]));
       
        handler.setHandlerResolver(reqistry);
       
        // Provide an event logger
        handler.setEventListener(new EventLogger());
       
        IOEventDispatch ioEventDispatch = new DefaultServerIOEventDispatch(handler, params);
        ListeningIOReactor ioReactor = new DefaultListeningIOReactor(2, params);
        try {
            ioReactor.listen(new InetSocketAddress(8080));
            ioReactor.execute(ioEventDispatch);
        } catch (InterruptedIOException ex) {
            log.error("Interrupted");
        } catch (IOException e) {
            log.error("I/O error: " + e.getMessage());
        }
        log.debug("Shutdown");
    }

    static class HttpFileHandler implements HttpRequestHandler  {
       
        private final String docRoot;
        private final Log log=LogFactory.getLog("HttpFileHandler");
       
        public HttpFileHandler(final String docRoot) {
            super();
            this.docRoot = docRoot;
        }
       
        public void handle(
                final HttpRequest request,
                final HttpResponse response,
                final HttpContext context) throws HttpException, IOException {

            String method = request.getRequestLine().getMethod().toUpperCase();
            log.debug("request.getRequestLine().getMethod().toUpperCase() => "+method);           
           
            if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) {
                throw new MethodNotSupportedException(method + " method not supported");
            }

            //测试SOAP原始上传内容.begin
            /*
            if (request instanceof HttpEntityEnclosingRequest) {
                HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
                byte[] entityContent = EntityUtils.toByteArray(entity);
                log.debug("Incoming entity content (bytes): " + entityContent.length);
                log.debug("Incoming entity content (String):"+new String(entityContent,"utf-8"));               
            }
            */
            //测试SOAP原始上传内容.end
           
            //检查上传url(不包括本地服务器地址).begin
            String target = request.getRequestLine().getUri();
            log.debug("request.getRequestLine().getUri() => "+target);
//          检查上传url(不包括本地服务器地址).end
           
            String strWS="/ws";
            if(target.equalsIgnoreCase(strWS))
            {
             log.debug("处理WebService服务请求");
             wsProcessing(request,response);
            }else {
             //默认,http请求,处理函数
             final File file = new File(this.docRoot, URLDecoder.decode(target, "UTF-8"));
             defaultProcessing(response,file);
            }

        }
       
        /**
         * WebService请求,处理函数
         *
         */
        public  void wsProcessing(final HttpRequest request,final HttpResponse response)
        {
            if (request instanceof HttpEntityEnclosingRequest) {
             try {
              //取从Axis1.4发过来的请求
              HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
              byte[] entityContent = EntityUtils.toByteArray(entity);                      

 //             create the actual message
                 MessageFactory messageFactory = MessageFactory.newInstance();
                 SOAPMessage message = messageFactory.createMessage();
 
                 //Create objects for the message parts           
                 SOAPPart soapPart = message.getSOAPPart();
                
                 //construct from ByteArrayInputStream                
                 StreamSource preppedMsgSrc = new StreamSource(new ByteArrayInputStream(entityContent));
                 /*
                 String MsgSrc=new String("<soapenv:Envelope xmlns:soapenv=/"http://schemas.xmlsoap.org/soap/envelope//" xmlns:xsd=/"http://www.w3.org/2001/XMLSchema/"  xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/"><soapenv:Body><JWSendLog soapenv:encodingStyle=/"http://schemas.xmlsoap.org/soap/encoding//"><arg0 xsi:type=/"soapenc:string/" xmlns:soapenc=/"http://schemas.xmlsoap.org/soap/encoding//">cd8f0a5a585940aa8420fb439311656d</arg0><arg1 xsi:type=/"soapenc:string/" xmlns:soapenc=/"http://schemas.xmlsoap.org/soap/encoding//">0</arg1><arg2 xsi:type=/"soapenc:string/" xmlns:soapenc=/"http://schemas.xmlsoap.org/soap/encoding//">kagula uid</arg2></JWSendLog></soapenv:Body></soapenv:Envelope>");
                 StreamSource preppedMsgSrc = new StreamSource(new ByteArrayInputStream(MsgSrc.getBytes()));
                 */
                 soapPart.setContent(preppedMsgSrc);
 
                 //Save the message
//                 message.saveChanges();
                
                 //iterator body content.begin
                 SOAPEnvelope envelope = soapPart.getEnvelope();
                 SOAPBody body=envelope.getBody();
                 Iterator iter=body.getChildElements();
                 while(iter.hasNext())
                 {
                  //may be could be for getting call method name
                  //among these important is getNodeName(),getValue()
                  //SOAPElement content.begin
                  SOAPElement element=(SOAPElement)iter.next();
                  log.debug("SOAPElement.getNodeName="+element.getNodeName()+",getNodeType="+element.getNodeType()+",getNodeValue="+element.getNodeValue());
                  log.debug("SOAPElement.getPrefix="+element.getPrefix()+",getTagName="+element.getTagName()+",getValue="+element.getValue());
                  //SOAPElement content.end
                  
                  Iterator eiter=element.getChildElements();
                  while(eiter.hasNext())
                  {
                   //may be could read for getting call method 's parameters
                   //SOAPElement content.begin
                   SOAPElement subelement=(SOAPElement)eiter.next();
                   log.debug("SOAPElement.getNodeName="+subelement.getNodeName()+",getNodeType="+subelement.getNodeType()+",getNodeValue="+subelement.getNodeValue());
                   log.debug("SOAPElement.getPrefix="+subelement.getPrefix()+",getTagName="+subelement.getTagName()+",getValue="+subelement.getValue());
                   //SOAPElement content.end                   
                  }
                 }
                 //iterator body content.end
 
                 //Check the input
                 /*
                 System.out.println("/nREQUEST:/n");
                 message.writeTo(System.out);
                 System.out.println();
                 */ 
                 }catch(Exception e)
                 {
                  log.error("soap error:"+e.toString());                 
                 }
            }//end if (request instanceof HttpEntityEnclosingRequest)
           
            //返回SOAP格式,信息
            returnSOAP(response,new String("你好!这是我的反馈信息。(Hello!It's my response msg.)"));
        }
       
        /**
         * 返回WebService服务请求的响应
         * @param response
         * @param strMsg
         */
        public void returnSOAP(final HttpResponse response,final String strMsg)
        {
         try {
          MessageFactory fac = MessageFactory.newInstance();
          SOAPMessage msg=fac.createMessage();
          SOAPPart part=msg.getSOAPPart();
          SOAPEnvelope envelope=part.getEnvelope();
          SOAPBody body=envelope.getBody();
          Name bodyName=envelope.createName("Response", "", "http://tempuri.org/");
          SOAPBodyElement list =body.addBodyElement(bodyName);

          Name resultN = envelope.createName("result");
          SOAPElement result = list.addChildElement(resultN);          
          result.addTextNode(strMsg);
          
          msg.saveChanges();
          
          msg.writeTo(System.out);
          log.debug("SOAPEnvelope.toString()"+envelope.toString());
          
          //response
                response.setStatusCode(HttpStatus.SC_OK);               
                StringEntity entity=new StringEntity(envelope.toString());
                response.setEntity(entity);
         
         } catch (Exception ex) {
          log.error("returnSOPA()=>"+ex.toString());
         }         
        }
       
        /**
         * http请求,缺省处理函数
         * @param response
         * @param file
         */
        public void defaultProcessing(final HttpResponse response,final File file)
        {
            if (!file.exists()) {

                response.setStatusCode(HttpStatus.SC_NOT_FOUND);
                EntityTemplate body = new EntityTemplate(new ContentProducer() {
                   
                    public void writeTo(final OutputStream outstream) throws IOException {
                        OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8");
                        writer.write("<html><body><h1>");
                        writer.write("File ");
                        writer.write(file.getPath());
                        writer.write(" not found");
                        writer.write("</h1></body></html>");
                        writer.flush();
                    }
                   
                });
                body.setContentType("text/html; charset=UTF-8");
                response.setEntity(body);
                log.error("File " + file.getPath() + " not found");
               
            } else if (!file.canRead() || file.isDirectory()) {
               
                response.setStatusCode(HttpStatus.SC_FORBIDDEN);
                EntityTemplate body = new EntityTemplate(new ContentProducer() {
                   
                    public void writeTo(final OutputStream outstream) throws IOException {
                        OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8");
                        writer.write("<html><body><h1>");
                        writer.write("Access denied");
                        writer.write("</h1></body></html>");
                        writer.flush();
                    }
                   
                });
                body.setContentType("text/html; charset=UTF-8");
                response.setEntity(body);
                log.error("Cannot read file " + file.getPath());
               
            } else {
               
                response.setStatusCode(HttpStatus.SC_OK);
                FileEntity body = new FileEntity(file, "text/html");
                response.setEntity(body);
                log.debug("Serving file " + file.getPath());
               
            }
        }
    }
   
    static class EventLogger implements EventListener {
     
     private final Log log=LogFactory.getLog("EventLogger");

        public void connectionOpen(final NHttpConnection conn) {
            log.debug("Connection open: " + conn);
        }

        public void connectionTimeout(final NHttpConnection conn) {
         log.debug("Connection timed out: " + conn);
        }

        public void connectionClosed(final NHttpConnection conn) {
         log.debug("Connection closed: " + conn);
        }

        public void fatalIOException(final IOException ex, final NHttpConnection conn) {
         log.debug("I/O error: " + ex.getMessage());
        }

        public void fatalProtocolException(final HttpException ex, final NHttpConnection conn) {
         log.debug("HTTP error: " + ex.getMessage());
        }
       
    }
       
}
---------------------------------------------------------------------------------------------------------------------------
第二部份:客户端代码片段(使用了Axis1.4)
---------------------------------------------------------------------------------------------------------------------------
        ...by omit...
       
        try
        {  
         String endpoint = "http://localhost:8080/ws"; 

         Service service = new Service();
         Call call = (Call) service.createCall();
 
         call.setTargetEndpointAddress(new java.net.URL(endpoint));  
         call.setOperationName("JWSendLog");        

         ret = (String) call.invoke(new Object[]{"cd8f0a5a585940aa8420fb439311656d","0","kagula uid","0"});
        }catch(AxisFault af)
        {
         System.out.println("Reason:"+af.getFaultReason());
        }catch (ServiceException se)
        {
         se.printStackTrace();
        }catch(Exception e)
        {
         e.printStackTrace();
        }
        System.out.println("testSMSWebService_JWSendLog(...) ret="+ret);
       
        ...by omit...
---------------------------------------------------------------------------------------------------------------------------
第三部份:请求SOAP样例
---------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
  <JWSendLog soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <arg0 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
    cd8f0a5a585940aa8420fb439311656d
    </arg0>
    <arg1 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">0</arg1>
    <arg2 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">kagula uid</arg2>
    <arg3 xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">中文参数测试</arg3>
  </JWSendLog>
 </soapenv:Body>   
</soapenv:Envelope>
---------------------------------------------------------------------------------------------------------------------------
第四部份:返回SOAP样例
---------------------------------------------------------------------------------------------------------------------------
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <Response xmlns="http://tempuri.org/">
      <result xmlns="">&#x4F60;&#x597D;&#xFF01;&#x8FD9;&#x662F;&#x6211;&#x7684;&#x53CD;&#x9988;&#x4FE1;&#x606F;&#x3002;(Hello!It's my response msg.)
      </result>
    </Response>
  </soapenv:Body>
</soapenv:Envelope>
---------------------------------------------------------------------------------------------------------------------------
第五部份:使用简介
启动程序后,在地址栏中打入http://localhost:8080/ws也会返回xml形式的内容。
在地址栏中打入http://localhost:8080/index.html,WEB浏览器会去access你项目当前运行目录下的WebRoot目录下的index.html文件。
如果没有找到文件,返回,文件不存在的提示。


参考网站:
[1]axis官方网站
http://ws.apache.org/axis/
[2]httpcomponents项目官方网站
http://jakarta.apache.org/httpcomponents/

备注:
[1]代码经过修改,可以不依赖于Axis1.4提供的jar包
[2]本文中的代码,只有通过必要修改,才能作为WebService服务器使用。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kagula086

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值