Spring JSR-303 bean 验证不工作,绑定结果为空
Spring JSR-303 bean validation not working, empty bindingresult
嗨 Whosebug
我已尝试将 beanvalidation 添加到我的小型 Web 应用程序中。直到现在它都不起作用,因为我的绑定结果保持为空。我做了以下事情:
- 添加所有依赖项(同学,Javax.el,Jboss-logging,Validation-api)
- 添加了注释
- 使用@valid 和 BindingResult 更新了控制器
- 更新了我的 jsp 页面
- 确保我的调度程序中有
<mvc:annotation-driven/>
-servlet.xml
我已经在 Whosebug 上查看过类似的问题,但我无法找到我需要的答案。我正在使用 Apache Tomcat.
我的控制器:
@RequestMapping(value = {"/cardForm"}, method = POST, params = {"dispatcher=createCard"})
public String addCard(@Valid @ModelAttribute("card") Card card, BindingResult result) {
System.out.println(result.getErrorCount());
if (result.hasErrors()) {
return "cardForm";
} else {
try {
service.addCard(card);
} catch (MapperException ex) {
Logger.getLogger(CardController.class.getName()).log(Level.SEVERE, null, ex);
}
return "redirect:/";
}
}
我的class待验证:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package domain;
import javax.persistence.Entity;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
*
* @author niels
*/
@Entity
public class Card extends DomainObjectBase {
@NotNull(message="{error.name.null}")
private String name;
@NotNull(message="{error.type.null}")
private String type;
@NotNull(message="{error.text.null}")
private String text;
@NotNull(message="{error.playerClass.null}")
private String playerClass;
@Min(value=0,message="{error.attack.min}")
private int attack;
@Min(value=0,message="{error.health.min}")
private int health;
@Min(value=0,message="{error.cost.min}")
private int cost;
public Card() {}
public Card(String name, String type, String text, String playerClass, int attack, int health, int cost) throws DomainException {
setName(name);
setType(type);
setText(text);
setPlayerClass(playerClass);
setAttack(attack);
setHealth(health);
setCost(cost);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getPlayerClass() {
return playerClass;
}
public void setPlayerClass(String playerClass) {
this.playerClass = playerClass;
}
public int getAttack() {
return attack;
}
public void setAttack(int attack) throws DomainException {
this.attack = attack;
}
public int getHealth() {
return health;
}
public void setHealth(int health) throws DomainException {
this.health = health;
}
public int getCost() {
return cost;
}
public void setCost(int cost) throws DomainException {
this.cost = cost;
}
}
我的调度员-servlet.xml:
<?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<mvc:annotation-driven/>
<context:component-scan base-package="controller"/>
<!--
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages"></property>
</bean>
-->
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang" />
</mvc:interceptors>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en_GB"/>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<bean class="org.springframework.context.support.ResourceBundleMessageSource"
id="messageSource">
<property name="basename" value="messages" />
</bean>
</beans>
我的cardForm.jsp:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html lang="en">
<head>
<title>
Hearthstone |
<spring:message code="title.addCard">
</spring:message>
</title>
<jsp:include page="title.jsp" />
</head>
<body>
<div id="wrapper">
<jsp:include page="menu.jsp" />
<!-- Page Content -->
<div id="page-content-wrapper">
<div class="container-fluid">
<div class="row">
<div class="col-lg-6 col-lg-offset-3">
<form:form action="${pageContext.request.contextPath}/cardForm.htm" method="post" modelAttribute="card">
<form:errors path="*" cssClass="errorblock" element="div" />
<c:choose>
<c:when test="${card.id > 0}">
<h3><spring:message code="card.update">
</spring:message></h3>
<form:hidden path="id" value="${card.id}"/>
<input type="hidden" name="dispatcher" value="updateCard"/>
</c:when>
<c:otherwise>
<h3><spring:message code="card.add">
</spring:message></h3>
<input type="hidden" name="dispatcher" value="createCard"/>
</c:otherwise>
</c:choose>
<div class="form-group">
<form:label path="name"><spring:message code="card.name">
</spring:message>: </form:label>
<form:input path="name" class="form-control"></form:input>
</div>
<div class="form-group">
<form:label path="type">Type: </form:label>
<form:select class="form-control" path="type">
<form:option value="Minion">Minion</form:option>
<form:option value="Spell">Spell</form:option>
<form:option value="Weapon">Weapon</form:option>
</form:select>
</div>
<div class="form-group">
<form:label path="text"><spring:message code="card.text">
</spring:message>: </form:label>
<form:input path="text" class="form-control"></form:input>
</div>
<div class="form-group">
<form:label path="playerClass"><spring:message code="card.playerClass">
</spring:message>: </form:label>
<form:select class="form-control" path="playerClass">
<form:option value="All classes">All classes</form:option>
<form:option value="Priest">Priest</form:option>
<form:option value="Shaman">Shaman</form:option>
<form:option value="Mage">Mage</form:option>
<form:option value="Warrior">Warrior</form:option>
<form:option value="Warlock">Warlock</form:option>
<form:option value="Paladin">Paladin</form:option>
<form:option value="Rogue">Rogue</form:option>
<form:option value="Druid">Druid</form:option>
<form:option value="Hunter">Hunter</form:option>
</form:select>
</div>
<div class="form-group">
<form:label path="attack"><spring:message code="card.attack">
</spring:message>: </form:label>
<form:input path="attack" class="form-control"></form:input>
</div>
<div class="form-group">
<form:label path="health"><spring:message code="card.health">
</spring:message>: </form:label>
<form:input path="health" class="form-control"></form:input>
</div>
<div class="form-group">
<form:label path="cost"><spring:message code="card.cost">
</spring:message>: </form:label>
<form:input path="cost" class="form-control"></form:input>
</div>
<div class="form-group"><form:button type="submit" class="btn btn-primary"><spring:message code="form.send">
</spring:message></form:button></div>
</form:form>
</div>
</div>
</div>
</div>
<!-- /#page-content-wrapper -->
</div>
<!-- /#wrapper -->
<!-- Bootstrap Core JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<!-- Menu Toggle Script -->
<script>
$("#menu-toggle").click(function (e) {
e.preventDefault();
$("#wrapper").toggleClass("toggled");
});
</script>
</body>
</html>
好的,我已经为您解决了,我必须说一切正常,但是您使用了错误的 javax.validation 注释 :)
您使用@NotNull,但事实是 controller.CardController#addCard(domain.Card, org.springframework.validation.BindingResult) 收到的 Card 实例中的字段永远不会为空,它们被设置为空字符串 - 这就是为什么您在 BindingResult 中看不到任何验证错误的原因。
只需添加 (org.hibernate.validator.constraints.)@NotEmpty 注释而不是当前的 @NotNull 注释,您将在 BindingResult 中看到报告的验证错误。
嗨 Whosebug
我已尝试将 beanvalidation 添加到我的小型 Web 应用程序中。直到现在它都不起作用,因为我的绑定结果保持为空。我做了以下事情:
- 添加所有依赖项(同学,Javax.el,Jboss-logging,Validation-api)
- 添加了注释
- 使用@valid 和 BindingResult 更新了控制器
- 更新了我的 jsp 页面
- 确保我的调度程序中有
<mvc:annotation-driven/>
-servlet.xml
我已经在 Whosebug 上查看过类似的问题,但我无法找到我需要的答案。我正在使用 Apache Tomcat.
我的控制器:
@RequestMapping(value = {"/cardForm"}, method = POST, params = {"dispatcher=createCard"})
public String addCard(@Valid @ModelAttribute("card") Card card, BindingResult result) {
System.out.println(result.getErrorCount());
if (result.hasErrors()) {
return "cardForm";
} else {
try {
service.addCard(card);
} catch (MapperException ex) {
Logger.getLogger(CardController.class.getName()).log(Level.SEVERE, null, ex);
}
return "redirect:/";
}
}
我的class待验证:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package domain;
import javax.persistence.Entity;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
*
* @author niels
*/
@Entity
public class Card extends DomainObjectBase {
@NotNull(message="{error.name.null}")
private String name;
@NotNull(message="{error.type.null}")
private String type;
@NotNull(message="{error.text.null}")
private String text;
@NotNull(message="{error.playerClass.null}")
private String playerClass;
@Min(value=0,message="{error.attack.min}")
private int attack;
@Min(value=0,message="{error.health.min}")
private int health;
@Min(value=0,message="{error.cost.min}")
private int cost;
public Card() {}
public Card(String name, String type, String text, String playerClass, int attack, int health, int cost) throws DomainException {
setName(name);
setType(type);
setText(text);
setPlayerClass(playerClass);
setAttack(attack);
setHealth(health);
setCost(cost);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getPlayerClass() {
return playerClass;
}
public void setPlayerClass(String playerClass) {
this.playerClass = playerClass;
}
public int getAttack() {
return attack;
}
public void setAttack(int attack) throws DomainException {
this.attack = attack;
}
public int getHealth() {
return health;
}
public void setHealth(int health) throws DomainException {
this.health = health;
}
public int getCost() {
return cost;
}
public void setCost(int cost) throws DomainException {
this.cost = cost;
}
}
我的调度员-servlet.xml:
<?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<mvc:annotation-driven/>
<context:component-scan base-package="controller"/>
<!--
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages"></property>
</bean>
-->
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang" />
</mvc:interceptors>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en_GB"/>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<bean class="org.springframework.context.support.ResourceBundleMessageSource"
id="messageSource">
<property name="basename" value="messages" />
</bean>
</beans>
我的cardForm.jsp:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html lang="en">
<head>
<title>
Hearthstone |
<spring:message code="title.addCard">
</spring:message>
</title>
<jsp:include page="title.jsp" />
</head>
<body>
<div id="wrapper">
<jsp:include page="menu.jsp" />
<!-- Page Content -->
<div id="page-content-wrapper">
<div class="container-fluid">
<div class="row">
<div class="col-lg-6 col-lg-offset-3">
<form:form action="${pageContext.request.contextPath}/cardForm.htm" method="post" modelAttribute="card">
<form:errors path="*" cssClass="errorblock" element="div" />
<c:choose>
<c:when test="${card.id > 0}">
<h3><spring:message code="card.update">
</spring:message></h3>
<form:hidden path="id" value="${card.id}"/>
<input type="hidden" name="dispatcher" value="updateCard"/>
</c:when>
<c:otherwise>
<h3><spring:message code="card.add">
</spring:message></h3>
<input type="hidden" name="dispatcher" value="createCard"/>
</c:otherwise>
</c:choose>
<div class="form-group">
<form:label path="name"><spring:message code="card.name">
</spring:message>: </form:label>
<form:input path="name" class="form-control"></form:input>
</div>
<div class="form-group">
<form:label path="type">Type: </form:label>
<form:select class="form-control" path="type">
<form:option value="Minion">Minion</form:option>
<form:option value="Spell">Spell</form:option>
<form:option value="Weapon">Weapon</form:option>
</form:select>
</div>
<div class="form-group">
<form:label path="text"><spring:message code="card.text">
</spring:message>: </form:label>
<form:input path="text" class="form-control"></form:input>
</div>
<div class="form-group">
<form:label path="playerClass"><spring:message code="card.playerClass">
</spring:message>: </form:label>
<form:select class="form-control" path="playerClass">
<form:option value="All classes">All classes</form:option>
<form:option value="Priest">Priest</form:option>
<form:option value="Shaman">Shaman</form:option>
<form:option value="Mage">Mage</form:option>
<form:option value="Warrior">Warrior</form:option>
<form:option value="Warlock">Warlock</form:option>
<form:option value="Paladin">Paladin</form:option>
<form:option value="Rogue">Rogue</form:option>
<form:option value="Druid">Druid</form:option>
<form:option value="Hunter">Hunter</form:option>
</form:select>
</div>
<div class="form-group">
<form:label path="attack"><spring:message code="card.attack">
</spring:message>: </form:label>
<form:input path="attack" class="form-control"></form:input>
</div>
<div class="form-group">
<form:label path="health"><spring:message code="card.health">
</spring:message>: </form:label>
<form:input path="health" class="form-control"></form:input>
</div>
<div class="form-group">
<form:label path="cost"><spring:message code="card.cost">
</spring:message>: </form:label>
<form:input path="cost" class="form-control"></form:input>
</div>
<div class="form-group"><form:button type="submit" class="btn btn-primary"><spring:message code="form.send">
</spring:message></form:button></div>
</form:form>
</div>
</div>
</div>
</div>
<!-- /#page-content-wrapper -->
</div>
<!-- /#wrapper -->
<!-- Bootstrap Core JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<!-- Menu Toggle Script -->
<script>
$("#menu-toggle").click(function (e) {
e.preventDefault();
$("#wrapper").toggleClass("toggled");
});
</script>
</body>
</html>
好的,我已经为您解决了,我必须说一切正常,但是您使用了错误的 javax.validation 注释 :)
您使用@NotNull,但事实是 controller.CardController#addCard(domain.Card, org.springframework.validation.BindingResult) 收到的 Card 实例中的字段永远不会为空,它们被设置为空字符串 - 这就是为什么您在 BindingResult 中看不到任何验证错误的原因。
只需添加 (org.hibernate.validator.constraints.)@NotEmpty 注释而不是当前的 @NotNull 注释,您将在 BindingResult 中看到报告的验证错误。