一尘不染

如何通过AJAX(Spring MVC)上的新模型重新加载JSP的特定部分?

jsp

我在用什么

  • 的Tomcat 7.0.56
  • JAVA 1.8
  • springMVC
  • jQuery的

目标是什么?

我正在实现内容目录。
例如,用户搜索特定的名称或电话号码。然后,联系人列表显示在页面左侧。在右侧,应显示所选联系人的详细信息。

问题出在哪里?

我的问题在于显示细节。

我的代码:

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html >
<%@ include file="includes/header.jsp" %>
<body>
    <div class="pageContainer container-fluid">
        <div class="row">
            <%@ include file="searchBar.jsp" %>
        </div>
        <div class="row">
            <div class="containerOverView col-lg-5 col-md-6 col-sm-12 col-xs-12">
                <%@ include file="overView.jsp" %>
            </div>
            <div class="containerDetailView col-lg-7 col-md-6 col-sm-12 col-xs-12">
                <%@ include file="detailView.jsp" %>
            </div>
        </div>
    </div>
</body>
</html>

detailView.jsp

<ul class="flex-container">
    <li class="flex-item-photo">Photo</li>
    <li class="flex-item-pdetails">Personal Details</li>
    <li class="flex-item-cdetails">Company Details</li>
    <li class="flex-item-map">Map:
        ${detailSearchResult.name}
    </li>

</ul>

MainController.java

// Delivers the refresh-information for the ajax request, when the detail view gets reloaded
    @RequestMapping(value = "/refreshDetail", method = RequestMethod.POST)
    @ResponseBody
    private String refreshDetailView(HttpServletRequest hsr, @RequestParam String id, ModelMap model){
        model.addAttribute("detailSearchResult", Dao.getDetailViewData(id));
        return "detailView";
    }

main.js

$(document).ready(function(){
$(".overViewListEmployee").click(function () {
    var id = $(this).find(".overViewEmployeeID").text();
    console.log("Works: " + id + ".");
    $.ajax({
        type: "POST",
        accepts: "text/plain",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        url: "/refreshDetail",
        data: ({"id" : id}),
        success: function(response) {
            $(".containerDetailView").html(response);
        }
    });
});
});

到底什么不起作用?

在我看来,ajax请求并未真正得到有效的响应。根据我的理解,ajax接受各种响应,但是以某种方式,当我调试JavaScript时,它说响应具有
响应错误:未定义响应

错误代码:

使用上面的代码:
400: 无法加载资源:服务器以状态400(错误请求)响应

当我在 main.js中 注释掉以下 行时

 //contentType: "application/json; charset=utf-8",

406 :( 不可接受)

有什么用?(由于调试)

当我调试代码时,我看到id的值正确进入了Controller并且该函数Dao.getDetailView(id)正常工作。因此,这实际上只是响应的问题。

我还尝试了什么?

我不确定是否可以那样工作,方法是返回一个字符串,其名称应为 detailView.jsp 页面的名称,该字符串应重新加载,因为我不知道添加属性的
模型 是否也随之运行,并且在 index.jsp中 呈现(其中包括 detailView.jsp )。
因此,我还尝试将Controller-Function设置如下:

// Delivers the refresh-information for the ajax request, when the detail view gets reloaded
    @RequestMapping(value = "/refreshDetail", method = RequestMethod.POST)        
    private ModelAndView refreshDetailView(@RequestParam String id, ModelMap model){
        model.addAttribute("detailSearchResult", Dao.getDetailViewData(id));
        return new ModelAndView("detailView");
    }

并从 main.js 删除此行:

accepts: "text/plain",

我还尝试通过返回模型:

return new ModelAndView("detailView", model);

我不经常使用JavaScript,因此这可能是一个非常愚蠢而明显的错误,但我似乎找不到。我从字面上尝试了所有可以找到的东西,但看起来好像卡在这里了。

我真的很感谢在这种情况下的任何帮助:)


更新:

main.js

$(".overViewListEmployee").click(function () {
    var id = parseInt($(this).find(".overViewEmployeeID").text());
    console.log("Works: " + id + ".");
    $.ajax({
        type: "POST",
        accept:"text/html",
        //contentType: "application/json; charset=utf-8",
        dataType: "html",
        url: "/refreshDetail",
        data: ({"id": id}),
        success: function(response) {
            $(".containerDetailView").html(response);
        }
    });
});

MainController.java

// Delivers the refresh-information for the ajax request, when the detail view gets reloaded
    @RequestMapping(value = "/refreshDetail", method = RequestMethod.POST, produces = MediaType.TEXT_HTML_VALUE)
    @ResponseBody
    private ModelAndView refreshDetailView(HttpServletRequest hsr, @RequestBody IdObject id, ModelMap model){
        model.addAttribute("detailSearchResult", Dao.getDetailViewData(id.getId()));
        return new ModelAndView("detailView", model);
    }

IdObject.java

public class IdObject {
int id;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}
}

现在,控制器完全没有到达-仍然出现 415 错误。


更新2:

WebInit.java(之前)

@Configuration
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer{

protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[]{RootConfig.class};
}

protected Class<?>[] getServletConfigClasses() {
    return new Class<?>[]{WebConfig.class};
}

protected String[] getServletMappings() {
    return new String[]{"/"};
}
}

WebInit.java(之后)

