это - rest контроллер




Кто-нибудь знает пример клиента RESTful, который следует принципу HATEOAS? (4)

Таким образом, к настоящему времени я понимаю, что все мы должны внедрять наши сервисы RESTful, предоставляющие представления, которые позволяют клиентам следовать принципу HATEOAS . И хотя все это имеет смысл в теории, я прочесываю сеть, чтобы найти один хороший пример кода клиента, который следует за идеей строго.

Чем больше я читаю, тем больше я начинаю чувствовать, что это академическая дискуссия, потому что никто этого не делает! Люди могут стонать все, что им нравится, о многих недостатках WS-* стека, но по крайней мере ясно, как писать клиенты: вы можете анализировать WSDL и генерировать код.

Теперь я понимаю, что это не обязательно с хорошим сервисом RESTful: вам нужно знать только об отношениях и представлениях, и вы должны иметь возможность динамически реагировать на них. Но все же, разве этот принцип не должен быть перегоняем и абстрагироваться до некоторых распространенных библиотек? Укажите информацию о представлениях и отношениях, которые вы можете получить, и получите более полезный код более высокого уровня, который вы можете использовать в своем приложении?

На самом деле это только наполовину искушенные идеи, но я просто опасаюсь, что если я сейчас погружусь и напишу правильно RESTful API, никто на самом деле не сможет его использовать! Или, по крайней мере, использование этого будет такой болью взади, потому что лишняя миля людям придется писать код клея, чтобы интерпретировать отношения и представления, которые я предоставляю.

Может ли кто-нибудь пролить свет на это с точки зрения клиента? Может ли кто-нибудь показать пример правильного динамического / реактивного клиентского кода RESTful, чтобы у меня появилась идея аудитории, на которой я на самом деле пишу? (еще лучше пример клиентского API, который предоставляет некоторые абстракции) В противном случае все его довольно теоретические ....

[edit: note, я нашел аналогичный вопрос here , на который я не думаю, что на него действительно ответил, автор был заперт заглушкой Википедии!]


Ваш веб-браузер по выбору является клиентом «чистого HATEOAS» для всего WWW.

На самом деле вопрос не имеет смысла.


Джим, я также немного расстроился из-за отсутствия примеров с клиентом RESTful после HATEOAS, поэтому я написал сообщение в блоге, в котором показан пример HATEOAS для создания и размещения заказа. Удивительно мало примеров этого с помощью API, и я понял, что это путано, но вот ссылка: Пример API с использованием Rest . Дайте мне знать, что вы думаете и что думаете, что я сделал не так.


Мы немного наполовину сделали это в нашем текущем проекте. Представления, которые мы возвращаем, генерируются из объектов домена, и клиент может запрашивать их либо в XML, JSON, либо в XHTML. Если это клиент XHTML, например Firefox, то человек видит набор исходящих ссылок из известного корневого ресурса и может просматривать все остальные ресурсы. Пока что чистый HATEOAS и отличный инструмент для разработчиков.

Но нас беспокоит производительность, когда клиент - это программа, а не человек, использующий браузер. Для наших представлений XML и JSON мы в настоящее время подавляем генерации связанных ссылок, поскольку они увеличивают размеры представлений и, следовательно, существенно влияют на сериализацию / десериализацию, использование памяти и пропускную способность. Наша другая проблема эффективности заключается в том, что при чистом HATEOAS клиентские программы будут в несколько раз увеличивать количество HTTP-запросов при их просмотре с известной ссылки на нужную им информацию. Так что лучше всего, с точки зрения эффективности , если клиенты имеют знания о закодированных в них ссылках.

Но это означает, что клиент должен сделать много конкатенации строк, чтобы сформировать URI, который подвержен ошибкам и затрудняет перераспределение пространства имен ресурсов. Поэтому мы используем систему шаблонов, в которой клиентский код выбирает шаблон и просит его развернуть себя из объекта параметра. Это тип заполнения формы.

Я очень хочу увидеть, что другие испытали на этом. HATEOAS кажется хорошей идеей, помимо аспектов производительности.

Изменить: наши шаблоны являются частью клиентской библиотеки Java, которую мы написали поверх среды Restlet . Клиентская библиотека обрабатывает все детали HTTP-запросов / ответов, заголовки HTTP, десериализацию / сериализацию, кодирование GZIP и т. Д. Это делает фактический клиентский код достаточно кратким и помогает изолировать его от некоторых изменений на стороне сервера.

В блоге Роя Филдинга о HATEOAS последовала очень интересная и интересная дискуссия.


Я написал два клиента HATEOAS, один раз на Java и один раз в Ruby, и я разделяю ваше разочарование. В обоих случаях была полная нехватка инструментальной поддержки для того, что я делал. Например, API REST, который я использовал, скажет мне, какой HTTP-метод должен использоваться для каждого HttpClient управления гипертекстом, но HttpClient не позволяет вам пройти метод, поэтому я получил следующий уродливый код (BTW весь код живет внутри пользовательская задача Ant, поэтому BuildException s):

