- 浏览: 1192315 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
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 12214Eclipse4.3版本(Kepler)的发布,对于开发Mav ... -
Eclipse使用Maven构建web项目
2013-04-03 21:45 603451.创建Maven项目: 点击“File”菜单,或者通过工具栏 ... -
Eclipse安装Maven插件
2013-04-03 20:52 2985641.工具下载: Eclipse4.2 jee版本(这里使用最新 ... -
Spring Integration-File Adapter使用
2012-05-31 10:32 8043File Adapter主要应用于企业应用程序之间共享文件系统 ... -
apache反向代理问题
2012-03-12 11:15 1988apache反向代理出现的问题: 一、问题描述: 用户访问时经 ... -
struts1实现aop
2010-12-28 15:35 1967项目05年正式上线,所用struts框架版本较低,在此环境实现 ... -
Axis源码分析-Web服务部署(二)
2010-08-09 14:44 65021.服务部署: 1)即时发布 编写java类,去掉包名称,将. ... -
Axis源码分析-客户端调用(一)
2010-08-06 15:36 129961.手工编码调用服务,如: Str ... -
quartz源码解读
2010-07-22 12:41 7080quartz针对web应用提供两种方式配置【servlet、l ... -
IE6下动态嵌入iframe无法显示
2009-03-18 21:07 5693为了实现提示框效果,从而使用动态嵌入iframe方案, ...
相关推荐
Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来...
内容索引:JAVA源码,综合应用,J2me游戏,PNG,图形处理 这是个J2ME控制台程序,它能剔除PNG文件中的非关键数据段,减少文件大小从而达到压缩图片的目的。而图片的质量并不会受到损失。使用时候只需在控制台窗口执行...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...
以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 ...