You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Thymeleaf表单中直接创建Comment对象作为th:object值报错,咨询可行性及解决方案

Thymeleaf表单中直接创建Comment对象作为th:object值报错,咨询可行性及解决方案

嘿,我来帮你拆解这个问题:

核心问题:为什么用th:with创建的对象当th:object会报错?

你看到的关键错误Neither BindingResult nor plain target object for bean name 'comment' available as request attribute,本质原因是Spring MVC的表单绑定机制要求目标对象必须存在于Request/Model属性中,而th:with创建的变量只是Thymeleaf模板内部的局部变量,Spring的表单处理器根本访问不到它。所以这种方式是不可行的,没办法直接用th:with的变量作为th:object。

解决方案1:常规推荐方式(Controller中传入空Comment对象)

这是最标准、最稳妥的做法,在展示图片的GET请求Controller方法里,把一个空的Comment对象添加到Model中:

@GetMapping("/picture/{pictureId}/show")
public String showPicture(@PathVariable Long pictureId, Model model) {
    // 获取图片对象并放入model
    Picture picture = pictureService.findPictureById(pictureId);
    model.addAttribute("picture", picture);
    
    // 添加空的Comment对象用于表单绑定,提前初始化user避免模板NPE
    Comment comment = Comment.create();
    comment.setUser(new User());
    model.addAttribute("comment", comment);
    
    return "picture/show";
}

然后修改模板,去掉th:with,直接使用Model里的comment:

<form th:object="${comment}" th:action="@{/comment/{pictureId}(pictureId=${picture.id})}" method="post">
    <div>
        <label for="username"><b>Username</b></label>
        <input id="username" type="text" th:field="*{user.username}">
    </div>
    <div>
        <label for="password"><b>Password</b></label>
        <input id="password" type="password" th:field="*{user.password}">
    </div>
    <div>
        <label for="commentText" ><b>Comment</b></label>
        <input id="commentText" type="text" th:field="*{commentText}">
    </div>
    <button type="submit">Submit</button>
</form>

这里还要修正你模板里的th:action错误:原来的@{/comment/picture.id}是无效写法,要使用路径变量语法@{/comment/{pictureId}(pictureId=${picture.id})}来正确传递图片ID。

解决方案2:极端场景下的临时替代(不推荐)

如果实在不想在Controller里添加对象,你可以直接在th:object里调用静态方法创建对象,但要注意这种方式没有BindingResult支持,表单验证失败后无法回显错误信息和用户输入的数据,只适合非常简单的表单:

<form th:object="${T(com.david.caterest.entity.Comment).create()}" th:action="@{/comment/{pictureId}(pictureId=${picture.id})}" method="post">
    <div>
        <label for="username"><b>Username</b></label>
        <input id="username" type="text" th:field="*{user.username}">
    </div>
    <div>
        <label for="password"><b>Password</b></label>
        <input id="password" type="password" th:field="*{user.password}">
    </div>
    <div>
        <label for="commentText" ><b>Comment</b></label>
        <input id="commentText" type="text" th:field="*{commentText}">
    </div>
    <button type="submit">Submit</button>
</form>

对应的Comment类需要修改create方法,提前初始化user避免空指针:

public static Comment create() {
    Comment comment = new Comment();
    comment.setUser(new User()); // 初始化user对象,防止模板访问属性时NPE
    return comment;
}

补充:你的Post方法需要完善的地方

现在的Post方法只设置了commentText,还需要补充其他必填字段:

@PostMapping("/comment/{pictureId}")
public String newComment(@ModelAttribute Comment comment, @PathVariable Long pictureId, Authentication authentication) {
    Picture picture = pictureService.findPictureById(pictureId);
    comment.setPicture(picture);
    
    // 获取当前登录用户(假设使用Spring Security)
    User currentUser = (User) authentication.getPrincipal();
    comment.setUser(currentUser);
    
    // 设置评论发布时间
    comment.setDateOfPost(LocalDateTime.now());
    
    // 保存评论到数据库
    commentService.saveComment(comment);
    
    return "redirect:/picture/" + pictureId + "/show";
}

这里用@ModelAttribute Comment comment可以直接绑定表单提交的数据,比单独接收commentText更简洁规范。

备注:内容来源于stack exchange,提问作者Davido

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 08:19:51