private HttpMethod getHypermediaControl(Node href, Node method,
        NodeList children) {
    if (href == null) {
        return null;
    }
    HttpMethod control;
    if (method == null || method.getNodeValue().equals("")
            || method.getNodeValue().equalsIgnoreCase("GET")) {
        control = new GetMethod(href.getNodeValue());
    } else if (method.getNodeValue().equalsIgnoreCase("POST")) {
        control = new PostMethod(href.getNodeValue());
    } else if (method.getNodeValue().equalsIgnoreCase("PUT")) {
        control = new PutMethod(href.getNodeValue());
    } else if (method.getNodeValue().equalsIgnoreCase("DELETE")) {
        control = new DeleteMethod(href.getNodeValue());
    } else {
        throw new BuildException("Unknown/Unimplemented method "
                + method.getNodeValue());
    }
    control.addRequestHeader(accept);
    return control;
}

Это оказалось основой для использования методов утилиты клиента REST.

private HttpMethod getHypermediaControl(String path, Document source)
        throws TransformerException, IOException {

    Node node = XPathAPI.selectSingleNode(source, path);
    return getHypermediaControl(node);
}

private HttpMethod getHypermediaControl(Node node) {
    if (node == null) {
        return null;
    }
    NamedNodeMap attributes = node.getAttributes();
    if (attributes == null) {
        return null;
    }
    Node href = attributes.getNamedItem("href");
    Node method = attributes.getNamedItem("method");
    HttpMethod control = getHypermediaControl(href, method,
            node.getChildNodes());
    return control;
}

private Document invokeHypermediaControl(HttpClient client, Document node,
        final String path) throws TransformerException, IOException,
        HttpException, URIException, SAXException,
        ParserConfigurationException, FactoryConfigurationError {
    HttpMethod method = getHypermediaControl(path, node);
    if (method == null) {
        throw new BuildException("Unable to find hypermedia controls for "
                + path);
    }
    int status = client.executeMethod(method);

    if (status != HttpStatus.SC_OK) {
        log(method.getStatusLine().toString(), Project.MSG_ERR);
        log(method.getResponseBodyAsString(), Project.MSG_ERR);
        throw new BuildException("Unexpected status code ("
                + method.getStatusCode() + ") from " + method.getURI());
    }
    String strResp = method.getResponseBodyAsString();
    StringReader reader = new StringReader(strResp);
    Document resp = getBuilder().parse(new InputSource(reader));
    Node rval = XPathAPI.selectSingleNode(resp, "/");
    if (rval == null) {
        log(method.getStatusLine().toString(), Project.MSG_ERR);
        log(method.getResponseBodyAsString(), Project.MSG_ERR);
        throw new BuildException("Could not handle response");
    }
    method.releaseConnection();
    return resp;
}

С помощью этого небольшого количества кода я могу довольно легко писать клиенты, которые будут перемещать элементы гипермедиа в возвращаемых документах. Основной бит, который отсутствует, - это поддержка параметров формы. К счастью для меня все элементы управления, которые я использую, являются без параметров, кроме одного (я следую правилу три в отношении рефакторинга ). Для полноты здесь приведен фрагмент кода:

    HttpMethod licenseUpdateMethod = getHypermediaControl(
            "/license/update", licenseNode);
    if (licenseUpdateMethod == null) {
        log(getStringFromDoc(licenseNode), Project.MSG_ERR);
        throw new BuildException(
                "Unable to find hypermedia controls to get the test suites or install the license");
    } else if (license != null) {
        EntityEnclosingMethod eem = (EntityEnclosingMethod) licenseUpdateMethod;
        Part[] parts = { new StringPart("license", this.license) };
        eem.setRequestEntity(new MultipartRequestEntity(parts, eem
                .getParams()));
        int status2 = client.executeMethod(eem);
        if (status2 != HttpStatus.SC_OK) {
            log(eem.getStatusLine().toString(), Project.MSG_ERR);
            log(eem.getResponseBodyAsString(), Project.MSG_ERR);
            throw new BuildException("Unexpected status code ("
                    + eem.getStatusCode() + ") from " + eem.getURI());
        }
        eem.releaseConnection();
    }

Теперь, что нужно делать, это посмотреть на детей из /license/update чтобы выяснить, какие параметры нужно передать, но мне придется подождать, пока у меня не будет еще двух параметров, которые мне нужно будет выполнить .

BTW это после всех усилий, это было чрезвычайно удовлетворительным и легко модифицировать сервер, не влияя на клиента. Это было так хорошо, что я удивлен, что он не объявлен вне закона в некоторых штатах.





hateoas