Provider service form of Web Service

This article does not explain the details of the use of jax-ws (only for dry goods), please understand.

Development framework used: jax-ws

 

Features: Both the server and the client directly manipulate the entire message content of SOAP. Eliminate unnecessary network transmission and xml serialization/deserialization

约定的URI:http://[host]:[port]/[web-app-name]/service/[business-name]/[select|delete|update|insert]?[query-strings]

  The business name (business-name) is reflected on the URI (borrowing an inappropriate word - resource)

  There are only four types of business operations: select (query), delete (delete), update (change), and insert (new). Business operations are reflected in URI (RPC form)

 

Implementation principle: reflect the implementation class of the business according to the agreed URI (according to the business-name on the URI); locate the method on the specific business implementation class according to the operation on the URI ([select|delete|update|insert]) and execute

 

First look at the entrance of the service

 

 

@ServiceMode(value = Service.Mode.MESSAGE)
@WebServiceProvider(serviceName = "TimingSOAPWS", portName = "TimingSOAPWSPort", targetNamespace = "http://www.timing.com")
@BindingType(value = SOAPBinding.SOAP12HTTP_MTOM_BINDING)
@MTOM(enabled = true, threshold = 10 * 1024 * 1024)//10M files only enable MTOM
public final class TimingSOAPWS implements AsyncProvider<SOAPMessage> {
    public void invoke(SOAPMessage request, AsyncProviderCallback<SOAPMessage> callback, WebServiceContext context) {

        javax.servlet.ServletContext servletContext = (javax.servlet.ServletContext)context.getMessageContext().get(MessageContext.SERVLET_CONTEXT);

        final Runnable processRunnable = new ProcessRunnable(request, callback, context);

        //If there is a thread pool in the servlet environment, use the thread pool
        if (servletContext != null) {

            Object o = servletContext.getAttribute(WSProviderThreadPoolListener.THREAD_POOL_ATTR);

            if (o instanceof ExecutorService)
                ((ExecutorService)o).execute(processRunnable);

        }
        else//There is no thread pool, start a new thread
            new Thread(processRunnable).start();
    }
}

 

 

Next, abstract the operations of the business

 

import javax.xml.ws.*;
/**
 * Abstract business processor. Define insert, update, delete, query
 * @author Hardneedl
 */
public interface WSOperator <S, R> {
    /**
     * Operation of inserting data
     * @param request the requested message
     * @param context web context @return the content that will be returned to the client
     */
    R insert(S request, WebServiceContext context) throws Exception;

    /**
     * Operation to update data
     * @param request the requested message
     * @param context web context
     * @return what will be returned to the client
     */
    R update(S request, WebServiceContext context) throws Exception;

    /**
     * Operation of deleting data
     * @param request the requested message
     * @param context web context
     * @return what will be returned to the client
     */
    R delete(S request, WebServiceContext context) throws Exception;

    /**
     * Operation of checking data
     * @param request the requested message
     * @param context web context
     * @return what will be returned to the client
     */
    R select(S request, WebServiceContext context) throws Exception;
}

 

Finally, let's look at the key implementation code

 

final class ProcessRunnable implements Runnable {
    private SOAPMessage request;
    private AsyncProviderCallback<SOAPMessage> callback;
    private WebServiceContext context;

    ProcessRunnable(SOAPMessage request, AsyncProviderCallback<SOAPMessage> callback, WebServiceContext context) {
        this.request=request;
        this.callback=callback;
        this.context=context;
    }

    public void run() {

        MessageContext msgContext = context.getMessageContext();
        String pathString=(String)msgContext.get(MessageContext.PATH_INFO);

        if (pathString==null||pathString.isEmpty())return;

        String pathInfos[] = pathString.split("/");

        try {
            WSOperator opt = ClzManagerFactory.getClzManager().getOperatorSingleInstance("com.timing.business."+pathInfos[1] + "Operator");

            Method method = opt.getClass().getDeclaredMethod(pathInfos[2], SOAPMessage.class, WebServiceContext.class);
            SOAPMessage soapMessage = (SOAPMessage)method.invoke(opt,request,context);
            callback.send(soapMessage);

        }catch (Exception e) {            
            callback.sendError(e);
        }

    }
}

 

What are the advantages over the WSDL->java approach?

 1) As far as four operation methods are concerned, the operation of the service is simple and clear

  2) In complex business situations, when the client posts large content to the server, it directly operates the xml, eliminating the need for the jax-ws runtime to deserialize the xml->java type. Deserialization operations consume more cpu and memory

  3) For simple business requirements, provide parameters directly with query strings on the URI, which also eliminates the need for jax-ws runtime to deserialize xml->java types

 

  In the development method of wsdl->java, even if the server returns an Integer type, it needs java->xml, and then the client xml->java

 

An example implementation of WSOperator

/* This is an adapter, the concrete business implementer inherits from this class */
public class WSOperatorAdapter implements WSOperator<SOAPMessage, SOAPMessage> {
    public SOAPMessage insert(SOAPMessage request, WebServiceContext context) throws Exception {return request;}
    public SOAPMessage update(SOAPMessage request, WebServiceContext context) throws Exception {return request;}
    public SOAPMessage delete(SOAPMessage request, WebServiceContext context) throws Exception {return request;}
    public SOAPMessage select(SOAPMessage request, WebServiceContext context) throws Exception {return request;}
}

 

final public class SiteInfoOperator extends WSOperatorAdapter{
    static private final Config CONFIG = ConfigFactory.getTextConfig();

    /**
     * output xml structure
     *  <SiteInfo pollutantSourceCode=""
     *            drainOutletCode=""
     *            drainOutletName=""
     *            equipmentName=""
     *            deviceName=""
     *            scales=""
     *            groupType=""
     *            isNormal=""
     *            remarks=""
     *            userId=""
     *            itemClass=""/>
     *
     *
     * @param request
     * @param context
     * @return
     * @throws Exception
     */
    public SOAPMessage insert(SOAPMessage request, WebServiceContext context) throws Exception {
        String xmlString = ConvertorFactory.createSOAPBodyStringConvertor("SiteInfo").convert(request);
        Map<String,String> param = new HashMap<>(1);
        param.put("xml", xmlString);

        DaoFactory.createInsertDao("siteinfo.insert").perform(param);
        return WSMessageTool.createSimpleTextMessage(
            ConfigFactory.getTextConfig().getString("db.insert.ok")
        );
    }
}

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326782102&siteId=291194637