0

我正在运行JEE6和工作。glassfish v3NetBean6.9RESTful web service

我有 jsp 文件,其中包含下面的 javascript 函数。

它基本上读取信息HTML input fields并转换为JSON format.

然后onclick Ajax call尝试使用 HTTP PUT 方法发送 JSON 字符串。(即我正在尝试UPDATE使用 REST 的数据库记录)

对于我正在使用的 js 框架是Prototype1.7

当我测试下面的函数时,它总是返回 404,因此会显示“出现问题”警报。

根据我在 1.5 版本以上的搜索原型支持 HTTP PUT/DELETE 方法,为此将_method添加到请求 URL 中,就像我正在做的那样:

var url = "/resources/inventory/" + invId + "?_method=PUT";

这将创建例如:

http://localhost:8080/NoJSF/resources/inventory/123?_method=PUT

我查看了 Firebug 和控制台,显示请求实际上是POST。不确定,但我相信这是因为 Prototype 使用 POST 隧道来实现 PUT 方法?

此外,即使正在调用 Ajax,我的带有 JAX-RS 注释和 @POST 的 Java 文件也没有被调用(@GET 版本正在处理单独的数据,所以这是正确的文件),因为它的方法的第一行吐出消息没有出现,所以我怀疑我的 Ajax 语句有一些错误,或者有超出我想象的东西.. 谁能给我提示?

function protoAjaxPut() {
            //get all fields value and store into json
            var invId = document.getElementById("invIdField").value;
            var invName = document.getElementById("invNameField").value;
            //put info into JSON format

            var jsonInput = JSON.stringify(new Array(invName));

            var url = "/resources/inventory/" + invId + "?_method=PUT";

            new Ajax.Request(url, {
                method:'put',
                postBody: jsonInput,
                ContentType: 'application/json',
                onSuccess: function(transport) {
                    var responseData = transport.responseText;
                    document.getElementById('putResponseText').innerHTML = responseData;
                },
                onFailure: function() { alert('something went wrong!')}
            })
        }//end protoAjaxPut
4

4 回答 4

1

它们是隧道式的:

http://dobrzanski.net/2007/04/22/using-put-and-delete-methods-in-ajax-requesta-with-prototypejs/

于 2010-12-18T15:54:51.567 回答
1

正如您在问题中已经提到的,原型默认避免 PUT、DELETE、... 请求有些人(包括我)认为这是愚蠢的行为,但由于开发人员似乎并不关心这一点,我们必须通过编辑请求函数本身来做到这一点(不触及我们的原型.js 的 dist!):

Ajax.Request.prototype.request = function(url) {
    this.url = url;
    this.method = this.options.method;
    var params = Object.isString(this.options.parameters) ?
        this.options.parameters :
        Object.toQueryString(this.options.parameters);

        // NOTE: THE MISSING PART WAS HERE

    if (params && this.method === 'get') {
        // when GET, append parameters to URL
        this.url += (this.url.include('?') ? '&' : '?') + params;
    }

    this.parameters = params.toQueryParams();

    try {
        var response = new Ajax.Response(this);
        if (this.options.onCreate) this.options.onCreate(response);
        Ajax.Responders.dispatch('onCreate', this, response);

        this.transport.open(this.method.toUpperCase(), this.url,
            this.options.asynchronous);

        if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);

        this.transport.onreadystatechange = this.onStateChange.bind(this);
        this.setRequestHeaders();

        this.body = this.method == 'post' ? (this.options.postBody || params) : null;
        this.transport.send(this.body);

        /* Force Firefox to handle ready state 4 for synchronous requests */
        if (!this.options.asynchronous && this.transport.overrideMimeType)
            this.onStateChange();

    }
    catch (e) {
        this.dispatchException(e);
    }
};

在原型启动后运行此代码。现在这个:

new Ajax.Request('42', {method:'PUT'});

将导致实际的HTTP PUT请求(请参阅 jsFiddle)。

于 2013-05-03T02:28:40.720 回答
0

低于使用原始 xml 而不是使用原型的作品。

当我使用原型 ajax 调用时,不允许返回 405 方法,不知道为什么。

<script type="text/javascript">
  function simplePut() {
            var xmlHttp = new XMLHttpRequest();
            var invId = document.getElementById("invIdField").value;
            var invName = document.getElementById("invNameField").value;
            //put info into JSON format

            var jsonInput = JSON.stringify(new Array(invId, invName));

            var url = "resources/inventory/" + invId;

            xmlHttp.onreadystatechange = function() {
                if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                    //out = xmlHttp.responseText;
                    document.getElementById('simple').innerHTML = xmlHttp.responseText;
                }
            }

            xmlHttp.open("put", url, true);
            //xmlHttp.open("put", "resources/inventory/1", true);
            //xmlHttp.setRequestHeader("Content-Type", "text/plain");
            xmlHttp.setRequestHeader("Content-Type", "application/json");
            xmlHttp.send(jsonInput);
        }//end protoAjaxPut
</script>

...html body 

 <body>
        <h1>Inventory page</h1>

        <table border="1" cellspacing="1" cellpadding="5">
            <th>id</th>
            <th>amount</th>
            <c:forEach items="${inventoryList}" var="inv" >
                <tr>
                    <td>${inv.id}</td>
                    <td><a href="" onclick="ajaxGet(${inv.id}); return false;">${inv.amount}</a></td>
                </tr>
            </c:forEach>
        </table>
        <hr />
        <h3>REST</h3>
        <form method="post" action="">
            Inventory ID: <input type="test" id="invIdField" readonly /><br />
            Inventory Name: <input type="text" id="invNameField" /><br />

            <input type="button" value="insert POST form" onclick="protoAjaxPost()" /><br />
            <!-- <input type="button" value="update PUT" onclick="protoAjaxPut()" /><br /> -->
            <div id="putResponseText"></div>
        </form>
        <button onclick="protoAjaxPut()">update PUT</button><br />
         <button onclick="simplePut()">call SIMPLE PUT</button><br />
         <button onclick="ajaxDelete()">HTTP DELETE</button><br />
         <div id="simple"></div>
    </body>
于 2010-12-19T23:46:45.833 回答
0

我要感谢 RienNeVaPlus 的回答。为了正确发布参数和内容类型,我添加了额外的覆盖:

Ajax.Request.prototype.setRequestHeaders = function() {
        var headers = {
          'X-Requested-With': 'XMLHttpRequest',
          'X-Prototype-Version': Prototype.Version,
          'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
        };

        if (this.method == 'post' || this.method=='put') {
          headers['Content-type'] = this.options.contentType +
            (this.options.encoding ? '; charset=' + this.options.encoding : '');

          /* Force "Connection: close" for older Mozilla browsers to work
           * around a bug where XMLHttpRequest sends an incorrect
           * Content-length header. See Mozilla Bugzilla #246651.
           */
          if (this.transport.overrideMimeType &&
              (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
                headers['Connection'] = 'close';
        }

        if (typeof this.options.requestHeaders == 'object') {
          var extras = this.options.requestHeaders;

          if (Object.isFunction(extras.push))
            for (var i = 0, length = extras.length; i < length; i += 2)
              headers[extras[i]] = extras[i+1];
          else
            $H(extras).each(function(pair) { headers[pair.key] = pair.value });
        }

        for (var name in headers) {
          this.transport.setRequestHeader(name, headers[name]);
        }
      };

仅针对 PUT 方法进行了测试。

于 2013-06-03T08:34:46.083 回答