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

Play Framework 2.8.x中Scala.html表单传值至Controller时遇空指针异常

问题原因及修复方案

1. 表单嵌套导致数据未正确提交

视图registraion.scala.html中,@helper.form(action = routes.Users.save())会自动生成合法的<form>标签,但你手动添加了嵌套的<form>标签,违反HTML规范,浏览器无法正确提交表单数据,最终导致Controller无法获取字段值,user.email为null引发空指针。

修复:
删除手动添加的<form>和</form>标签,保留@helper.form的包裹:

@(userFrom: Form[commons.Forms.User])
@()(implicit request: Http.Request)
@main("User form") {
    <h1>User form</h1>
    @helper.form(action = routes.Users.save()) {
        <!-- <legend>User (@userFrom("name").value)</legend>-->
        <!-- <legend>User (userFrom("email"))</legend>-->
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" class="form-control" id="name" name="name" placeholder="Name">
        </div>
        <div class="form-group">
            <label for="email">Email address</label>
            <input type="email" class="form-control" id="email" name="email" placeholder="Email">
        </div>
        <div class="form-group">
            <label for="password">Password</label>
            <input type="password" class="form-control" id="password" name="password" placeholder="Password">
        </div>
        <input type="submit" class="btn btn-primary" value="Save">
        <a class="btn" href="@routes.Authentication.login()">Cancel</a>
    }
}

2. 表单类不符合JavaBean规范

Play Framework的表单绑定依赖JavaBean规范,你的Forms.User类只有公共字段,缺少对应的getter/setter方法,导致表单数据无法正确绑定到对象,字段值为null。

修复:
给Forms.User添加getter和setter方法:

public class Forms {
    public static class User {
        private String name;
        private String email;
        private String password;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }
    }
}

3. Controller中iuserDao未注入

Users控制器里的iuserDao字段没有通过@Inject注解注入,后续调用iuserDao.findByEmail和iuserDao.create时也会触发空指针,提前修复该问题:

修复:
给iuserDao添加@Inject注解:

public class Users extends Controller {
    @Inject
    private IUserDao iuserDao;
    private final Form<Forms.User> userForm;
    private final play.i18n.MessagesApi messagesApi;

    @Inject
    public Users(FormFactory formFactory, MessagesApi messagesApi) {
        this.userForm = formFactory.form(Forms.User.class);
        this.messagesApi = messagesApi;
    }

    // 其他方法保持不变
}

4. 优化路由定义

Play 2.8中无需在路由里显式声明request: Request,直接在Controller方法参数中获取即可:

POST /users controllers.Users.save()

额外建议

  • 绑定表单后可打印表单数据,确认字段是否正确绑定:
    System.out.println(userForm.data());
    
  • 使用Play的校验注解对输入进行合法性校验,避免无效数据进入业务逻辑:
    import play.data.validation.Constraints;
    
    public class Forms {
        public static class User {
            @Constraints.Required
            private String name;
    
            @Constraints.Required
            @Constraints.Email
            private String email;
    
            @Constraints.Required
            private String password;
    
            // getter和setter
        }
    }
    

内容的提问来源于stack exchange,提问作者Dinesh Babu M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 17:47:04