English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Во время清明节小长假, я освежил в памяти相关信息 о веб-сервисе и кратко总结了 его принцип работы. Это может быть полезно для друзей и myself в будущем. Если в статье есть ошибки, пожалуйста, дайте ценные советы, чтобы мы могли вместе учиться.
В веб-сервисе мы должны сначала понять значение связанных терминов: WSDL, UDDI... Более подробное описание терминов не рассматривается, акцент делается на принципах.
В веб-сервисе существуют три роли: провайдер услуги, запрашивающий услугу и посредник, их отношения показаны на рис. 1-1
Реализация полного веб-сервиса включает следующие шаги:
◆ Предоставляющий веб-сервис разработчик проектирует и реализует веб-сервис, а после отладки и проверки корректности публикует его через посредника веб-сервиса и регистрирует в UDDI-регистраторе; (публикация)
◆ Заявитель веб-сервиса запрашивает у посредника веб-сервиса определенный сервис, посредник выполняет запрос к центру регистрации UDDI, чтобы найти сервис, соответствующий запросу; (Обнаружение)
◆ Посредник веб-сервиса возвращает заявителю информацию о веб-сервисе, которая соответствует условиям, информация записана в WSDL и может быть прочитана любыми машинами, поддерживающими веб-сервисы; (Обнаружение)
◆ Используя информацию о веб-сервисе, возвращаемую посредником веб-сервиса (WSDL), создается соответствующее сообщение SOAP и отправляется поставщику веб-сервиса для вызова веб-сервиса; (Привязка)
◆ Поставщик веб-сервиса выполняет соответствующий веб-сервис по сообщениям SOAP и возвращает результат веб-заявителю. (Привязка)
Рис. 1-1 Архитектура веб-сервиса
Примечание: Функция WSDL - это руководство по веб-сервису. Заявитель веб-сервиса создает соответствующие сообщения SOAP на основе этого WSDL, а поставщик услуг выполняет привязку после получения запроса SOAP.
Следующий код является конфигурацией сервлета в файле web.xml
<!-- При определении инициализационных параметров или настройке URL для сервлета или JSP-страницы сначала необходимо命名 сервлет или JSP-страницу. Элемент сервлета используется для выполнения этой задачи. --> <servlet> <servlet-name>UserService</servlet-name> <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class> <!-- Маркирует, загружается ли сервлет контейнером при запуске (инстанцируется и вызывается метод init(); значение больше нуля, чем меньше значение, тем выше приоритет сервлета, и он загружается раньше при запуске приложения). --> <load-on-startup>1</load-on-startup> </servlet> <!-- Сервер, как правило, предоставляет сервлету стандартный URL: http://host/webAppPrefix/servlet/ServletName. --> Но часто URL изменяется, чтобы сервлет мог получить доступ к инициализационным параметрам или easierely обрабатывать относительные URL. При изменении стандартного URL используется элемент servlet-mapping. --> <servlet-mapping> <servlet-name>UserService</servlet-name> <!-- Описывает URL по отношению к корневой директории веб-приложения. Значение элемента url-pattern должно начинаться с обратной косой черты (/). --> <url-pattern>/user</url-pattern> </servlet-mapping> Часть красного кода очень важна, она будет загружена соответствующий servlet при запуске веб-контейнера. Часть зеленого цвета представляет внешнюю интерфейс этой службы. Таким образом, можно найти соответствующий файл jax-ws.xml (как показано ниже) <endpoint name="UserPort" implementation="cn.ujn.service.UserService" url-pattern="/user"> </endpoint>
Далее это привязывается к соответствующему реализованному классу cn.ujn.service.UserService. Тело SOAP-запроса, отправляемого клиентом, содержит имя метода и информацию о параметрах, запрашиваемых клиентом.
Ниже приведено клиентское封装енное сообщение 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
/** * Вызов веб-службы через протокол SOAP1.1 * * 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-соединение для вывода, то установите флаг DoOutput в 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()); //写入SOAP消息(相对于客户端来说,使用的是out.write()) out.write(sb.toString().getBytes()); // Получает ответ сервера int code = conn.getResponseCode(); if (code == 200) { InputStream is = conn.getInputStream(); byte[] b = new byte[1024]; int len = 0; soapOfResult = new StringBuffer(); // Читает определенное количество байтов из потока ввода и хранит их в массиве буфера b. Возвращает количество фактически прочитанных байтов в виде целого числа // Если因为没有 доступных байтов в конце потока, то возвращается значение -1; while ((len = is.read(b)) != -1) { // Преобразует массив байтов в строку с использованием указанного набора символов. String s = new String(b, 0, len, "UTF-8"); soapOfResult.append(s); } } conn.disconnect(); return soapOfResult == null ? null : soapOfResult.toString(); }
Примечание: после отправки клиентом запроса SOAP запрос блокируется до получения сервером кода состояния.
Ниже приведен ответ сервера (обертка ответа 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>
Клиент, получив данные JSON от сервера, выполняет соответствующие операции по разбору. Например:
// Разбор протокола SOAP (DOM-разбор используется только для разборки документов типа XML, а сообщения SOAP используют формат данных XML) Document doc = XmlUtil.string2Doc(result); Element ele = (Element) doc.getElementsByTagName("return").item(0); Метод中使用到的string2Doc() метод Körper如下: public static Document string2Doc(String str) { //将XML文档解析成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; }
На основе возвращенного результата клиент выполняет соответствующую обработку.
的上文是web服务的基本工作原理。
Спасибо за чтение, надеюсь, это поможет вам, спасибо за поддержку нашего сайта!