【问题标题】:@ModelAttribute fields are null in Spring controller@ModelAttribute 字段在 Spring 控制器中为空
【发布时间】:2018-01-03 09:32:55
【问题描述】:

我按照教程在 Spring 中处理表单提交。我想用表单填充我的TaskEntity bean,并在我的控制器的taskSubmit 方法中提供这个bean 的值。但是,当我填写表单并点击提交时,此方法中task 的所有属性都为空。相关代码如下:

TaskEntity.java

public class TaskEntity {

    private String title;
    private String description;
    private Date dueDate;
    private TaskPriority priority;

    public void setTitle(String title) 
    {
        this.title = title;
    }

    public String getTitle() 
    {
        return this.title;
    }

    public void setDescription(String description) 
    {
        this.description = description;
    }


    public String getDescription() 
    {
        return this.description;
    }

    public void setDueDate(Date dueDate) 
    {
        this.dueDate = dueDate;
    }

    public Date getDueDate() 
    {
        return this.dueDate;
    }

    public void setPriority(String priority) 
    {
        this.priority = TaskPriority.valueOf(priority);
    }

    public TaskPriority getPriority() 
    {
        return this.priority;
    }
}

addTask.jsp

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>To Do List - Add Task</title>
    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/stylesheet.css">
</head>
<body>
    <form action="tasks" th:action="@{/tasks}" th:object="${taskEntity}" method="post">
        <p>Title: <input type="text" th:field="*{title}" /></p>
        <p>Description: <input type="text" th:field="*{description}" /></p>
        <p>Due Date: <input type="text" th:field="*{dueDate}" /></p>
        <p>Priority: <input type="text" th:field="*{priority}" /></p>
        <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
    </form>
</body>
</html>

TaskController.java

@Controller
public class TaskController {

    private static final String TASKS = "/tasks";
    private static final String ADD_TASK = "/addTask";

    @Autowired
    private TaskEntityDao taskEntityDao;

    ObjectMapper mapper = new ObjectMapper();

    @RequestMapping(value = TASKS, method = RequestMethod.GET)
    public ModelAndView readTasks() 
    {
        return new ModelAndView("tasks");
    }

    @RequestMapping(value = ADD_TASK, method = RequestMethod.GET)
    public String addTask(Model model)
    {
        model.addAttribute("taskEntity", new TaskEntity());
        return "addTask";
    }

    @RequestMapping(value = TASKS, method = RequestMethod.POST)
    public void taskSubmit(@ModelAttribute TaskEntity task)
    {
        // Fields for 'task' are all null!      
        taskEntityDao.createTask(task);

        readTasks();
    }
}

我预计 TaskEntity 传递给带有 model.addAttribute("taskEntity", new TaskEntity()); 的视图会将表单值映射到它的字段,但我一定错过了一些东西。

更新:

我正在从我的 Spring 配置中添加视图解析器代码:

<bean id="viewResolver"
    class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass"
        value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>

【问题讨论】:

  • 如果在 readTasks() 方法中添加model.addAttribute("taskEntity", new TaskEntity()); 会怎样?
  • 请发布您的 Spring MVC 配置,至少是 ViewResolver(s)。
  • @SotiriosDelimanolis 我已经更新了我的问题,谢谢
  • Thymeleaf 不适用于UrlBasedViewResolver,它有自己的ViewResolver 用于Thymeleaf,此外,Thymeleaf 适用于.html 文件,不适用于.jsp .您能否发布在您的网络浏览器中从addTask.jsp 生成的最终 html 代码?

标签: java forms jsp spring-mvc thymeleaf


【解决方案1】:

通过您的编辑,您已确认您的视图分辨率适用于 JSP。

您有一个带有&lt;input&gt; 元素的 JSP 页面,看起来像

<input type="text" th:field="*{description}" />

大概th:fieldThymeleaf element,但是您的页面不是由Thymeleaf 处理的,而是由JSP Servlet 处理的。 JSP Servlet 不关心th:field,无论如何它都不是特别的。它只是从字面上复制它。此外,您的 input 没有 name 属性。 As such, when you submit the form, your browser doesn't send a corresponding value.(即使有,它也不会有 Spring MVC 识别的名称并且可以绑定到您的模型属性。)

设置您的 MVC 配置以正确呈现 Thymeleaf 视图而不是 JSP 视图。

或者如果你真的想使用 JSP,请使用相应的技术:EL、JSTL 和 Spring 的标签库。网上有很多教程,比如this one

【讨论】:

  • 有什么方法可以避免对 Thymeleaf 的需求,而只需从我的 JSP 页面中的简单表单中发布?
  • @petehallw 当然。使用 EL 和 JSTL 等 JSP 特性。 Spring也自带了自己的标签库。
【解决方案2】:

对于同一个 URL,您有一个 GET/POST,在这种情况下由 TASKS = "/tasks" 表示

因此根据以下内容:

@RequestMapping(value = TASKS, method = RequestMethod.GET)
public ModelAndView readTasks() 
{
    return new ModelAndView("tasks");
}

TaskEntity 对象是在哪里创建的?

您在addTask 方法中有model.addAttribute("taskEntity", new TaskEntity());,但可以使用其他 URL,在本例中为ADD_TASK = "/addTask"

您需要了解 Web 表单是根据通过 GET 事件创建的模型加载的,然后当提交事件发生时(Web 表单已填写)POST 事件发生。在这种情况下,GET/POST(由 @RequestMapping 处理)共享“相同”URL 是正常的。

观察: Thymeleaf 不适用于UrlBasedViewResolver,它有自己的ViewResolver 用于Thymeleaf,此外,Thymeleaf 可用于.html 文件,而不是与.jsp。因此,我假设POST 事件无法正常工作,Model 应该如何预期。

注意@Controller 直接依赖于@Repository 是一种不好的做法,它应该是@Service

根据:

@RequestMapping(value = TASKS, method = RequestMethod.POST)
public void taskSubmit(@ModelAttribute TaskEntity task)
{
    // Fields for 'task' are all null!      
    taskEntityDao.createTask(task);

    readTasks();
}
  • 对于Fields for 'task' are all null!,您如何确认?
  • 考虑删除readTasks()@RequestMapping 调用其他 @RequestMapping 并不常见。

【讨论】:

  • 我很欣赏你的错误做法,我是新手,你可能是正确的。但是,我认为这实际上不是我问题的答案。关于 Thymeleaf 的部分可能是相关的,但我认为我不会混淆 URL。我通过 /addTask 导航到表单,并将表单 POST 导航到 /task。另一个 /task 方法 readTasks() 与我的问题无关,但用于从数据库中获取任务。
猜你喜欢
  • 2020-03-03
  • 2014-11-03
  • 2020-05-05
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
  • 2016-11-18
  • 2017-01-08
  • 1970-01-01
相关资源
最近更新 更多