2012-02-06 45 views
0

我想通过JSON GET将变量wordId传递到我的webapp中的Spring-mvc控制器。我没有问题与静态url使用JSON,但我不知道什么是最好的做法与动态/参数的URL。 使用JSP和Spring-mvc的动态JSON网址

控制器部分:

@RequestMapping(value="/delete/{wordId}", method = RequestMethod.GET) 
@ResponseStatus(HttpStatus.NO_CONTENT) 
public void deleteWord(@RequestParam ("wordId") Long wordId, Principal principal) { 

    wordService.deleteWord(wordId, principal.getName()); 
} 

JSP部分:

<c:choose> 
    <c:when test="${not empty accountWords}"> 
     <c:forEach items="${accountWords}" var="word" varStatus="status"> 
      <li class="word"> 
       <input type="checkbox" name="word" class="word_checkbox" value="" /> 
       <span>${word.word}</span> 
       <s:url value="/words/delete/${word.wordId}" var="delete_word"></s:url> 
       <a href="${delete_word}"><img src="resources/gfx/delete.png" /></a> 
      </li> 
     </c:forEach> 
    </c:when> 
</c:choose> 

jQuery的部分到目前为止:

$("li.word a").click(function(e) { 
    e.preventDefault(); 
    var deleteUrl = ... 
    $.getJSON(deleteUrl, function() { 

    }); 
}); 

你能告诉我应该如何我的jQuery部分传递wordId变量到控制器?我可以从标签的href属性获取url,但我想要有相对的url。我stucked ...

UPDATE:

$("#testJSON").click(function() { 
    $.getJSON("admin/json.html", function(w) { 
     $('#span_json').html("w.wordId + "<br>" + w.word); 
    }); 
}); 
+0

我只用静态URL [上面已更新]尝试过,并没有问题,但我不知道如何使用参数来做到这一点。 – 2012-02-06 23:28:20

回答

1

由于wordID的是URL的一部分,你应该使用@PathVariable注释,而不是@RequestParam。

另外,由于您询问了最佳实践,因此我应该指出,对不具有幂等性的操作使用HTTP GET方法并不是一个好习惯。换句话说,您不应该使用GET来更改服务器端数据的操作,例如从数据库中删除记录。

正确执行记录删除的HTTP方法是HTTP DELETE方法。一些旧版本的浏览器不支持DELETE,所以你会发现很多代码都是用POST代替删除的。不过,我认为这不是什么大问题。有关更多详细信息,请参见http://annevankesteren.nl/2007/10/http-method-support

使用DELETE而不是GET不仅仅是为了“以正确的方式来做事”的好主意......它实际上可以帮助您避免一些令人讨厌的问题。有一些浏览器插件可以通过预先获取页面上的所有链接并将它们存储在本地缓存中来加速人们在网络上的体验。如果用户安装了这些插件之一,插件将“点击”您网页上的每个删除链接!另外,如果您正在构建面向公众的应用程序,搜索引擎抓取工具也将遵循您的删除链接。我已经看到了这种情况发生在现实世界中,所以相信我这是一个真正的担忧!

另一个RESTful最佳实践是使用遵循/名词/ {id}模式的URL,并使用HTTP方法作为动词。因此,使用GET代替/ delete/{wordId},最好使用带有DELETE的/ word/{wordId}。

与所有我建议的变化你的代码应该是这样的:

控制器

@RequestMapping(value="/word/{wordId}", method = RequestMethod.DELETE) 
@ResponseStatus(HttpStatus.NO_CONTENT) 
public void deleteWord(@PathVariable ("wordId") Long wordId, Principal principal) { 
    wordService.deleteWord(wordId, principal.getName()); 
} 

不幸的是,jQuery和JSP变得有点麻烦,当您使用DELETE,而不是GET。GET是确实很诱人,因为你可以建立一个链接,你这样做是这样的:

<a href="${delete_word}"><img src="resources/gfx/delete.png" /></a> 

为了让浏览器使用DELETE取而代之的是,你要么需要有它的方法是删除表单,或者您需要调用一些执行Ajax DELETE的JavaScript。 (既然你已经使用Ajax,这是该技术我会去。)我会改变你的链接到一个按钮启动:

<button class="delete-button" id="delete_${delete_word}"><img src="resources/gfx/delete.png" /></button> 

这将创建一个按钮,保存这个词的ID你想要在按钮本身的ID中删除。不知何故,您需要将每个按钮的单词ID删除,这是一种方法。我见过其他人将ID放在按钮旁边的隐藏区域。 (说实话,我从来没有喜欢这些技术,我希望有人跟着我的回答,以更好的方式来做到这一点。)

无论如何,随着你的JSP体内的变化,你还想添加一些处理点击全部删除按钮的jQuery。 (请注意,我把一类名为“删除键”按钮,这样便很容易在jQuery的参考。)

的jQuery:

$(".delete-button").on("click", function() { 
    var wordId = $(this).attr("id").substring("delete_".length); 
    $.ajax({ 
     type: "DELETE", 
     url: "/word/" + wordId, 
     success: function() { 
      // Maybe put some code here that deletes the <li> ? 
     } 
    }); 
}); 

注意我是如何提取的文字标识从按钮的id属性被点击:

var wordId = $(this).attr("id").substring("delete_".length); 

当然,你也可以这样来做:

var wordId = $(this).attr("id").substring(7); 

我更喜欢这样做的第一种方式,因为它自我记录子字符串正在做什么。在第二个例子中,数字7是一个幻数,并不能解释发生了什么。

+0

尼斯回答Michael,欢迎来到StackOverflow。 – digitaljoel 2012-02-08 20:36:14

+0

真棒回答!非常有启发性,我非常感谢你的帮助:)。我只有一个小问题。你喜欢PUT而不是POST来通过ajax添加新单词吗? [与上面描述的情况相反的东西]或者仅仅是POST就足够了。 – 2012-02-09 23:33:40

+0

@Mariusz:应该如何使用PUT和POST有一点区别,这在http://jcalcote.wordpress.com/2008/10/16/put-or-post-the-rest-of -故事/ 。简而言之,PUT和POST之间的差异归结为服务器如何在相同的URL和相同的参数下处理两个HTTP请求。当两次调用会创建两条记录或返回一个错误时,我们应该使用POST,而当重复调用没有效果时,我们会使用PUT。或者,你可以做几乎每个人都做的事情,只需忽略PUT并对所有RESTful创建使用POST。 :-) – 2012-02-10 08:34:46