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

向Thymeleaf模型类新增变量时抛出SpEL异常求助

问题:SpringEL无法找到plan_number属性

我是Thymeleaf和Spring的新手,估计犯了低级错误,但卡了两天没解决。我搭了个简单的Spring+H2+Thymeleaf应用,原本只有id、activity、description三个属性时HTML显示正常。现在给模型和HTML加了第4个属性plan_number后,出现了异常:

2022-07-19 18:15:57.347 ERROR 22372 --- [nio-8080-exec-1] org.thymeleaf.TemplateEngine             : [THYMELEAF][http-nio-8080-exec-1] Exception processing template "TaskView": Exception evaluating SpringEL expression: "task.plan_number" (template: "TaskView" - line 73, col 9)
其他信息已省略
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'plan_number' cannot be found on object of type 'com.apa.app.task.Task' - maybe not public or not valid?

只要HTML里不加这个新增属性的th:utext代码就正常,一加就报错。已经在控制器里用println确认H2读出来的数据是正常的,求帮忙解决。


相关代码

Model类

@Entity
@Table(name="tasks")
public class Task {

    @Id
    @GeneratedValue
    private long id;
    private String type;            // Type of task 
    private int plan_number;        // The task number as appears in the plan view
    private String activity;        // Short description that is seen in task view
    private String description;     // Detailed free form text of steps
    private String x;
    
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public long getplan_number() {
        return plan_number;
    }
    public void setplan_number(int plan_number) {
        this.plan_number = plan_number;
    }
    public String getActivity() {
        return activity;
    }
    public void setActivity(String activity) {
        this.activity = activity;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getx() {
        return x;
    }
    public void setx(String x) {
        this.x = x;
    }

    public Task( ) {
    }
    
    public Task(long id, String type, int plan_number, String activity, String description, String x) {
        super();
        this.id = id;
        this.type = type;
        this.plan_number = plan_number;
        this.activity = activity;
        this.description = description;
        this.x = x;
    }
    
    @Override
    public String toString() {
        return "Task [id=" + id + ", type=" + type + ", plan_number=" + plan_number + ", activity=" + activity
                + ", description=" + description + ", x=" + x + "]";
    }
}

Controller类

@Controller
public class TaskController {

    @Autowired
    private TaskService taskService;

    @GetMapping({"/TaskList"})
    public String taskview(Model model) {
        model.addAttribute("tasks", taskService.getTasks());
        return "TaskView";
    }   
    
    @PostConstruct
    private void postInit() {
        System.out.println("All data :" + taskService.getTasks());
    }
}

HTML代码片段

<div th:each ="task : ${tasks}">
    <span th:switch="${task.type}">
        <p th:case = "'action'">
        <tr class="table-light">
            <td class='priority'>1</td>
            <td th:utext=${task.activity}></td>
            <td th:utext=${task.description}></td>
            <td th:utext=${task.plan_number}></td>
        </tr>
        </p>

解决方案

问题根源

SpringEL依赖JavaBean规范查找属性对应的getter方法,你的plan_number属性存在两个问题:

  1. getter/setter命名不符合规范:getplan_number()和setplan_number()没有遵循"get/set + 首字母大写的属性名"规则
  2. getter返回类型不匹配:属性是int类型,但getter返回long类型

修复方案

方案一:修正命名和返回类型(保留蛇形属性名)

修改Task类中plan_number的getter/setter:

// 修正返回类型为int,方法名首字母大写
public int getPlan_number() {
    return plan_number;
}
public void setPlan_number(int plan_number) {
    this.plan_number = plan_number;
}

方案二:改用驼峰命名(更符合Java开发规范)

  1. 修改Task类的属性、方法、构造器及toString:
@Entity
@Table(name="tasks")
public class Task {
    // ...其他属性不变
    private int planNumber;        // 改为驼峰命名

    // ...其他getter/setter不变
    public int getPlanNumber() {
        return planNumber;
    }
    public void setPlanNumber(int planNumber) {
        this.planNumber = planNumber;
    }

    public Task(long id, String type, int planNumber, String activity, String description, String x) {
        super();
        this.id = id;
        this.type = type;
        this.planNumber = planNumber;
        this.activity = activity;
        this.description = description;
        this.x = x;
    }

    @Override
    public String toString() {
        return "Task [id=" + id + ", type=" + type + ", planNumber=" + planNumber + ", activity=" + activity
                + ", description=" + description + ", x=" + x + "]";
    }
}
  1. 同步修改HTML中的表达式:
<td th:utext=${task.planNumber}></td>

两种方案都能让SpringEL正确识别属性,解决异常。


内容的提问来源于stack exchange,提问作者Damo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:36:22