【发布时间】:2016-03-13 23:54:42
【问题描述】:
我正在尝试在我的 spring mvc web 应用程序的每个页面的导航栏中添加一个搜索表单,就像 stackoverflow 上的那个一样,我遇到了问题。现在我在我的几个页面上有一个可用的搜索功能,使用典型的 mvc 表单。我获取输入的字符串并将一个名为“searchString”的变量存储在我创建的名为“searchForm.java”的对象中。然后我尝试使用 spring data 的 findbycontaing 方法在数据库中查询输入的字符串,然后将该结果放在模型上,然后使用 thymeleaf 将其表示在视图上。但是我认为导航栏应该使用 ajax 来完成,因为它在每个页面和其他表单的页面上。
所以我想我正在将提交给导航栏中搜索表单的字符串发送到控制器,在那里我在存储库中查询它以带回搜索结果,然后我尝试将搜索结果放在模型上,但我什么也没得到,它所做的只是将我重定向到搜索页面。我可能没有多大意义,但我会展示我的代码,如果有人可以让我知道我是否以正确的方式解决我的问题,以及你们是否在我的代码中看到任何错误。提前致谢。
所以这是我提交表单的 ajax 和 jquery。
<script th:inline="javascript">
/*<![CDATA[*/
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
$(document).ready(function(){
$("#searchButton").on("click", function(ev) {
$.ajax({
url : "navSearch",
type : "post",
data : {
"newSearch" : $("#newSearch").val()
},
success : function(data) {
console.log(data);
},
error : function() {
console.log("There was an error");
}
});
});
});
/*]]>*/
</script>
这里可能存在问题,因为在 chrome 开发人员工具的控制台中,在重定向之前,会很快弹出一条消息,上面写着uncaught TypeError: Cannot read property 'toLowerCase' of undefined,它来自jquery.min.js:5,所以这可能是我的问题,但我不知道如何解决这个问题,到目前为止我一直在寻找答案,但没有运气。
这是我的html表单,我认为这应该不是问题,但谁知道呢,所以我还是把它放上去。我在这个视图中使用百里香。
<form action = "setSearch" class="navbar-form navbar-right">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search" id="newSearch"></input>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
</div>
<button type="submit" class="btn btn-default" id="searchButton">Search</button>
</form>
这是我的 searchForm.java 类,我将要查询的字符串临时存储在数据库中。
public class SearchForm {
private String searchString;
public String getSearchString()
{
return searchString;
}
public void setSearchString(String searchString)
{
this.searchString = searchString;
}
}
这是我的控制器,我正在尝试处理 ajax 提交并将其作为 setSearch.html 页面上的搜索结果返回。我在这里想的是,表单中的字符串“newSearch”可以使用 Spring Data 查询方法进行匹配,然后能够将其返回并将其添加到模型中,但它不起作用,它只是将我重定向到没有数据的 /searchSet 页面,因为这是表单操作所在的位置,这就是我告诉它返回的内容。所以老实说,我不确定是否有任何数据达到这一点。
@RequestMapping(value="setSearch/navSearch", method=RequestMethod.POST)
public @ResponseBody String navSearch (@RequestParam String newSearch, ModelMap model)
{
List<QuestionAnswerSet> questionAnswerSetByQuestion = (List<QuestionAnswerSet>) questionAnswerSetRepo.findByQuestionContaining(newSearch);
model.put("searchResult", questionAnswerSetByQuestion);
return "setSearch";
}
这是我在控制器中使用的有效搜索方法的示例,我在 /searchSet 页面上的常规表单上使用它,没有 ajax。
@RequestMapping(value="/setSearch", method=RequestMethod.GET)
public String searchGet(ModelMap model) {
SearchForm searchForm = new SearchForm();
model.put("searchForm", searchForm);
return "setSearch";
}
@RequestMapping(value="/setSearch", method=RequestMethod.POST)
public String searchPost(@ModelAttribute SearchForm searchForm, ModelMap model) {
List<QuestionAnswerSet> questionAnswerSetByQuestion = (List<QuestionAnswerSet>) questionAnswerSetRepo.findByQuestionContaining(searchForm.getSearchString());
model.put("searchResult", questionAnswerSetByQuestion);
return "setSearch";
}
更新
我已将表单中的代码从<button type="submit" class="btn btn-default" id="searchButton">Search</button> 更改为<button type="button" class="btn btn-default" id="searchButton">Search</button>,现在我得到了之前的Uncaught TypeError: Cannot read property 'toLowerCase' of undefined,页面没有任何反应。
更新
我现在可以毫无问题地提交 ajax 表单,我在标头中缺少元标记,所以 csrf 没有正确提交,所以现在我在 chrome 开发人员工具控制台中收到此错误XHR Loaded (navSearch - 405 Method Not Allowed - 7.265999971423298ms - 634B)
更新
现在一切都在 Ajax 端运行,我需要调整我的 url 以匹配我在控制器上的请求映射中的 url,它可以很好地运行所有代码。但是整体搜索功能还是不行,这是我更新的控制器。
我知道我的问题是我返回的是字符串而不是对象,但我不确定如何返回对象然后将 url 重定向到 /setSearch 页面。它正在运行代码并在控制台中返回一个字符串“setSearch”,因为我在控制器的末尾告诉它。
@RequestMapping(value="/setSearch/search", method=RequestMethod.POST)
public @ResponseBody String search (@RequestParam String newSearch, ModelMap model)
{
List<QuestionAnswerSet> questionAnswerSetByQuestion = (List<QuestionAnswerSet>) questionAnswerSetRepo.findByQuestionContaining(newSearch);
model.put("searchResult", questionAnswerSetByQuestion);
return "setSearch";
}
这是我的工作 ajax
<script th:inline="javascript">
/*<![CDATA[*/
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
$(document).ready(function(){
$("#searchButton").on("click", function(ev) {
$.ajax({
url : "/setSearch/search",
type : "post",
data : {
"newSearch" : $("#newSearch").val()
},
success : function(data) {
console.log(data);
},
error : function() {
console.log("There was an error");
}
});
});
});
/*]]>*/
</script>
【问题讨论】:
-
几件事,搜索应该是 GET 而不是 POST 请求(坚持 Restfull 原则)。接下来单击控制台本身的错误并查看它的来源。它来自javascript还是您的服务器代码?然后把有问题的代码部分复制下来放到题中。
-
错误来自
jquery.min.js:5 -
请求发布了吗?我在您发布的代码中没有发现任何问题。可能是由其他代码引起的。
-
这很奇怪,但现在它说它在第9026行,当我点击它时它与这个部分有关
setRequestHeader: function( name, value ) { var lname = name.toLowerCase(); if ( !state ) { name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; requestHeaders[ name ] = value; } -
我明白了,所以问题出在
xhr.setRequestHeader(header, token);。可能没有定义名为_csrf和csrf_header的元数据?
标签: ajax spring-mvc spring-data thymeleaf