- 浏览: 1200928 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
insistboy:
写的太棒了,受不了
WebLogic11g-创建域(Domain) -
goldyeah:
厉害了 困扰我大半个月的问题解决了 谢谢博主
WebLogic11g-单双向SSL配置(以Springside3为例) -
zy315351965:
404伤不起
开源流程引擎Snaker -
nannan408:
双向的时候谷歌提示“不接受您的登录证书,或者您可能没有提供登录 ...
WebLogic11g-单双向SSL配置(以Springside3为例) -
一颗赛艇:
不成功啊。启动有问题 <Security> < ...
WebLogic11g-单双向SSL配置(以Springside3为例)
在Axis源码分析-Web服务部署(二)中
http://dead-knight.iteye.com/blog/732961
已经将两种web部署方式进行了分析
其中涉及了服务端AxisServlet初始化。以及对get、post请求的监听。
服务端处理请求实际上就是AxisServlet中doPost所做的事情。
AxisServlet中doPost源码:
doPost主要任务为:
1.构造MessageContext并进行初始化
通过createMessageContext方法完成MessageContext构造,通过setProperty完成属性设置;
2.构造请求消息体
通过Message requestMsg =new Message(req.getInputStream(),false,
req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE),
req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION));
完成;其构造方法依赖SOAPPart实例,并将请求输入流req.getInputStream()即:org.apache.catalina.connector.CoyoteInputStream(Tomcat环境)设置为SOAPPart的currentMessage;
3.AxisServer引擎调用
通过invoke方法完成对各Handler链的一次调用;后面详细分析。
4.将处理完成的响应消息体发送至客户端。
AxisServer引擎invoke调用分析
通过以上代码可见、整个Axis引擎处理是通过一系列的handler chain进行invoke。其处理顺序为http requestFlow(URLMapper、HTTPAuthHandler)----global requestFlow(JWSHandler)----service requestFlow responseFlow(接口服务)
----global responseFlow----http responseFlow
那么依次分析各Handler处理过程。
一、transport配置Handler
1.org.apache.axis.handlers.http.URLMapper:
URLMapper主要任务将客户端调用服务对应的SOAPService设置到MessageContext中
AxisEngine:
由于在初始化AxisServlet已经对server-config.wsdd配置进行实例化至WSDDDeployment中,并由FileProvider引用。
FileProvider实际上将getService任务交给deployment完成:
deployment在AxisEngine初始化时已经持有server-config.wsdd中各种配置信息,如:transport、handler、globalConfiguration、service,并将各类配置存储至HashMap缓存中。
WSDDDeployment:
可见,deployment只是从存储service信息的HashMap(services)中取出WSDDServie实例(该实例在初始化时即WSDDDeployment构造函数中,已经对配置总所有service服务进行了注册),然后通过WSDDService返回SOAPService。WSDDService只是一种数据结构,用于保存service配置的属性信息;SOAPService是一种Handler,可参与整个Handler Chain中,并对MessageContext进行处理。
(SOAPService) s.getInstance(this)实现如下(实现类为:WSDDDeployableItem):
WSDDservice是WSDDDeployableItem的子类,WSDDservice的getInstance方法由父类WSDDDeployableItem完成。
WSDDservice-makeNewInstance:
至此,整个URLMapper的Handler已经处理完成。其重要任务就是将缓存中的service信息构造成SOAPService Handler,并设置到Messagecontext中。SOAPService实际上是个Handler Chain即:SimpleTargetedChain,该链中包含了service中配置的requestFlow、provider、responseFlow。当执行SOAPService的invoke方法时,通过配置依次执行handler。
2.org.apache.axis.handlers.http.HTTPAuthHandler:
HTTPAuthHandler主要是处理针对Basic验证方式的web应用,简单地将http请求中的用户名、密码信息设置到MessageContext中。
二、globalConfiguration配置handler
WSDDDeployment中的getGlobalRequest方法
WSDDRequestFlow中的makeNewInstance由父类WSDDChain实现
org.apache.axis.handlers.JWSHandler
在上一篇中已经分析了JWSHandler的用途,主要是针对jws部署方式的处理。
由于JWS部署方式是没有service配置信息的,无法在WSDDDeployment缓存中获取,故通过JWSHandler进行特殊处理。
由于jws方式没有service信息,则通过这个handler完成SOAPService的构造。
三、service配置handler
回到AxisServer中
如果在service中配置了requestFlow,则先执行request handler 的invoke
如果部署的service未配置handler,则直接执行provider handler的invoke
RPCProvider是JavaProvider子类,其invoke由父类JavaProvider实现。
JavaProvider:
RPCProvider:
由于时间问题,后面部分分析的比较粗糙
希望以后看到这个,还能记得。
http://dead-knight.iteye.com/blog/732961
已经将两种web部署方式进行了分析
其中涉及了服务端AxisServlet初始化。以及对get、post请求的监听。
服务端处理请求实际上就是AxisServlet中doPost所做的事情。
AxisServlet中doPost源码:
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0; String soapAction = null; MessageContext msgContext = null; if (isDebug) { log.debug("Enter: doPost()"); } if (tlog.isDebugEnabled()) { t0 = System.currentTimeMillis(); } Message responseMsg = null; String contentType = null; try { //获取服务端引擎。初始化工作在init方法已完成 AxisEngine engine = getEngine(); if (engine == null) { // !!! should return a SOAP fault... ServletException se = new ServletException(Messages.getMessage("noEngine00")); log.debug("No Engine!", se); throw se; } res.setBufferSize(1024 * 8); // provide performance boost. /** get message context w/ various properties set */ //MessageContext初始化以及属性设置 msgContext = createMessageContext(engine, req, res); // ? OK to move this to 'getMessageContext', // ? where it would also be picked up for 'doGet()' ? if (securityProvider != null) { if (isDebug) { log.debug("securityProvider:" + securityProvider); } msgContext.setProperty(MessageContext.SECURITY_PROVIDER, securityProvider); } /* Get request message */ //构造请求消息体。req.getInputStream()即为请求输入流 //http request header+xml(soap格式) Message requestMsg = new Message(req.getInputStream(), false, req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE), req.getHeader(HTTPConstants. HEADER_CONTENT_LOCATION)); // Transfer HTTP headers to MIME headers for request message. MimeHeaders requestMimeHeaders = requestMsg.getMimeHeaders(); for (Enumeration e = req.getHeaderNames(); e.hasMoreElements(); ) { String headerName = (String) e.nextElement(); for (Enumeration f = req.getHeaders(headerName); f.hasMoreElements(); ) { String headerValue = (String) f.nextElement(); requestMimeHeaders.addHeader(headerName, headerValue); } } if (isDebug) { log.debug("Request Message:" + requestMsg); /* Set the request(incoming) message field in the context */ /**********************************************************/ } msgContext.setRequestMessage(requestMsg); String url = HttpUtils.getRequestURL(req).toString(); msgContext.setProperty(MessageContext.TRANS_URL, url); // put character encoding of request to message context // in order to reuse it during the whole process. String requestEncoding; try { requestEncoding = (String) requestMsg.getProperty(SOAPMessage. CHARACTER_SET_ENCODING); if (requestEncoding != null) { msgContext.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, requestEncoding); } } catch (SOAPException e1) { } try { soapAction = getSoapAction(req); if (soapAction != null) { msgContext.setUseSOAPAction(true); msgContext.setSOAPActionURI(soapAction); } msgContext.setSession(new AxisHttpSession(req)); if (tlog.isDebugEnabled()) { t1 = System.currentTimeMillis(); } if (isDebug) { log.debug("Invoking Axis Engine."); //here we run the message by the engine } //AxisServer执行invoke engine.invoke(msgContext); if (isDebug) { log.debug("Return from Axis Engine."); } if (tlog.isDebugEnabled()) { t2 = System.currentTimeMillis(); } responseMsg = msgContext.getResponseMessage(); } catch (AxisFault fault) { //log and sanitize processAxisFault(fault); configureResponseFromAxisFault(res, fault); responseMsg = msgContext.getResponseMessage(); if (responseMsg == null) { responseMsg = new Message(fault); ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()). getMessage().setMessageContext(msgContext); } } catch (Exception e) { //other exceptions are internal trouble responseMsg = msgContext.getResponseMessage(); res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); responseMsg = convertExceptionToAxisFault(e, responseMsg); ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()). getMessage().setMessageContext(msgContext); } catch (Throwable t) { logException(t); //other exceptions are internal trouble responseMsg = msgContext.getResponseMessage(); res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); responseMsg = new Message(new AxisFault(t.toString(),t)); ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()). getMessage().setMessageContext(msgContext); } } catch (AxisFault fault) { processAxisFault(fault); configureResponseFromAxisFault(res, fault); responseMsg = msgContext.getResponseMessage(); if (responseMsg == null) { responseMsg = new Message(fault); ((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()). getMessage().setMessageContext(msgContext); } } if (tlog.isDebugEnabled()) { t3 = System.currentTimeMillis(); } /* Send response back along the wire... */ /***********************************/ if (responseMsg != null) { // Transfer MIME headers to HTTP headers for response message. MimeHeaders responseMimeHeaders = responseMsg.getMimeHeaders(); for (Iterator i = responseMimeHeaders.getAllHeaders(); i.hasNext(); ) { MimeHeader responseMimeHeader = (MimeHeader) i.next(); res.addHeader(responseMimeHeader.getName(), responseMimeHeader.getValue()); } // synchronize the character encoding of request and response String responseEncoding = (String) msgContext.getProperty( SOAPMessage.CHARACTER_SET_ENCODING); if (responseEncoding != null) { try { responseMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, responseEncoding); } catch (SOAPException e) { } } //determine content type from message response contentType = responseMsg.getContentType(msgContext. getSOAPConstants()); sendResponse(contentType, res, responseMsg); } else { // No content, so just indicate accepted res.setStatus(202); } }
doPost主要任务为:
1.构造MessageContext并进行初始化
通过createMessageContext方法完成MessageContext构造,通过setProperty完成属性设置;
2.构造请求消息体
通过Message requestMsg =new Message(req.getInputStream(),false,
req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE),
req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION));
完成;其构造方法依赖SOAPPart实例,并将请求输入流req.getInputStream()即:org.apache.catalina.connector.CoyoteInputStream(Tomcat环境)设置为SOAPPart的currentMessage;
3.AxisServer引擎调用
通过invoke方法完成对各Handler链的一次调用;后面详细分析。
4.将处理完成的响应消息体发送至客户端。
AxisServer引擎invoke调用分析
public void invoke(MessageContext msgContext) throws AxisFault { String hName = null ; Handler h = null ; MessageContext previousContext = getCurrentMessageContext(); try { setCurrentMessageContext(msgContext); hName = msgContext.getStrProp( MessageContext.ENGINE_HANDLER ); if ( hName != null ) { if ( (h = getHandler(hName)) == null ) { ClassLoader cl = msgContext.getClassLoader(); try { log.debug( Messages.getMessage("tryingLoad00", hName) ); Class cls = ClassUtils.forName(hName, true, cl); h = (Handler) cls.newInstance(); } catch( Exception e ) { h = null ; } } if( tlog.isDebugEnabled() ) { t1=System.currentTimeMillis(); } if ( h != null ) h.invoke(msgContext); else throw new AxisFault( "Server.error", Messages.getMessage("noHandler00", hName), null, null ); } } else { hName = msgContext.getStrProp(MessageContext.TRANSPORT); if ( hName != null ) { if ((h = hr.find( hName )) != null ) { h.invoke(msgContext); } else { log.error(Messages.getMessage("noTransport02", hName)); } } else { defaultTransport.invoke(msgContext); } //首先对server-config.wsdd中http传输协议配置的requestFlow //handler进行处理,如:URLMapper、HTTPAuthHandler hName = msgContext.getTransportName(); SimpleTargetedChain transportChain = null; if ( hName != null && (h = getTransport( hName )) != null ) { if (h instanceof SimpleTargetedChain) { transportChain = (SimpleTargetedChain)h; h = transportChain.getRequestHandler(); if (h != null) h.invoke(msgContext); } } //处理全局请求handler chain if ((h = getGlobalRequest()) != null ) { h.invoke(msgContext); } //处理所配置接口服务中的requestflow请求handler chain h = msgContext.getService(); if (h == null) { Message rm = msgContext.getRequestMessage(); rm.getSOAPEnvelope().getFirstBody(); h = msgContext.getService(); if (h == null) throw new AxisFault("Server.NoService", Messages.getMessage("noService05", "" + msgContext.getTargetService()), null, null ); } initSOAPConstants(msgContext); try { h.invoke(msgContext); } catch (AxisFault ae) { if ((h = getGlobalRequest()) != null ) { h.onFault(msgContext); } throw ae; } //处理全局响应handler chain if ((h = getGlobalResponse()) != null) h.invoke(msgContext); //处理http传输的响应handler chain if (transportChain != null) { h = transportChain.getResponseHandler(); if (h != null) h.invoke(msgContext); } } } catch (AxisFault e) { throw e; } catch (Exception e) { // Should we even bother catching it ? throw AxisFault.makeFault(e); } finally { // restore previous state setCurrentMessageContext(previousContext); } if (log.isDebugEnabled()) { log.debug("Exit: AxisServer::invoke"); } }
通过以上代码可见、整个Axis引擎处理是通过一系列的handler chain进行invoke。其处理顺序为http requestFlow(URLMapper、HTTPAuthHandler)----global requestFlow(JWSHandler)----service requestFlow responseFlow(接口服务)
----global responseFlow----http responseFlow
那么依次分析各Handler处理过程。
一、transport配置Handler
1.org.apache.axis.handlers.http.URLMapper:
public void invoke(MessageContext msgContext) throws AxisFault { log.debug("Enter: URLMapper::invoke"); if ( msgContext.getService() == null ) { String path = (String)msgContext.getProperty(HTTPConstants.MC_HTTP_SERVLETPATHINFO); if ((path != null) && (path.length() >= 1)) { //rules out the cases of path="", path=null if(path.startsWith("/")) path = path.substring(1); //设置此次请求目标服务 msgContext.setTargetService( path ); } } log.debug("Exit: URLMapper::invoke"); }
URLMapper主要任务将客户端调用服务对应的SOAPService设置到MessageContext中
public void setTargetService(String tServ) throws AxisFault { log.debug("MessageContext: setTargetService(" + tServ+")"); if (tServ == null) { setService(null); } else { try { //首先从AxisEngine获取SOAPService服务 //通过SOAPService设置对应的MessageContext属性 setService(getAxisEngine().getService(tServ)); } catch (AxisFault fault) { // If we're on the client, don't throw this fault... if (!isClient()) { throw fault; } } } targetService = tServ; }
AxisEngine:
public SOAPService getService(String name) throws AxisFault { try { //委托至FileProvider返回SOAPService return config.getService(new QName(null, name)); } catch (ConfigurationException e) { try { return config.getServiceByNamespaceURI(name); } catch (ConfigurationException e1) { throw new AxisFault(e); } } }
由于在初始化AxisServlet已经对server-config.wsdd配置进行实例化至WSDDDeployment中,并由FileProvider引用。
FileProvider实际上将getService任务交给deployment完成:
public SOAPService getService(QName qname) throws ConfigurationException { SOAPService service = deployment.getService(qname); if (service == null) { throw new ConfigurationException(Messages.getMessage("noService10", qname.toString())); } return service; }
deployment在AxisEngine初始化时已经持有server-config.wsdd中各种配置信息,如:transport、handler、globalConfiguration、service,并将各类配置存储至HashMap缓存中。
WSDDDeployment:
public SOAPService getService(QName name) throws ConfigurationException { //从缓存中取出WSDDService WSDDService s = (WSDDService) services.get(name); if (s != null) { //通过WSDDService结构返回SOAPService实例 return (SOAPService) s.getInstance(this); } return null; }
可见,deployment只是从存储service信息的HashMap(services)中取出WSDDServie实例(该实例在初始化时即WSDDDeployment构造函数中,已经对配置总所有service服务进行了注册),然后通过WSDDService返回SOAPService。WSDDService只是一种数据结构,用于保存service配置的属性信息;SOAPService是一种Handler,可参与整个Handler Chain中,并对MessageContext进行处理。
(SOAPService) s.getInstance(this)实现如下(实现类为:WSDDDeployableItem):
public final Handler getInstance(EngineConfiguration registry) throws ConfigurationException { //是否为单态实例 if (scope == SCOPE_SINGLETON) { synchronized (this) { if (singletonInstance == null) singletonInstance = getNewInstance(registry); } return singletonInstance; } return getNewInstance(registry); } private Handler getNewInstance(EngineConfiguration registry) throws ConfigurationException { QName type = getType(); if (type == null || WSDDConstants.URI_WSDD_JAVA.equals(type.getNamespaceURI())) { //该任务交给具体子类完成 return makeNewInstance(registry); } else { return registry.getHandler(type); } }
WSDDservice是WSDDDeployableItem的子类,WSDDservice的getInstance方法由父类WSDDDeployableItem完成。
WSDDservice-makeNewInstance:
public Handler makeNewInstance(EngineConfiguration registry) throws ConfigurationException { if (cachedService != null) { return cachedService; } // 初始化类型映射. initTMR(); Handler reqHandler = null; //获取Service中配置的requestFlow Handler WSDDChain request = getRequestFlow(); if (request != null) { //存在requestFlow时,返回对应的Handler //具体操作如WSDDService.getInstance方法 reqHandler = request.getInstance(registry); } Handler providerHandler = null; if (providerQName != null) { try { //此处重要!!!在配置service时, //<service name="Version" provider="java:RPC"> //其中的provider即为处理Messagecontext实现方式 //RPC:org.apache.axis.providers.java.RPCProvider providerHandler = WSDDProvider.getInstance(providerQName,this,registry); } catch (Exception e) { throw new ConfigurationException(e); } if (providerHandler == null) throw new WSDDException( Messages.getMessage("couldntConstructProvider00")); } Handler respHandler = null; WSDDChain response = getResponseFlow(); if (response != null) { //存在requestFlow时,返回对应的Handler respHandler = response.getInstance(registry); } //构造SOAPService实例,实际上SOAPService为SimpleTargetedChain子类 SOAPService service = new SOAPService(reqHandler, providerHandler,respHandler); //设置SOAPService属性 service.setStyle(style); service.setUse(use); service.setServiceDescription(desc); service.setHighFidelityRecording(!streaming); service.setSendType(sendType); if ( getQName() != null ) service.setName(getQName().getLocalPart()); service.setOptions(getParametersTable()); service.setRoles(roles); service.setEngine(((WSDDDeployment)registry).getEngine()); if (use != Use.ENCODED) { // If not encoded, turn off multi-refs and prefer // not to sent xsi:type and xsi:nil service.setOption(AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE); service.setOption(AxisEngine.PROP_SEND_XSI, Boolean.FALSE); } // Set handlerInfoChain if (_wsddHIchain != null) { HandlerInfoChainFactory hiChainFactory = _wsddHIchain.getHandlerChainFactory(); service.setOption(Constants.ATTR_HANDLERINFOCHAIN, hiChainFactory); } AxisEngine.normaliseOptions(service); WSDDFaultFlow [] faultFlows = getFaultFlows(); if (faultFlows != null && faultFlows.length > 0) { FaultableHandler wrapper = new FaultableHandler(service); for (int i = 0; i < faultFlows.length; i++) { WSDDFaultFlow flow = faultFlows[i]; Handler faultHandler = flow.getInstance(registry); wrapper.setOption("fault-" + flow.getQName().getLocalPart(), faultHandler); } } try { service.getInitializedServiceDesc(MessageContext.getCurrentContext()); } catch (AxisFault axisFault) { throw new ConfigurationException(axisFault); } cachedService = service; return service; }
至此,整个URLMapper的Handler已经处理完成。其重要任务就是将缓存中的service信息构造成SOAPService Handler,并设置到Messagecontext中。SOAPService实际上是个Handler Chain即:SimpleTargetedChain,该链中包含了service中配置的requestFlow、provider、responseFlow。当执行SOAPService的invoke方法时,通过配置依次执行handler。
2.org.apache.axis.handlers.http.HTTPAuthHandler:
public void invoke(MessageContext msgContext) throws AxisFault { log.debug("Enter: HTTPAuthHandler::invoke"); /* Process the Basic Auth stuff in the headers */ /***********************************************/ String tmp = (String)msgContext.getProperty(HTTPConstants.HEADER_AUTHORIZATION); if ( tmp != null ) tmp = tmp.trim(); if ( tmp != null && tmp.startsWith("Basic ") ) { String user=null ; int i ; tmp = new String( Base64.decode( tmp.substring(6) ) ); i = tmp.indexOf( ':' ); if ( i == -1 ) user = tmp ; else user = tmp.substring( 0, i); msgContext.setUsername( user ); log.debug( Messages.getMessage("httpUser00", user) ); if ( i != -1 ) { String pwd = tmp.substring(i+1); if ( pwd != null && pwd.equals("") ) pwd = null ; if ( pwd != null ) { msgContext.setPassword( pwd ); log.debug( Messages.getMessage("httpPassword00", pwd) ); } } } log.debug("Exit: HTTPAuthHandler::invoke"); }
HTTPAuthHandler主要是处理针对Basic验证方式的web应用,简单地将http请求中的用户名、密码信息设置到MessageContext中。
二、globalConfiguration配置handler
//AxisServer中执行global invoke if ((h = getGlobalRequest()) != null ) { h.invoke(msgContext); }
WSDDDeployment中的getGlobalRequest方法
public Handler getGlobalRequest() throws ConfigurationException { if (globalConfig != null) { //取出当前requestFlow WSDDRequestFlow reqFlow = globalConfig.getRequestFlow(); if (reqFlow != null) //返回Handler Chain return reqFlow.getInstance(this); } return null; }
WSDDRequestFlow中的makeNewInstance由父类WSDDChain实现
public Handler makeNewInstance(EngineConfiguration registry) throws ConfigurationException { //new SimpleChain Chain c = new org.apache.axis.SimpleChain(); for (int n = 0; n < handlers.size(); n++) { WSDDHandler handler = (WSDDHandler)handlers.get(n); Handler h = handler.getInstance(registry); if ( h != null ) //向chain中添加handler c.addHandler(h); else throw new ConfigurationException("……"); } return c; }
org.apache.axis.handlers.JWSHandler
在上一篇中已经分析了JWSHandler的用途,主要是针对jws部署方式的处理。
由于JWS部署方式是没有service配置信息的,无法在WSDDDeployment缓存中获取,故通过JWSHandler进行特殊处理。
由于jws方式没有service信息,则通过这个handler完成SOAPService的构造。
//先从jws的soapservices缓存中获取 SOAPService rpc = (SOAPService)soapServices.get(clsName); if (rpc == null) { //构造SOAPService,provider为:RPCProvider rpc = new SOAPService(new RPCProvider()); rpc.setName(clsName); rpc.setOption(RPCProvider.OPTION_CLASSNAME, clsName ); rpc.setEngine(msgContext.getAxisEngine()); String allowed = (String)getOption(RPCProvider.OPTION_ALLOWEDMETHODS); if (allowed == null) allowed = "*"; rpc.setOption(RPCProvider.OPTION_ALLOWEDMETHODS, allowed); String scope = (String)getOption(RPCProvider.OPTION_SCOPE); if (scope == null) scope = Scope.DEFAULT.getName(); rpc.setOption(RPCProvider.OPTION_SCOPE, scope); rpc.getInitializedServiceDesc(msgContext); //缓存当前SOAPService soapServices.put(clsName, rpc); } rpc.setEngine(msgContext.getAxisEngine()); rpc.init(); // ?? msgContext.setService( rpc );
三、service配置handler
回到AxisServer中
//将URLMapper 或者JWSHandler handler中设置的service取出 h = msgContext.getService(); if (h == null) { Message rm = msgContext.getRequestMessage(); rm.getSOAPEnvelope().getFirstBody(); if (h == null) ……; } if( tlog.isDebugEnabled() ) { t3=System.currentTimeMillis(); } //初始化soap信息 //比较复杂,通过sax解析request Inputstream。 //有空时再补充说明 initSOAPConstants(msgContext); try { //执行service handler chain,包含provider h.invoke(msgContext); } catch (AxisFault ae) { if ((h = getGlobalRequest()) != null ) { h.onFault(msgContext); } throw ae; }
如果在service中配置了requestFlow,则先执行request handler 的invoke
如果部署的service未配置handler,则直接执行provider handler的invoke
RPCProvider是JavaProvider子类,其invoke由父类JavaProvider实现。
JavaProvider:
public void invoke(MessageContext msgContext) throws AxisFault { if (log.isDebugEnabled()) log.debug("Enter: JavaProvider::invoke (" + this + ")"); String serviceName = msgContext.getTargetService(); Handler service = msgContext.getService(); //service对应的类名 //jws:即通过javac编译后加载的class类 //wsdd:即通过className配置的class类 String clsName = getServiceClassName(service); if ((clsName == null) || clsName.equals("")) { throw new AxisFault("Server.NoClassForService", Messages.getMessage("noOption00", getServiceClassNameOptionName(), serviceName), null, null); } IntHolder scope = new IntHolder(); Object serviceObject = null; try { //通过clsName新建service对应的class实例对象 //未配置scope属性,则默认为request 生命周期 //scope为session属性,则将该对象存储至session中 serviceObject = getServiceObject(msgContext, service, clsName, scope); SOAPEnvelope resEnv = null; OperationDesc operation = msgContext.getOperation(); if (operation != null && OperationType.ONE_WAY.equals(operation.getMep())) { msgContext.setResponseMessage(null); } else { Message resMsg = msgContext.getResponseMessage(); if (resMsg == null) { resEnv = new SOAPEnvelope(msgContext.getSOAPConstants(),msgContext.getSchemaVersion()); //构造响应消息体response Message resMsg = new Message(resEnv); String encoding = XMLUtils.getEncoding(msgContext); resMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, encoding); msgContext.setResponseMessage( resMsg ); } else { resEnv = resMsg.getSOAPEnvelope(); } } Message reqMsg = msgContext.getRequestMessage(); SOAPEnvelope reqEnv = reqMsg.getSOAPEnvelope(); //实际处理交给子类RPCProvider实现 processMessage(msgContext, reqEnv, resEnv, serviceObject); } catch( SAXException exp ) { entLog.debug( Messages.getMessage("toAxisFault00"), exp); Exception real = exp.getException(); if (real == null) { real = exp; } throw AxisFault.makeFault(real); } catch( Exception exp ) { entLog.debug( Messages.getMessage("toAxisFault00"), exp); AxisFault fault = AxisFault.makeFault(exp); //make a note if this was a runtime fault, for better logging if (exp instanceof RuntimeException) { fault.addFaultDetail(Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION, "true"); } throw fault; } finally { // If this is a request scoped service object which implements // ServiceLifecycle, let it know that it's being destroyed now. if (serviceObject != null && scope.value == Scope.REQUEST.getValue() && serviceObject instanceof ServiceLifecycle) { ((ServiceLifecycle)serviceObject).destroy(); } } if (log.isDebugEnabled()) log.debug("Exit: JavaProvider::invoke (" + this + ")"); }
RPCProvider:
public void processMessage(MessageContext msgContext, SOAPEnvelope reqEnv, SOAPEnvelope resEnv, Object obj) throws Exception { if (log.isDebugEnabled()) { log.debug("Enter: RPCProvider.processMessage()"); } SOAPService service = msgContext.getService(); ServiceDesc serviceDesc = service.getServiceDescription(); RPCElement body = getBody(reqEnv, msgContext); Vector args = null; try { args = body.getParams(); } catch (SAXException e) { if(e.getException() != null) throw e.getException(); throw e; } int numArgs = args.size(); OperationDesc operation = getOperationDesc(msgContext, body); // Create the array we'll use to hold the actual parameter // values. We know how big to make it from the metadata. Object[] argValues = new Object[operation.getNumParams()]; // A place to keep track of the out params (INOUTs and OUTs) ArrayList outs = new ArrayList(); // Put the values contained in the RPCParams into an array // suitable for passing to java.lang.reflect.Method.invoke() // Make sure we respect parameter ordering if we know about it // from metadata, and handle whatever conversions are necessary // (values -> Holders, etc) for (int i = 0; i < numArgs; i++) { RPCParam rpcParam = (RPCParam) args.get(i); Object value = rpcParam.getObjectValue(); // first check the type on the paramter ParameterDesc paramDesc = rpcParam.getParamDesc(); // if we found some type info try to make sure the value type is // correct. For instance, if we deserialized a xsd:dateTime in // to a Calendar and the service takes a Date, we need to convert if (paramDesc != null && paramDesc.getJavaType() != null) { // Get the type in the signature (java type or its holder) Class sigType = paramDesc.getJavaType(); // Convert the value into the expected type in the signature value = JavaUtils.convert(value, sigType); rpcParam.setObjectValue(value); if (paramDesc.getMode() == ParameterDesc.INOUT) { outs.add(rpcParam); } } // Put the value (possibly converted) in the argument array // make sure to use the parameter order if we have it if (paramDesc == null || paramDesc.getOrder() == -1) { argValues[i] = value; } else { argValues[paramDesc.getOrder()] = value; } if (log.isDebugEnabled()) { log.debug(" " + Messages.getMessage("value00", "" + argValues[i])); } } // See if any subclasses want a crack at faulting on a bad operation // FIXME : Does this make sense here??? String allowedMethods = (String) service.getOption("allowedMethods"); checkMethodName(msgContext, allowedMethods, operation.getName()); // Now create any out holders we need to pass in int count = numArgs; for (int i = 0; i < argValues.length; i++) { // We are interested only in OUT/INOUT ParameterDesc param = operation.getParameter(i); if(param.getMode() == ParameterDesc.IN) continue; Class holderClass = param.getJavaType(); if (holderClass != null && Holder.class.isAssignableFrom(holderClass)) { int index = count; // Use the parameter order if specified or just stick them to the end. if (param.getOrder() != -1) { index = param.getOrder(); } else { count++; } // If it's already filled, don't muck with it if (argValues[index] != null) { continue; } argValues[index] = holderClass.newInstance(); // Store an RPCParam in the outs collection so we // have an easy and consistent way to write these // back to the client below RPCParam p = new RPCParam(param.getQName(), argValues[index]); p.setParamDesc(param); outs.add(p); } else { throw new AxisFault(Messages.getMessage("badOutParameter00", "" + param.getQName(), operation.getName())); } } // OK! Now we can invoke the method Object objRes = null; try { //该方法完成服务调用 //即通过反射调用执行service中className、以及客户端指定的operation指定的操作名称 //obj:className所对应的实例 //argValues:操作方法包含的参数 objRes = invokeMethod(msgContext, operation.getMethod(), obj, argValues); } catch (IllegalArgumentException e) { String methodSig = operation.getMethod().toString(); String argClasses = ""; for (int i = 0; i < argValues.length; i++) { if (argValues[i] == null) { argClasses += "null"; } else { argClasses += argValues[i].getClass().getName(); } if (i + 1 < argValues.length) { argClasses += ","; } } log.info(Messages.getMessage("dispatchIAE00", new String[]{methodSig, argClasses}), e); throw new AxisFault(Messages.getMessage("dispatchIAE00", new String[]{methodSig, argClasses}), e); } /** If this is a one-way operation, there is nothing more to do. */ if (OperationType.ONE_WAY.equals(operation.getMep())) return; //根据返回值构造响应消息体 RPCElement resBody = createResponseBody(body, msgContext, operation, serviceDesc, objRes, resEnv, outs); resEnv.addBodyElement(resBody); }
由于时间问题,后面部分分析的比较粗糙
希望以后看到这个,还能记得。
发表评论
-
Eclipse4.3创建Maven项目
2013-07-20 11:56 12327Eclipse4.3版本(Kepler)的发布,对于开发Mav ... -
Eclipse使用Maven构建web项目
2013-04-03 21:45 605051.创建Maven项目: 点击“File”菜单,或者通过工具栏 ... -
Eclipse安装Maven插件
2013-04-03 20:52 2987161.工具下载: Eclipse4.2 jee版本(这里使用最新 ... -
Spring Integration-File Adapter使用
2012-05-31 10:32 8122File Adapter主要应用于企业应用程序之间共享文件系统 ... -
apache反向代理问题
2012-03-12 11:15 2055apache反向代理出现的问题: 一、问题描述: 用户访问时经 ... -
struts1实现aop
2010-12-28 15:35 2022项目05年正式上线,所用struts框架版本较低,在此环境实现 ... -
Axis源码分析-Web服务部署(二)
2010-08-09 14:44 65961.服务部署: 1)即时发布 编写java类,去掉包名称,将. ... -
Axis源码分析-客户端调用(一)
2010-08-06 15:36 130921.手工编码调用服务,如: Str ... -
quartz源码解读
2010-07-22 12:41 7126quartz针对web应用提供两种方式配置【servlet、l ... -
IE6下动态嵌入iframe无法显示
2009-03-18 21:07 5745为了实现提示框效果,从而使用动态嵌入iframe方案, ...
相关推荐
Axis1.4源码分析 Axis是Apache软件基金会的一个开源项目,它是一个基于Java的Web服务框架,专门用于实现SOAP(简单对象访问协议)和WSDL(Web服务描述语言)。Axis1.4是该框架的一个稳定版本,为开发人员提供了构建...
1. **SOAP处理**:了解Axis如何处理SOAP消息,包括解析请求、生成响应,以及错误处理机制。 2. **WSDL解析**:学习如何从WSDL文件中提取服务信息,包括操作、消息类型、端点地址等。 3. **Web服务部署**:熟悉Axis...
在描述中提到的博文链接中,博主可能会分享一个具体的示例,展示如何在Axis2服务端实现文件接收和处理。通常,这涉及到以下几个步骤: 1. **创建服务类**:定义一个服务类,该类包含一个或多个方法来处理文件上传...
3. **源码分析**: 文件“ws_server”可能包含服务端的源代码。服务端代码通常涉及以下部分: - 定义服务接口:声明服务提供的操作和参数类型。 - 实现服务接口:编写处理请求的实际逻辑。 - 部署服务:将服务...
然后,通过实例化这些接口并调用相应方法,就可以向服务发送请求并接收响应。 在"myaxis"这个压缩包中,可能包含了创建和运行Web服务所需的全部文件,如服务端的Java源码、WSDL文件、部署描述符(web.xml)、以及...
2. **Axis1架构**:熟悉Axis1的工作流程,包括服务发布、请求处理和响应生成。 3. **服务部署**:学习如何使用wsdd文件来配置和部署Web服务。 4. **代码生成**:了解如何从WSDL生成Java服务端和客户端代码。 5. **...
通过研究这个服务,我们可以学习如何利用Axis创建一个能接收请求、处理业务逻辑并返回响应的Web服务。 在实际操作中,首先,开发者需要安装和配置Axis环境,然后定义服务接口,比如一个发送短信的函数。接着,使用...
使用Axis2提供的命令行工具或Web服务测试客户端,如SOAPUI,发送带有附件的请求,并检查响应是否正确包含附件。 【文件使用】"使用Axis2传输附件.txt" 该文本文件很可能包含了详细的代码示例,指导读者如何在实际...
四、源码分析 在压缩包中的"webservice源码"可能包括以下几个部分: 1. 服务端接口:定义Web服务提供的操作,通常是一个Java接口,方法名对应WSDL中的操作。 2. 服务端实现:实现服务端接口,处理实际业务逻辑。 3. ...
4. **接收响应**:服务端处理请求后,会返回一个包含天气数据的SOAP响应。客户端接收到这个响应并解析其中的数据。 5. **显示结果**:解析后的天气信息被展示给用户,可能是在命令行界面或者一个简单的图形用户界面...
- 服务端接收到请求后处理业务逻辑,并返回响应。 - 客户端接收并解析响应,完成交互。 3. **Web服务的实现技术**: - JAX-WS(Java API for XML Web Services):Java平台上的标准Web服务栈,用于创建和消费Web...
它提供了一种高效、灵活和可扩展的方式来处理Web服务,包括服务端和客户端的实现。 接下来,**MyEclipse** 是一个强大的Java EE集成开发环境,它是Eclipse的商业版本,提供了丰富的特性来支持Java、Web、JSP、...
需按照WSDL文件中描述的接口和服务地址,构造SOAP请求并发送至服务端,处理返回的响应。 #### 五、WebService的应用场景 WebService广泛应用于企业级应用集成、B2B通信、SOA架构等领域,是现代软件体系结构的重要...
8. **源码分析**:学习博主提供的源码,理解服务端如何定义和暴露服务,客户端如何生成代理并调用服务。 9. **部署与发布**:Web服务部署到应用服务器,如Tomcat,供其他系统通过网络调用。 10. **错误处理与调试*...
2. 服务器端:服务器接收到请求后,解析XML文档,执行对应的方法,并将结果封装成XML响应。 3. 库支持:大多数编程语言都有现成的XML-RPC库,简化了开发工作。例如,Python有SimpleXMLRPCServer和xmlrpclib,Java有...
对于SOAP,CXF可以处理WSDL(Web服务描述语言)来生成服务端和客户端代码。对于RESTful服务,CXF提供了基于JAX-RS(Java API for RESTful Web Services)的实现。 2. **协议绑定**:CXF不仅限于HTTP,还支持其他...
5. 源码分析:通过分析具体的WebService实现源码,加深对WebService工作原理的理解,这可能包括服务端的部署、处理请求和返回响应的流程,以及客户端的调用逻辑。 6. 工具支持:探讨各种开发工具,如Apache Axis、...
- 实现这个服务可能涉及创建WSDL文件来描述服务接口,编写服务端代码来处理请求,并部署服务到一个Web服务器上,如Apache Tomcat。 - 客户端则可以使用SOAP请求来调用这个服务,获取返回的问候消息。 6. **源码...
请求发送后,服务端接收到请求,解析SOAP消息,执行对应的方法,并返回响应。 总的来说,这个项目涵盖了Web服务的基本工作流程,包括服务的发布、调用和交互。通过这个项目,你可以学习到如何在实际开发中创建和...
标题中的“几种监控SOAP消息的方法”意味着我们将探讨如何在IT环境中监测基于...在实际操作中,结合标签中的“源码”和“工具”,理解这些工具的工作原理,并能根据项目需求灵活应用,是每个IT专业人员必备的技能之一。