【问题标题】:How to bind list to the view without a middle model class?如何在没有中间模型类的情况下将列表绑定到视图?
【发布时间】:2021-01-16 14:19:14
【问题描述】:

我有这段代码可以正常工作。

它从存储库中检索数据,将其设置为 listPlaces 并将 listPlaces 绑定到视图。

控制器

ListPlaces listPlaces = new ListPlaces();
listPlaces.setListPlaces(placeRepository.selectPlaces(idUser));

ModelAndView modelAndView = new ModelAndView("/myplaces.html");
modelAndView.addObject("listPlacesBind", listPlaces);

型号

public class ListPlaces {
    
    private List<Place> listPlaces;

    public List<Place> getListPlaces() {
        return listPlaces;
    }

    public void setListPlaces(List<Place> listPlaces) {
        this.listPlaces = listPlaces;
    }
    
}

查看

<th:block th:each="place, itemStat : *{listPlaces}">                    
<span th:text="*{listPlaces[__${itemStat.index}__].codPlace}" />

然后想到我可以通过执行以下操作来简化此代码:

  1. 移除 ListPlaces 模型类
  2. 将控制器代码更改为以下内容:
List<Place> listPlaces;
listPlaces = placeRepository.selectPlaces(idUser);

ModelAndView modelAndView = new ModelAndView("/myplaces.html");
modelAndView.addObject("listPlacesBind", listPlaces);

也就是说,不是在中间使用模型类,而是想尝试直接在控制器中创建列表并将其绑定到视图。

然后我收到以下错误:

Property or field 'listPlaces' cannot be found on object of type 'java.util.ArrayList' - maybe not public or not valid?

在调试模式下运行,我将 listPlaces 设置为“监视”视图。

注意到在第一种情况下它创建了两个级别的“listPlaces”,而在第二种情况下它只创建了一个级别。

看来它缺少第二级。

那么,如果不需要中间模型类就不能做到这一点吗?

也许有一种方法可以在不需要中产阶级的情况下添加第二层。

【问题讨论】:

    标签: java spring spring-boot spring-mvc thymeleaf


    【解决方案1】:

    您没有显示所有相关代码,但猜到了缺少的部分,在需要的地方进行更改。一种选择是更改您的控制器方法,例如:

    @GetMapping("/myplaces")
    public String whateverIsTheName(Model model) {
        model.addAttribute("listPlaces", placeRepository.selectPlaces(idUser));
        return "myplaces";
    }
    

    在不创建任何中间类的情况下,您可以像上面一样使用Model 并保留那些'两个级别',以便有一个对象具有此属性listPlaces

    【讨论】:

    • 很棒的解决方案!这行得通。已接受检查答案。谢谢。
    • 顺便说一句,这是我之前的控制器方法缺少的部分:@RequestMapping(method = RequestMethod.GET, value = "/myplaces") public ModelAndView initMyPlaces() { User loggedUser = new User(); loggedUser = utilities.getLoggedUser(); Long idUser = loggedUser.getIdUser(); ListPlaces listPlaces = new ListPlaces(); listPlaces.setListPlaces(placeRepository.selectPlaces(idUser)); ModelAndView modelAndView = new ModelAndView("/myplaces.html"); modelAndView.addObject("listPlacesBind", listPlaces); return modelAndView; }
    • 我按照您的建议从模型视图更改为模型,并且效果很好。甚至可以通过从以下代码中删除 th:object 来简化 html:&lt;form action="/myplaces" method="post" th:object="${listPlacesBind}"&gt;
    【解决方案2】:

    你犯了一个错误。在第一个 Controller 中,您将 ListPlaces 的对象绑定到 ModelAndView。

    ListPlaces listPlaces = new ListPlaces();
    listPlaces.setListPlaces(placeRepository.selectPlaces(idUser));
    
    ModelAndView modelAndView = new ModelAndView("/myplaces.html");
    modelAndView.addObject("listPlacesBind", listPlaces);// Here listPlaces is an Object Of ListPlaces model
    

    但在第二次更改中,listPlaces 是一个 List 而不是 ListPlaces 模型的对象,因此在您的 HTML 中它期望 ListPlaces 模型的对象但得到一个列表,因此它显示错误。

    List<Place> listPlaces;
    listPlaces = placeRepository.selectPlaces(idUser);
    
    ModelAndView modelAndView = new ModelAndView("/myplaces.html");
    modelAndView.addObject("listPlacesBind", listPlaces);// Here listPlaces is a list not an object of ListPlaces model
    

    所以更改您的 HTML 代码以接受列表,而不是 Objet。 如果有任何疑问,请告诉我。

    【讨论】:

    • 如何更改 html 以接受列表而不是对象?
    • ``` ``` 在上面的 HTML 代码 itemStat : *{listPlaces}" 是 ListPlaces 类的一个字段,但在第二次更改中,您没有绑定 ListPlaces 类的任何对象。在第二次更改“ listPlacesBind" 包含一个列表,因此在 "listPlacesBind" 上运行 th:each,如下所示 ``` ``
    • 如有疑问请告知。
    • listPlacesBind 也是解决方案 1 的一部分。我只是忘记在视图中使用它的位置添加代码。对于那个很抱歉。这是:&lt;form action="/myplaces" method="post" th:object="${listPlacesBind}"&gt;。无论如何,我理解你的建议。所以我从表单标签中删除了 th:object="${listPlacesBind} ,你提出的改变做了(这与@Santiago Wagner 建议的改变相同)并且它奏效了。所以,非常感谢。我也在标记赞成这个,因为已经检查了另一个答案是否被接受。谢谢。很好的解决方案。
    【解决方案3】:

    模型中不再存在名称 listPlaces,因为您现在将其命名为 listPlacesBind:

    modelAndView.addObject("listPlacesBind", listPlaces)
    

    也就是说,列表不再是模型中对象的字段,您必须像这样访问它:

    <th:block th:each="place, itemStat : ${listPlacesBind}">                    
    <span th:text="${listPlacesBind[__${itemStat.index}__].codPlace}" />
    

    【讨论】:

    • 好吧,listPlacesBind 也是解决方案 1 的一部分。我只是忘记在视图中使用它的位置添加代码。在这里:&lt;form action="/myplaces" method="post" th:object="${listPlacesBind}"&gt;。无论如何,我理解你的建议。所以我从表单标签中删除了 th:object="${listPlacesBind} ,实现了你的建议并且它起作用了。我可以接受这个作为答案,但是 stackoverflow 只允许选择一个答案,而我之前已经选择了另一个答案。所以,给这个赞。这是一个很好的建议。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    相关资源
    最近更新 更多