使用@Valid在Spring中进行表单验证无效。

16

我想验证我的表单,但是它不起作用。 我的实体类

import java.io.Serializable;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;

@Entity
@Table(name = "users")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;
    @NotNull
    @Size(max = 20)
    @Column(name = "username")
    private String username;
    @NotNull
    @Size(max = 20)
    @Column(name = "password")
    private String password;
    @NotNull
    @Size(max = 20)
    @Column(name = "firstName")
    private String firstName;
    @NotNull
    @Size(max = 20)
    @Column(name = "lastName")
    private String lastName;
    @Size(min = 11, max = 11)
    @Column(name = "personalId")
    private String personalId;
    @Size(max = 40)
    @Column(name = "city")
    private String city;
    @Size(max = 40)
    @Column(name = "address")
    private String address;
    @NotNull
    @Email
    @Size(max = 30)
    @Column(name = "email")
    private String email;
    @Size(min = 9, max = 9)
    @Column(name = "phone")
    private String phone;
    @OneToMany(mappedBy = "user")
    private Set<UserRole> userRoleSet;
}

管理员列表页 adminList.jsp 和表单跳转至添加管理员页面:

<form action="addAdminForm" method="post">
    <input type="submit" value="Dodaj administratora" />
</form>

addAdmin.jsp页面公式:

    <form:form action="addAdmin" modelAttribute="user" method="post">
    <form:label path="username">Login: </form:label>
    <form:input path="username" />
    <form:errors path="username" cssClass="error" />
    <br />
    <form:label path="password">Hasło: </form:label>
    <form:password path="password" />
    <form:errors path="password" cssClass="error" />
    <br />
    <form:label path="firstName">Imię: </form:label>
    <form:input path="firstName" />
    <form:errors path="firstName" cssClass="error" />
    <br />
    <form:label path="lastName">Nazwisko: </form:label>
    <form:input path="lastName" />
    <form:errors path="lastName" cssClass="error" />
    <br />
    <form:label path="email">Email: </form:label>
    <form:input path="email" />
    <form:errors path="email" cssClass="error" />
    <br />
    <input type="submit" value="Dodaj" />
</form:form>

控制器:

    @RequestMapping(value = "/admin/addAdminForm", method = RequestMethod.POST)
public ModelAndView goAddAdminForm() {
    ModelAndView mav = new ModelAndView("admin/addadmin");
    mav.addObject("user", new User());
    return mav;
}

@RequestMapping(value = "/admin/addAdmin", method = RequestMethod.POST)
public String addAdmin(@Valid @ModelAttribute("user") User user,
        BindingResult result, Model model) {
    if (result.hasErrors()) {
        return "admin/addadmin";
    } else {
        userService.createUser(user);
        user = userService.findByUsername(user.getUsername());
        UserRole userRole = new UserRole("ROLE_ADMIN");
        userRole.setUser(user);
        userRoleService.createUserRole(userRole);
        return "redirect:/admin/adminlist";
    }
}
当我尝试发送空表单时,我应该会收到错误信息,但是result.hasErrors()并没有返回错误,导致我的应用程序进入else语句并尝试保存用户。为什么@Valid无法工作?
当我尝试发送空表单时,我应该会收到错误信息,但是result.hasErrors()并没有返回错误,导致我的应用程序进入else语句并尝试保存用户。为什么@Valid无法工作?

嗨,我遇到了一个类似的情况,但在我的情况下,@NotEmpty也不起作用。请问除了上述的配置外,我还需要进行其他配置吗? - Toseef Zafar
9个回答

51

将我的项目升级到Spring Boot 2.3.0后,我遇到了同样的问题,花费了数小时的时间,直到意识到从#19550开始,Web和WebFlux启动器不再默认依赖验证启动器。如果您的应用程序使用了验证功能,则需要在构建文件中手动添加spring-boot-starter-validation的依赖。


1
在导入starter-validation之前,编译器显示了问题,现在编译器一切正常,但它仍然无法工作。在“错误”对象中显示零个错误。 - Muhammad Muzammil
1
这应该是被接受的答案,谢谢分享。 - irshad.ahmad
1
对,@irshad.ahmad说得没错,在2021年,我怀疑大多数人来到这篇帖子是因为缺少这个依赖。是否可以更改已接受的答案,@the-nightmare? - Kevin-Prichard

9

我在我的Spring Boot 2.4.1项目中也遇到了同样的问题。您需要在pom.xml文件中添加此依赖项。

...
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
...

6

我在使用旧的Java Bean时,在Kotlin中遇到了同样的问题。它们缺少field目标说明符,没有这个说明符,javax.validation注释就不起作用。

以下是包含field以解决问题的Kotlin代码片段:

@field:NotNull
@field:Size(max = 20)
@Column(name = "username")
var username:  String

谢谢,这对我的 Kotlin 项目有所帮助。 - Violetta
1
哇,我真的无法感谢你了!在找到这个之前,我尝试了其他所有的Java项目选项。太棒了! - Lavínia Beghini

6
你确定验证不起作用吗?除非你注册了例如 StringTrimmerEditor,否则在提交表单时你的字段实际上将是长度为0的字符串实例,而不是null值,因此注释会认为这样的值是有效的。
如果要验证字符串不为空(不为null且不为空字符串),例如使用@NotBlank 注释。我刚试过,@Email注释也会通过空字符串,这意味着你的空表单现在实际上是有效的。

我添加了 @NotBlank@Valid。为什么 @NotNull 不够用呢? - The Nightmare
2
我没有看到问号,但我猜最后一部分是一个问题 :). @NotNull 只检查值是否不为 null,但你从表单中获取的值实际上是 "",意味着长度为 0 的 String 实例,而不是 null。希望这能解释清楚。 - Bohuslav Burghardt

4

我遇到了同样的错误(应用程序未经验证)。

我添加了

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>

并且成功了!


4

我在一个2.5.0(快照版)的Spring Boot项目中遇到了同样的问题。我在pom.xml文件中添加了以下依赖项,问题得到了解决。

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

0
今天(2018年4月22日),hibernate-validator已更新到版本6.0.9.Final。在我的测试中,我发现使用@Valid验证嵌套对象可以在版本5.2.5.Final及以下版本中工作,但我不明白为什么最新版本不能工作(也许将来有人可以解释一下),这是我的代码:
@JsonIgnoreProperties(ignoreUnknown = true)
public class PackQueryReq {

    // ......

    @NotNull(message = "params can't be NULL")
    @Valid
    private PackQueryParams params;
}
public class PackQueryParams {

    @Min(value=1)
    @NotNull(message = "enterpriseId can't be NULL")
    private Integer enterpriseId;
}

在Spring MVC控制器上:

public Resp query(@RequestBody @Valid PackQueryReq packQuery) {
   //...
}

0

我不得不更改 hibernate-validator 的版本。8.0.0 不起作用,但 6.1.5 可以。

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.1.5.Final</version>
    </dependency>

0
<mvc:annotation-driven/>

检查上述标签是否在dispatcher-servlet.xml中声明。此标签将激活所有注释。


您不需要一个代码片段来提供一行代码建议。这会误导读者,他们会认为它会产生结果,但实际上只是一个可以格式化为代码示例的单个代码。 - Anurag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接