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
相关产品推荐
相关产品推荐

