我正在JEE6
上glassfish v3
NetBean6.9
正在RESTful web service
上工作HTML input fields
。
我的jsp文件包含下面的javascript函数。
它基本上从JSON format
读取信息并转换为onclick Ajax call
。
然后使用UPDATE
,尝试使用HTTP PUT方法发送JSON字符串。
(即我正在尝试使用REST Prototype1.7
db记录
对于我使用的js框架是var url = "/resources/inventory/" + invId + "?_method=PUT";
当我测试下面的功能时,它总是返回404,因此显示“出错”警报。
根据我的搜索,上面的1.5版本Prototype支持HTTP PUT / DELETE方法,并且这样做会将 _method 添加到请求URL,就像我正在做的那样:
http://localhost:8080/NoJSF/resources/inventory/123?_method=PUT
这将创建例如:
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
我查看了Firebug和控制台,显示该请求实际上是 POST 。不确定,但我相信这是因为Prototype使用POST隧道来实现PUT方法?
即使正在调用Ajax,我的带有JAX-RS注释的@JOST的Java文件甚至没有被调用(@GET版本正在使用单独的数据,所以这是正确的文件),因为它的方法的第一行吐出的消息没有出现所以我怀疑我的Ajax语句有一些bug或者有一些超出我思考的东西..有人能给我提示吗?
{{1}}
答案 0 :(得分:1)
他们是通过隧道传输的:
http://dobrzanski.net/2007/04/22/using-put-and-delete-methods-in-ajax-requesta-with-prototypejs/
答案 1 :(得分:1)
正如您在问题中提到的那样,默认为prototype averts PUT, DELETE,... requests。 Some people(包括我)认为这是愚蠢的行为,但由于开发人员似乎关心这一点,我们必须通过编辑请求函数本身来做到这一点(不要触及我们对prototype.js的分析!) :
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 请求(see a jsFiddle)。
答案 2 :(得分: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>
答案 3 :(得分:0)
我要感谢RienNeVaPlus的回答。我添加了额外的覆盖,以便正确发布参数和contenttype:
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方法。