113人参与 • 2024-08-06 • 设计模式
在现代软件开发中,数据验证是确保应用程序健壮性和可靠性的关键环节。java bean validation (jsr 380) 作为一个功能强大的规范,为我们提供了一套全面的注解工具集,这些注解能够帮助开发者在java应用程序中以一种声明式的方式执行数据验证。从基本的非空验证到复杂的正则表达式匹配,jsr 380规范及其实
@notnull
注解用于确保被注解的字段不为 null
。这在需要强制字段必须有值的情况下非常有用,例如,用户实体的用户名或电子邮件字段。
public class user {
@notnull(message = "用户名不能为空")
private string username;
// 其他用户属性...
}
public class user {
@notnull(message = "用户名不能为空", groups = registrationchecks.class, payload = errorpayloads.class)
private string username;
// 用户名是用户身份的唯一标识,注册时必须填写。
// groups属性定义了此验证属于registrationchecks组,可用于部分验证场景。
// payload属性可用于携带额外的元数据,供验证器使用。
}
@notblank
注解除了确保字符串不为 null
外,还检查字符串至少有一个非空白字符。这适用于需要文本输入的字段,如用户评论或表单提交。
true
,指示是否在验证前去除字符串两端的空白字符。public class comment {
@notblank(message = "评论内容不能为空", trim = true)
private string content;
// 其他评论属性...
}
public class comment {
@notblank(message = "评论内容不能为空", trim = true, groups = commentchecks.class, payload = errorpayloads.class)
private string content;
// 评论内容必须填写,trim=true表示在验证前去除两端空白字符。
// groups属性定义了此验证属于commentchecks组。
}
@notempty
注解用于验证字符串、集合或数组不为 null
且至少有一个元素(对于集合和数组)或至少有一个非空白字符(对于字符串)。
public class message {
@notempty(message = "消息内容不能为空")
private string text;
// 其他消息属性...
}
public class message {
@notempty(message = "消息内容不能为空", groups = messagechecks.class, payload = errorpayloads.class)
private string text;
// 消息文本不能为空,适用于消息发送场景。
}
@size
注解用于验证字符串、集合、数组或map的大小是否在指定的范围内。
public class book {
@size(min = 1, max = 100, message = "书名长度必须在1到100个字符之间")
private string title;
// 其他书籍属性...
}
public class book {
@size(min = 1, max = 100, message = "书名长度必须在1到100个字符之间", groups = bookchecks.class, payload = errorpayloads.class)
private string title;
// 书名长度限制,适用于图书管理系统。
}
@past
注解用于验证日期类型的字段是否表示过去的日期。
import java.time.localdate;
public class event {
@past(message = "事件日期必须是过去的日期")
private localdate eventdate;
// 其他事件属性...
}
import java.time.localdate;
public class event {
@past(message = "事件日期必须是过去的日期", groups = eventchecks.class, payload = errorpayloads.class)
private localdate eventdate;
// 事件日期应为过去日期,适用于历史事件记录。
}
@future
注解用于验证日期类型的字段是否表示未来的日期。
public class delivery {
@future(message = "预计送达日期必须是未来的日期")
private localdate expecteddeliverydate;
// 其他送达属性...
}
public class delivery {
@future(message = "预计送达日期必须是未来的日期", groups = deliverychecks.class, payload = errorpayloads.class)
private localdate expecteddeliverydate;
// 预计送达日期应为未来日期,适用于订单处理系统。
}
@pattern
注解用于验证字符串是否与指定的正则表达式匹配。
public class userregistration {
@pattern(regexp = "^[a-za-z0-9_.+-]+@[a-za-z0-9-]+\.[a-za-z0-9-.]+$",
message = "电子邮箱格式不正确" flags = {pattern.flag.case_insensitive})
private string email;
// 其他注册属性...
}
public class userregistration {
@pattern(regexp = "^[a-za-z0-9_.+-]+@[a-za-z0-9-]+\\.[a-za-z0-9-.]+$",
message = "电子邮箱格式不正确", flags = {pattern.flag.case_insensitive}, groups = registrationchecks.class, payload = errorpayloads.class)
private string email;
// 电子邮箱格式验证,适用于用户注册表单。
}
@min
注解用于验证数值类型的字段是否大于或等于指定的最小值。
public class product {
@min(value = 1, message = "购买数量不能少于1")
private int quantity;
// 其他产品属性...
}
public class product {
@min(value = 1, message = "购买数量不能少于1", groups = productchecks.class, payload = errorpayloads.class)
private int quantity;
// 购买数量验证,适用于购物车系统。
}
@max
注解用于验证数值类型的字段是否小于或等于指定的最大值。
public class product {
@max(value = 100, message = "库存数量不能超过100")
private int stock;
// 其他产品属性...
}
public class product {
@max(value = 100, message = "库存数量不能超过100", groups = stockchecks.class, payload = errorpayloads.class)
private int stock;
// 库存数量验证,适用于库存管理系统。
}
@decimalmin
注解用于验证 bigdecimal
或包装的数值类型字段是否大于或等于指定的十进制最小值。
true
)。public class price {
@decimalmin(value = "0.00", inclusive = true, message = "价格必须非负")
private bigdecimal value;
// 其他价格属性...
}
public class price {
@decimalmin(value = "0.00", inclusive = true, message = "价格必须非负", groups = pricechecks.class, payload = errorpayloads.class)
private bigdecimal value;
// 价格必须为非负值,适用于财务管理系统。
}
@decimalmax
注解用于验证 bigdecimal
或包装的数值类型字段是否小于或等于指定的十进制最大值。
true
)。public class price {
@decimalmax(value = "1000.00", inclusive = true, message = "价格不能超过1000")
private bigdecimal value;
// 其他价格属性...
}
public class price {
@decimalmax(value = "1000.00", inclusive = true, message = "价格不能超过1000", groups = pricechecks.class, payload = errorpayloads.class)
private bigdecimal value;
// 价格上限验证,适用于定价策略。
}
@email
注解用于验证字符串字段是否为有效的电子邮件地址。
public class user {
@email(message = "电子邮件地址无效")
private string email;
// 其他用户属性...
}
public class user {
@email(message = "电子邮件地址无效", regexp = "^.+@.+\\..+$", groups = userchecks.class, payload = errorpayloads.class)
private string email;
// 电子邮箱地址验证,适用于用户信息管理。
}
@valid
注解用于递归地对关联的对象或集合进行验证。
public class order {
@valid
private user user;
@valid
private list<orderitem> items;
// 其他订单属性...
}
public class order {
@valid(groups = orderchecks.class, payload = errorpayloads.class)
private user customer;
// 递归验证用户信息,适用于订单处理。
}
@positive
注解用于验证数值类型的字段是否严格大于 0。
public class account {
@positive(message = "账户余额必须为正数")
private bigdecimal balance;
// 其他账户属性...
}
public class account {
@positive(message = "账户余额必须为正数", groups = accountchecks.class, payload = errorpayloads.class)
private bigdecimal balance;
// 账户余额验证,适用于银行账户管理。
}
@positiveorzero
注解用于验证数值类型的字段是否大于或等于 0。
public class account {
@positiveorzero(message = "账户余额不能为负数")
private bigdecimal balance;
// 其他账户属性...
}
public class account {
@positiveorzero(message = "账户余额不能为负数", groups = accountchecks.class, payload = errorpayloads.class)
private bigdecimal balance;
// 账户余额验证,确保余额非负。
}
@negative
注解用于验证数值类型的字段是否严格小于 0。
public class debt {
@negative(message = "债务金额必须为负数")
private bigdecimal amount;
// 其他债务属性...
}
public class debt {
@negative(message = "债务金额必须为负数", groups = debtchecks.class, payload = errorpayloads.class)
private bigdecimal amount;
// 债务金额验证,适用于债务管理。
}
@negativeorzero
注解用于验证数值类型的字段是否小于或等于 0。
public class debt {
@negativeorzero(message = "债务金额不能为正数")
private bigdecimal amount;
// 其他债务属性...
}
public class debt {
@negativeorzero(message = "债务金额不能为正数", groups = debtchecks.class, payload = errorpayloads.class)
private bigdecimal amount;
// 债务金额验证,确保债务非正。
}
@digits
注解用于验证数值类型的字段是否符合指定的整数和小数位数。
public class financialtransaction {
@digits(integer = 10, fraction = 2, message = "交易金额格式不正确")
private bigdecimal amount;
// 其他交易属性...
}
public class financialtransaction {
@digits(integer = 10, fraction = 2, message = "交易金额格式不正确", groups = transactionchecks.class, payload = errorpayloads.class)
private bigdecimal amount;
// 交易金额必须是最多10位整数和2位小数。
}
@pastorpresent
注解用于验证日期类型的字段是否表示现在或过去的日期。
import java.time.localdate;
public class insurancepolicy {
@pastorpresent(message = "保险生效日期必须为当前或过去的日期")
private localdate effectivedate;
// 其他保险属性...
}
import java.time.localdate;
public class insurancepolicy {
@pastorpresent(message = "保险生效日期必须为当前或过去的日期", groups = insurancechecks.class, payload = errorpayloads.class)
private localdate effectivedate;
// 保险生效日期验证,适用于保险单管理。
}
@futureorpresent
注解用于验证日期类型的字段是否表示现在或未来的日期。
public class appointment {
@futureorpresent(message = "预约日期必须是当前或未来的日期")
private localdate appointmentdate;
// 其他预约属性...
}
public class appointment {
@futureorpresent(message = "预约日期必须是当前或未来的日期", groups = appointmentchecks.class, payload = errorpayloads.class)
private localdate appointmentdate;
// 预约日期验证,适用于预约系统。
}
@valid
注解用于递归地验证关联的对象或集合中的元素。
public class order {
@valid
private user customer;
@valid
private list<orderitem> items;
// 其他订单属性...
}
public class order {
@valid(groups = {orderchecks.class, itemchecks.class}, payload = {errorpayloads.class})
private list<orderitem> items;
// 递归验证订单项列表,适用于订单详细处理。
}
@validated
注解用于指定验证时使用的验证组。
public class paymentservice {
@validated(paymentchecks.class)
public void processpayment(paymentdetails details) {
// 使用特定的验证组来处理支付详情
}
}
public class paymentservice {
@validated(paymentchecks.class)
public void processpayment(@validated(paymentdetailschecks.class) paymentdetails details) {
// 使用特定的验证组来处理支付详情。
}
}
@convertgroup
注解用于在验证过程中将一个分组转换为另一个分组。
public class datamigrationservice {
@convertgroup(from = legacydatachecks.class, to = currentdatachecks.class)
public void migratedata(legacydata data) {
// 从旧数据验证转换为新数据验证
}
}
public class datamigrationservice {
@convertgroup(from = legacydatachecks.class, to = currentdatachecks.class)
public void migratedata(@validated(legacydatachecks.class) legacydata data) {
// 从旧数据验证转换为新数据验证。
}
}
@reportassingleviolation
注解用于将验证过程中的所有违反约束的情况报告为单个验证错误。
public class criticalfield {
@reportassingleviolation(message = "关键字段验证失败")
private string field;
// 其他属性...
}
public class criticalfield {
@reportassingleviolation(message = "关键字段验证失败")
private string field;
// 将所有违反约束的情况报告为单个验证错误。
}
@groups
注解用于指定验证的分组,允许在不同场景下应用不同的验证规则。
@valid
或 @validated
注解一起使用。public class user {
@valid
private profile profile;
// 其他用户属性...
}
public class profile {
@notnull(groups = registrationchecks.class)
private string biography;
// 其他个人资料属性...
}
@safehtml
注解用于验证html内容是否是安全的,防止跨站脚本(xss)攻击。
public class htmlcontent {
@safehtml(message = "内容包含不安全的html")
private string content;
// 其他html内容属性...
}
@ean
注解用于验证国际标准书号(isbn)或欧洲商品编号(ean-13)。
public class product {
@ean(message = "无效的ean或isbn编号")
private string ean;
// 验证国际标准书号或欧洲商品编号
}
虽然@url
注解在jsr 380规范中没有定义,但hibernate validator提供了类似的功能,用于验证字符串是否是有效的url格式。
public class website {
@url(message = "无效的url")
private string url;
// 其他网站属性...
}
public class website {
@url(message = "无效的url", protocol = "https", host = "example.com", port = 443)
private string url;
// 验证字符串是否是有效的url格式
电商平台,用户可以浏览商品、下单购买,并进行订单管理。该平台需要验证用户信息、商品详情、订单数据以及支付信息的准确性和有效性。
import javax.validation.constraints.*;
import javax.validation.valid;
import java.util.list;
public class ecommerceplatform {
// 用户信息
public class user {
@email(message = "电子邮件地址无效", groups = userchecks.class)
private string email;
@notblank(message = "用户名不能为空", groups = userchecks.class)
private string username;
// 用户相关方法...
}
// 商品详情
public class product {
@notnull(message = "商品id不能为空", groups = productchecks.class)
private string productid;
@positiveorzero(message = "库存数量不能为负数", groups = productchecks.class)
private int stock;
@decimalmin(value = "0.01", message = "商品价格必须至少为0.01", groups = productchecks.class)
private bigdecimal price;
// 商品相关方法...
}
// 订单
public class order {
@valid
private user user;
@valid
@size(min = 1, message = "订单至少需要一个商品项", groups = orderchecks.class)
private list<orderitem> items;
@positive(message = "订单总金额必须为正数", groups = orderchecks.class)
private bigdecimal totalamount;
// 订单相关方法...
}
// 订单项
public class orderitem {
@notnull(message = "商品id不能为空", groups = itemchecks.class)
private string productid;
@positive(message = "购买数量必须为正数", groups = itemchecks.class)
private int quantity;
// 订单项相关方法...
}
// 支付信息
public class paymentinfo {
@positive(message = "支付金额必须为正数", groups = paymentchecks.class)
private bigdecimal amount;
@notblank(message = "支付方式不能为空", groups = paymentchecks.class)
private string method;
// 支付信息相关方法...
}
}
//验证组定义
public interface userchecks {}
public interface productchecks {}
public interface orderchecks {}
public interface itemchecks {}
public interface paymentchecks {}
//错误元数据载荷
public class errorpayloads implements payload {}
在这个综合性业务场景中,我们使用了@notnull
、@notblank
、@positiveorzero
、@decimalmin
、@positive
、@email
等注解来确保数据的有效性。@valid
注解用于递归验证嵌套对象,而自定义验证组(如userchecks
、productchecks
等)允许我们在不同的场景下应用不同的验证规则。errorpayloads
类用于携带额外的元数据,这些元数据可以在验证失败时由验证器使用。
在线预订系统允许用户根据其类型(个人或公司)进行预订。系统需要对不同类型的预订应用不同的验证规则。
import javax.validation.*;
import javax.validation.constraints.*;
import java.time.localdate;
import java.util.set;
// 验证组接口
public interface personalbookingchecks {}
public interface corporatebookingchecks {}
// 预订类型枚举
public enum bookingtype {
personal, corporate;
}
// 预订实体类
public class booking {
private bookingtype type;
// 个人预订字段
@notblank(message = "个人预订的姓名必须填写", groups = personalbookingchecks.class)
private string personalname;
@email(message = "个人预订的电子邮箱格式必须正确", groups = personalbookingchecks.class)
private string personalemail;
// 公司预订字段
@notblank(message = "公司预订的公司名称必须填写", groups = corporatebookingchecks.class)
private string corporatename;
@positiveorzero(message = "公司预订的税务编号必须是非负数", groups = corporatebookingchecks.class)
private long corporatetaxid;
// 所有预订类型共有的字段
@notnull(message = "入住日期不能为空")
private localdate checkindate;
@notnull(message = "退房日期不能为空")
private localdate checkoutdate;
// 用于设置预订类型的setter方法
public void setbookingtype(bookingtype type) {
this.type = type;
}
}
// 服务层验证逻辑
public class bookingservice {
private final validator validator = validation.builddefaultvalidatorfactory().getvalidator();
public void processbooking(booking booking) {
set<constraintviolation<booking>> violations;
switch (booking.gettype()) {
case personal:
violations = validator.validate(booking, personalbookingchecks.class);
break;
case corporate:
violations = validator.validate(booking, corporatebookingchecks.class);
break;
default:
throw new illegalstateexception("未知的预订类型");
}
if (!violations.isempty()) {
// 将验证错误转换为用户友好的字符串信息
throw new illegalargumentexception("预订验证失败: " + formatvalidationerrors(violations));
}
// 如果验证通过,继续处理预订逻辑,例如保存到数据库
// 省略处理预订的代码...
}
private string formatvalidationerrors(set<constraintviolation<booking>> violations) {
stringbuilder sb = new stringbuilder();
for (constraintviolation<booking> violation : violations) {
sb.append(violation.getpropertypath()).append(": ").append(violation.getmessage()).append("\n");
}
return sb.tostring();
}
// 省略其他服务方法...
}
// 测试类
public class bookingapplication {
public static void main(string[] args) {
bookingservice service = new bookingservice();
booking booking = new booking();
// 这里设置了booking的属性和类型...
// 处理预订
service.processbooking(booking);
}
}
上述代码,booking
类包含了根据不同预订类型(个人或公司)所需的不同字段,并使用相应的jsr 380注解进行了验证。bookingservice
类中的processbooking
方法根据booking
对象的类型使用分组验证,并处理验证结果。如果存在验证错误,它将抛出一个包含所有错误的illegalargumentexception
异常。
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论