【问题标题】:Thymeleaf post form doesn't submit dataThymeleaf 发布表单不提交数据
【发布时间】:2019-01-19 18:39:48
【问题描述】:

我是 Thymeleaf 的新手,我尝试使用 Thymeleaf 和 Spring 执行简单的表单提交。控制器长这样

@Slf4j
@Controller
public class BookController {

  private static final String BOOK_BOOKFORM_URL = "book/bookform";

  private BookService bookService;

  @Autowired
  public BookController(BookService bookService) {
    this.bookService = bookService;
  }

  @GetMapping("/book/{id}/show")
  public String showBookById(@PathVariable String id, Model model) {

    model.addAttribute("book", bookService.findById(Long.valueOf(id)));

    return "book/bookshow";
  }

  @GetMapping("book/new")
  public String newBook(Model model) {
    model.addAttribute("book", new BookCommand());

    return "book/bookform";
  }

  @GetMapping("book/{id}/update")
  public String updateBook(@PathVariable String id, Model model) {
     model.addAttribute("book", 
        bookService.findCommandById(Long.valueOf(id)));
     return BOOK_BOOKFORM_URL;
  }

  @PostMapping("book/")
  public String saveOrUpdate(@Valid @ModelAttribute("book") BookCommand 
    command,
     BindingResult bindingResult) {

    if (bindingResult.hasErrors()) {

      bindingResult.getAllErrors().forEach(objectError -> {
        log.debug(objectError.toString());
      });

      return BOOK_BOOKFORM_URL;
    }

    BookCommand savedCommand = bookService.saveBookCommand(command);

    return "redirect:/book/" + savedCommand.getId() + "/show";
  }

  @GetMapping("book/{id}/delete")
  public String deleteById(@PathVariable String id) {

    log.debug("Deleting id: " + id);

    bookService.deleteById(Long.valueOf(id));
    return "redirect:/";
  }
}

Thymeleaf 的形式是这样的

<body>
<!--/*@thymesVar id="book" type="com.sombra.test.firsttry.model.Book"*/-->
<div class="container-fluid" style="margin-top: 20px">
  <div class="row">
    <div class="col-md-6 col-md-offset-3">
     <form class="form" th:modelAttribute="book" th:object="${book}" 
        th:action="@{/book/}" method="post">
        <input type="hidden" th:field="*{id}"/>
        <div class="pannel-group">
          <div class="panel panel-primary">
            <div class="panel-heading">
               <h1 class="panel-title">Змінити інформацію про книгу</h1>
            </div>
            <div class="panel-body">
              <div class="row">
                <div class="col-md-3 form-group">
                  <label>Ім'я:</label>
                  <input type="text" class="form-control" th:field="*{name}"/>
               </div>
               <div class="col-md-3 form-group">
                 <label>Опубліковано:</label>
                  <input type="text" class="form-control" th:field="* 
                  {published}"/>
               </div>
               <div class="col-md-3 form-group">
                  <label>Жанр:</label>
                  <input type="text" class="form-control" th:field="*{genre}"/>
               </div>
               <div class="col-md-3 form-group">
                  <label>Рейтинг:</label>
                  <input type="text" class="form-control" th:field="*{rating}"/>
               </div>
          </div>
             <button type="submit" class="btn btn-primary">Save</button>
        </div>
      </div>
    </div>
  </form>
</div>

Book 和 BookCommand 是使用 Spring 的 Converter 相互转换的 POJO。 当我按下提交按钮时,控制器方法 saveOrUpdate 既不会将我重定向到包含有关图书信息的页面,因为它必须在成功保存的情况下执行此操作,也不会从 BindingResult 记录错误消息。那么,可能是什么原因呢?

【问题讨论】:

    标签: spring spring-boot thymeleaf


    【解决方案1】:

    将此@PostMapping("book/") 更改为@PostMapping("/book/")

    如果上述方法不起作用,请通过删除斜线来使用以下内容。

    th:action="@{/book/}",因为问题仅在于 URL 匹配。

    【讨论】:

      【解决方案2】:

      感谢大家的假设和帮助! 最后,我找到了问题的原因。问题是关于存储表单的已发布字段中的日期。 Spring 无法将插入的字符串转换为日期,但由于某种原因,使用 BindingResult 错误日志记录的块中没有记录错误。解决方案是将 Date 的活页夹添加到控制器中,如下所示:

       @InitBinder
       public void initBinder(WebDataBinder binder) {
          binder.registerCustomEditor(Date.class, new CustomDateEditor(new 
          SimpleDateFormat("yyyy-MM-dd"), true));
       }
      

      【讨论】:

        【解决方案3】:

        使用@SessionAttributes 注解 像这样

        @Slf4j
        @Controller
        @SessionAttributes("book")
        public class BookController {
        
          private static final String BOOK_BOOKFORM_URL = "book/bookform";
        
          private BookService bookService;
        
          @Autowired
          public BookController(BookService bookService) {
            this.bookService = bookService;
          }
        
          @GetMapping("/book/{id}/show")
          public String showBookById(@PathVariable String id, Model model) {
        
            model.addAttribute("book", bookService.findById(Long.valueOf(id)));
        
            return "book/bookshow";
          }
        
          @GetMapping("book/new")
          public String newBook(Model model) {
            model.addAttribute("book", new BookCommand());
        
            return "book/bookform";
          }
        
          @GetMapping("book/{id}/update")
          public String updateBook(@PathVariable String id, Model model) {
             model.addAttribute("book", 
                bookService.findCommandById(Long.valueOf(id)));
             return BOOK_BOOKFORM_URL;
          }
        
          @PostMapping("book/")
          public String saveOrUpdate(@Valid @ModelAttribute("book") BookCommand 
            command,
             BindingResult bindingResult) {
        
            if (bindingResult.hasErrors()) {
        
              bindingResult.getAllErrors().forEach(objectError -> {
                log.debug(objectError.toString());
              });
        
              return BOOK_BOOKFORM_URL;
            }
        
            BookCommand savedCommand = bookService.saveBookCommand(command);
        
            return "redirect:/book/" + savedCommand.getId() + "/show";
          }
        
          @GetMapping("book/{id}/delete")
          public String deleteById(@PathVariable String id) {
        
            log.debug("Deleting id: " + id);
        
            bookService.deleteById(Long.valueOf(id));
            return "redirect:/";
          }
        }
        

        【讨论】:

        • 添加@SessionAttributes 不会改变这种情况。还有其他假设吗?
        • 你得到的输出是什么?
        • 其实没有输出。它既不会重定向到添加了记录视图的页面,也不会记录错误消息。它只是与“/book/”地址保持在同一页面上。
        • 我认为表单提交没有发生。
        • 在 saveOrUpdate 方法中打印一些消息来检查函数是否正在执行
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-19
        • 2018-05-17
        • 2014-01-13
        • 1970-01-01
        • 2019-10-09
        • 1970-01-01
        相关资源
        最近更新 更多