English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Princípio de execução do Web Service:详细介绍

     Usando o feriado de Qingming, revisei o conteúdo relacionado ao Web Service e fiz uma breve resumo de seu princípio. Para os amigos que precisam e para mim mesmo para referência futura. Se o artigo tiver algo errado, por favor, faça sugestões valiosas para que possamos nos inspirar mutuamente.

      No serviço web, devemos primeiro entender o significado dos termos relevantes: WSDL, UDDI ... A introdução aos termos relevantes não será repetida aqui, focando na teoria.
No serviço web, existem três papéis: provedor de serviço, solicitante de serviço e intermediário de serviço, e suas relações são mostradas na figura1-1Mostrado

    Implementar um serviço web completo envolve os seguintes passos:

   ◆ O provedor de serviço web projeta e implementa o serviço web, publica o serviço web debugado pelo intermediário do serviço web e registra no registro UDDI; (Publicação)

   ◆ O solicitante do serviço web solicita serviços específicos ao intermediário do serviço web, e o intermediário consulta o registro UDDI para encontrar serviços que atendem aos requisitos do solicitante; (Descoberta)

   ◆ O intermediário do serviço web retorna informações de descrição de serviço que atendem aos requisitos ao solicitante do serviço web, essas informações são escritas em WSDL e podem ser lidas por todos os dispositivos que suportam serviços web; (Descoberta)

   ◆ Gera mensagens SOAP correspondentes com base na descrição de serviço retornada pelo intermediário do serviço web (WSDL) e envia-as ao provedor de serviço web para chamar o serviço web; (Ligação)

   ◆ O provedor de serviço web executa o serviço web correspondente com base na mensagem SOAP e retorna o resultado do serviço ao solicitante do serviço web. (Ligação)

  

Figura1-1 Arquitetura do serviço web

     Nota: O papel do WSDL é um documento de especificação de serviço web. O solicitante do serviço web gera mensagens SOAP correspondentes com base neste WSDL, e o provedor do serviço realiza a ligações após receber a mensagem de solicitação SOAP.

     O seguinte código é a configuração servlet no web.xml

  <!-- Ao definir parâmetros de inicialização ou URLs personalizadas para servlets ou páginas JSP, é necessário nomear primeiro o servlet ou a página JSP. O elemento Servlet é usado para realizar essa tarefa. -->
  <servlet>
  <servlet-name>UserService</servlet-name>
  <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
  <!-- 标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法;正数的值越小,该servlet的优先级越高,应用启动时就越先加载 -->
  <load-on-startup>1</load-on-startup>
  </servlet>
  <!-- 服务器一般为servlet提供一个缺省的URL:http://host/webAppPrefix/servlet/ServletName。
   但是,常常会更改这个URL,以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时,使用servlet-mapping元素。 -->
  <servlet-mapping>
   <servlet-name>UserService</servlet-name>
   <!-- 描述了相对于Web应用的根目录的URL。url-pattern元素的值必须以斜杠(/)起始。 -->
   <url-pattern>/user</url-pattern>
  </servlet-mapping>
  红色代码部分很重要,会在Web容器启动的时候加载相应的servlet。绿色部分为该服务的外部接口。以此找到相应的jax-ws.xml文件(如下所示)
  <endpoint name="UserPort" implementation="cn.ujn.service.UserService"
    url-pattern="/user">
  </endpoint>

    进而绑定到相关的相应的实现类cn.ujn.service.UserService中。客户端发送的SOAP请求消息消息体body中包含有客户端所请求的方法名和参数信息。

    以下为客户端封装的soap消息体(以Json方式与服务端进行数据传输)(SOAP Rerquest Envelope):

  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://ujn.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-  <soapenv:Body>
-  <q0:login>
     <arg0>{"username":"shq","password":"shq"}</arg0>
 </q0:login>
 </soapenv:Body>
 </soapenv:Envelope>

以下为SOAP1.1协议调用Web服务