@Configuration
public class WebInit implements WebApplicationInitializer{

@Override
public void onStartup(ServletContext container) {
    // Create the 'root' Spring application context
    AnnotationConfigWebApplicationContext rootContext =
            new AnnotationConfigWebApplicationContext();
    rootContext.register(WebConfig.class);

    // Manage the lifecycle of the root application context
    container.addListener(new ContextLoaderListener(rootContext));

    // Create the dispatcher servlet's Spring application context
    AnnotationConfigWebApplicationContext dispatcherContext =
            new AnnotationConfigWebApplicationContext();
    dispatcherContext.register(RootConfig.class);

    // Register and map the dispatcher servlet
    ServletRegistration.Dynamic dispatcher =
            container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("/");
}
}

现在,我不确定这是否是您的意思,但是从我的阅读中了解的内容与使用的含义@AnnotationDrivenConfig相同AnnotationConfigWebApplicationContext。而且,由于我是使用纯Java配置来完成此工作的,所以这就是我要走的路。但是我仍然遇到同样的错误。

WebConfig.java

@Configuration
@EnableWebMvc
@ComponentScan("com.avectris.newtel")
public class WebConfig extends WebMvcConfigurerAdapter {

@Bean
public InternalResourceViewResolver resolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/view/");
    resolver.setSuffix(".jsp");
    return resolver;
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    registry.addResourceHandler("/sass_compiled/**").addResourceLocations("/sass_compiled/");
    registry.addResourceHandler("/js/**").addResourceLocations("/js/");
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    final ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    converter.setObjectMapper(objectMapper);
    converters.add(converter);
    super.extendMessageConverters(converters);
}
}

阅读 196

收藏
2020-06-10

共1个答案

一尘不染

看一下您的Ajax请求,我认为您正在尝试发送json对象(但实际上不是),然后您尝试使用@RequestParam而不是@RequestBody获取id的值。

如果您不想在ajax有效负载中发送json对象,则您的内容类型错误。尝试这样的事情。jQuery将data属性转换为查询字符串。

$(document).ready(function(){
  $(".overViewListEmployee").click(function () {
    var id = $(this).find(".overViewEmployeeID").text();
    console.log("Works: " + id + ".");
    $.ajax({
        type: "POST",
        headers: {
            "Accept" : "text/html",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
        },
        url: "/refreshDetail",
        //you can get rid of data if you change your url to "/refreshDatil?id="+id
        data: {"id" : id},
        success: function(response) {
            $(".containerDetailView").html(response);
        }
    });
  });
});

如果您确实要发送json对象(如我在评论中已经说过的那样),则需要在控制器级别进行一些更改。


编辑

好的,您现在正在混合两种可能的解决方案。使用当前的ajax对象,您不是在发送json对象,而是普通的http请求。发生ajax请求时,您可以在浏览器中检查“网络”标签,然后会/refreshDetail?id=yourid在Paylod中看到类似的请求
,而没有json对象。

另一方面,您的控制器@RequestBody正在尝试从有效负载中获取类似IdObject的对象,但您并未这样做。您的控制器应如下所示:

@RequestMapping(value = "/refreshDetail", method = RequestMethod.POST, produces = MediaType.TEXT_HTML_VALUE)
private ModelAndView refreshDetailView(HttpServletRequest hsr, @RequestParam int id, ModelMap model){
    model.addAttribute("detailSearchResult", Dao.getDetailViewData(id));
    return new ModelAndView("detailView", model);
}

还要从ajax对象的data属性中删除方括号:

$(".overViewListEmployee").click(function () {
    var id = parseInt($(this).find(".overViewEmployeeID").text());
    console.log("Works: " + id + ".");
    $.ajax({
        type: "POST",
        accept:"text/html",
        //contentType: "application/json; charset=utf-8",
        dataType: "html",
        url: "/refreshDetail",
        data: {"id": id},
        success: function(response) {
            $(".containerDetailView").html(response);
        }
    });
});

如果您要发送json负载 如果您真正需要的是从javascript发送json对象,那么您需要更改ajax请求

$(".overViewListEmployee").click(function () {
    var id = parseInt($(this).find(".overViewEmployeeID").text());
    console.log("Works: " + id + ".");
    $.ajax({
        type: "POST",
        accept:"text/html",
        dataType: "html",
        contentType: "application/json",
        url: "/refreshDetail",
        data: JSON.stringify({"id": id}),
        success: function(response) {
            $(".containerDetailView").html(response);
        }
    });
});

使用contentType jQuery设置header Content- Type,告诉您的控制器请求带有json负载。然后,JSON.stringify将带有要发送的信息的javascript对象转换为json字符串,并将其用作jQuery有效负载。

在后端,您的控制器现在应该使用,@RequestBody因为该信息不在请求参数中,而是json负载。因此,它看起来应该像这样:

@RequestMapping(value = "/refreshDetail", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.TEXT_HTML_VALUE)
    private ModelAndView refreshDetailView(HttpServletRequest hsr, @RequestBody IdObject id, ModelMap model){
        model.addAttribute("detailSearchResult", Dao.getDetailViewData(id.getId()));
        return new ModelAndView("detailView", model);
    }

在这种情况下,请求映射上的consumers属性不是必需的,因为您没有其他任何映射到相同的value
/refreshDetail,但是它使代码更易于阅读。

@ResponseBody在任何一种情况下,您都不必在控制器上使用,因为您要发回视图。发回时会用到它jsonxml等等。

2020-06-10