Thymeleaf发布表单未提交数据

时间:2018-08-13 04:58:51

标签: spring spring-boot thymeleaf

我是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的错误消息。那么,这可能是什么原因?

3 个答案:

答案 0 :(得分:1)

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

如果上述方法不起作用,请通过删除斜线与下面的方法一起使用。

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

答案 1 :(得分:0)

使用@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:/";
  }
}

答案 2 :(得分:0)

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

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