/** 
* 通过SOAP1.1协议调用Web服务 
* 
* text/xml 这是基于soap1.1协议 
* 
* @param wsdl WSDL路径 
* @param method方法名 
* @param namespace命名空间 
* @param headerParameters 头参数 
* @param bodyParameters  体参数 
* @param isBodyParametersNS 体参数是否有命名空间 
* @return String 
* @throws Exception 
*/ 
public static String invokeBySoap11(String wsdl, String method, 
String namespace, Map<String, String> headerParameters, 
Map<String, String> bodyParameters, boolean isBodyParametersNS) 
throws Exception { 
StringBuffer soapOfResult = null; 
// 去除 ?wsdl,获取方法列表 
int length = wsdl.length(); 
wsdl = wsdl.substring(0, length - 5; 
//以字符串为参数创建URL实例 
URL url = new URL(wsdl); 
//创建连接 
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
//设置请求方式 
conn.setRequestMethod("POST"); 
//如果打算使用URL连接进行输入,则将DoInput标志设置为true 
conn.setDoInput(true); 
//如果打算使用URL连接进行输出,则将DoInput标志设置为true 
conn.setDoOutput(true); 
//主要是设置HttpURLConnection请求头里面的属性(K-V) 
conn.setRequestProperty("Content",-Type", "text/xml; charset=utf-8"); 
//获取输入流(相对于客户端来说,使用的是OutputStream) 
OutputStream out = conn.getOutputStream(); 
// 获取soap1.1版本消息 
StringBuilder sb = new StringBuilder(); 
sb.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"  
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" "); 
sb.append("xmlns:ns0=\"" + namespace + "\""); 
sb.append(">"); 
//拼装消息头 
if (headerParameters != null) { 
sb.append("<soap:Header>"); 
for (Entry<String, String> headerParameter : headerParameters 
.entrySet()) { 
sb.append("<ns0:"); 
sb.append(headerParameter.getKey()); 
sb.append(">"); 
sb.append(headerParameter.getValue()); 
sb.append("</ns0:"); 
sb.append(headerParameter.getKey()); 
sb.append(">"); 
} 
sb.append("</soap:Header>"); 
} 
//拼装消息体 
sb.append("<soap:Body><ns0:"); 
sb.append(method); 
sb.append(">"); 
// 输入参数 
if (bodyParameters != null) { 
for (Entry<String, String> inputParameter : bodyParameters 
.entrySet()) { 
if (isBodyParametersNS) { 
sb.append("<ns0:"); 
sb.append(inputParameter.getKey()); 
sb.append(">"); 
sb.append(inputParameter.getValue()); 
sb.append("</ns0:"); 
sb.append(inputParameter.getKey()); 
sb.append(">"); 
} else { 
sb.append("<"); 
sb.append(inputParameter.getKey()); 
sb.append(">"); 
sb.append(inputParameter.getValue()); 
sb.append("</"); 
sb.append(inputParameter.getKey()); 
sb.append(">"); 
} 
} 
} 
sb.append("</ns0:"); 
sb.append(method); 
sb.append("></soap:Body></soap:Envelope>"); 
//测试用 
System.out.println(sb.toString()); 
//Escreve a mensagem SOAP (para o cliente, é usado out.write()) 
out.write(sb.toString().getBytes()); 
//Obtém a resposta do servidor 
int code = conn.getResponseCode(); 
if (code == 200) { 
InputStream is = conn.getInputStream(); 
byte[] b = new byte[1024]; 
int len = 0; 
soapOfResult = new StringBuffer(); 
//Lê um número específico de bytes do fluxo de entrada e os armazena no array de缓冲区 b. Devolve o número real de bytes lidos como inteiro 
//Se não houver mais bytes disponíveis no final do fluxo devido a um erro, o valor de retorno -1; 
while ((len = is.read(b)) != -1) { 
//Converte o array de bytes em uma string usando o conjunto de caracteres nomeado.  
String s = new String(b, 0, len, "UTF-8"); 
soapOfResult.append(s); 
} 
} 
conn.disconnect(); 
return soapOfResult == null ? null : soapOfResult.toString(); 
} 

    Nota: Após o cliente enviar a mensagem de solicitação SOAP, ele fica em estado de bloqueio até que o servidor retorne o código de status.

    A seguir está a resposta do servidor (Encerramento de Resposta SOAP):

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
-<S:Body>
-<ns2:loginResponse xmlns:ns2="http://ujn.cn/">
 <return>1</return>
</ns2:loginResponse>
 </S:Body>
</S:Envelope>

    Após a receção dos dados JSON enviados pelo servidor, o cliente realiza as operações de análise correspondentes. Exemplo:

// A análise do protocolo SOAP (A análise DOM pode ser usada apenas para documentos do tipo XML, enquanto as mensagens SOAP adotam o formato de dados XML) 
Document doc = XmlUtil.string2Doc(result);}} 
Element ele = (Element) doc.getElementsByTagName("return").item(0); 
Métodos usados string2Doc() método corpo如下: 
public static Document string2Doc(String str) { 
//Converter o documento XML em uma árvore DOM 
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
Document document = null; 
DocumentBuilder build; 
if (str == null || str.equals("")) { 
return null; 
} 
try { 
InputStream bais = new ByteArrayInputStream(str.getBytes("UTF"-8")); 
build = factory.newDocumentBuilder(); 
//Parse the content of the given InputStream as an XML document and return a new DOM Document object.  
document = build.parse(bais); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
return document; 
} 

    De acordo com o resultado de volta, o cliente realiza o processamento correspondente.

    Aqui está o princípio básico de funcionamento do serviço web.

    Obrigado por ler, espero que isso ajude a todos, obrigado pelo apoio ao site!

Você também pode gostar