精华内容
下载资源
问答
  • Springboot的表单验证

    2019-06-18 15:32:34
    Springboot在实体类中提供了一下校验规则: @NotNull:判断是否为null, @NotBlank: 判断字符串是否为 null 或者是空串(去掉首尾空格)。 @NotEmpty: 判断字符串是否 null 或者是空串。 @Length: 判断字符的长度(最大...

    Springboot在实体类中提供了一下校验规则:

    • @NotNull:判断是否为null,
    • @NotBlank: 判断字符串是否为 null 或者是空串(去掉首尾空格)。
    • @NotEmpty: 判断字符串是否 null 或者是空串。
    • @Length: 判断字符的长度(最大或者最小)
    • @Min: 判断数值最小值
    • @Max: 判断数值最大值
    • @Email: 判断邮箱是否合法

    表单验证使用 JSR303 的验证注解,hibernate-validators,提供了使用MessageSource和访问静态资源(如CSS,JavaScript,图片)国际化支持我们的视图,使用ResourceHandlerRegistry,全部采用基于注解的配置。

    bean类

    
    public class Admin implements Serializable{
    	@NotBlank(message="姓名不能为空") //姓名的非空校验
    	private String name;
    	
    	@NotBlank(message="密码不能为空") //姓名的非空校验
    	private String password;
    	
    	@NotNull(message="年龄不能为空")  
    	@Min(value=15,message="年龄最少不能小于5岁")
    	private int  age;
    	
    	@NotBlank(message="email不能为空")
    	@Email(message="email 输入的不是一个合格的字符串,请检车看卡")
    	private String  email;
    	 ...
    }
    
    
    @Controller
    @RequestMapping("/showAdmin")
    public class AdaminController {
    	
    	@RequestMapping("/addAdmin")
    	public String showPage(@ModelAttribute("kklt") Admin admin){
    		return "addAdmin";
    	}
    	
    	/**
    	 * 完成添加的操作
    	 * @Valid:开启了多admin参数对象的数据校验
    	 * @param admin
    	 * @return
    	 * 
    	 */
    	@RequestMapping("/saveAdminOk")
    	public String saveAdminFinish(@ModelAttribute("kklt") @Valid Admin admin,BindingResult bindingResult){
    		System.out.println("来吧,我过来了~~"+bindingResult);
    		if(bindingResult.hasErrors()){
    			return "addAdmin";	
    		}
    		return "success";
    	}
    }
    
    

    这何使用Spring表单标签, 表单验证使用 JSR303 的验证注解,hibernate-validators,提供了使用MessageSource和访问静态资源(如CSS,JavaScript,图片)国际化支持我们的视图,使用ResourceHandlerRegistry,全部采用基于注解的配置。

    JSR303是一种规范,hibernate-validator是我们在这篇文章中使用的一种实现,它也提供了几个不包含在规范中自己的验证注释。

    需要注意的是:

    1、向页面传值的时候:可以在跳转页面的方法中注入一个 Adamin 对象。 由于 springmvc 会将该对象放入到 Model 中传递。 key 的名称会使用 该对象的驼峰式的命名规则来作为 key。参数的变量名需要与对象的名称相同。将首字母小写。

    2、如果想为传递的对象更改名称,可以使用@ModelAttribute(“aa”)这表示当 前传递的对象的 key 为 aa。那么我们在页面中获取该对象的 key 也需要修改为 aa * @param admin

    在html中配置:

    <body align="center" width="100%" height="100%">
    	<form th:action="@{/showAdmin/saveAdminOk}" method="post" style="width:50%;height:150px;background:#f12345F" align ="center">
    	
    		姓        名:<input type="text" name="name"  /><font th:errors="${kklt.name}" color="red"></font></br></br>
    		密        码:<input type="password" name="password"/></br><font th:errors="${kklt.password}" color="red"></font></br></br>
    		年        龄:<input type="text" name="age"/><font th:errors="${kklt.age}"  color="red"></font></br></br>
    	           用户邮箱:<input type="text" name="email"/><font th:errors="${kklt.email}"  color="red"></font></br></br>
    	           
    		<input type="submit" value="ok"/></br>
    	</form>
    </body>
    

    更多阅读

    SpringMVC, SpringBoot、 Spring Cloud及Maven的理解

    终于,我还是下决心学Java后台了

    坚持:学习Java后台的第一阶段,我学习了那些知识

    展开全文
  • 该方法是以钻孔柱状图为原始资料,首先利用SURAPC软件生成岩层等高线,然后使用CAD和ARCGIS软件生成了网格点坐标,接着在ANSYS中建立实体建模并划分网格,从而建立有限元模型,再利用接口程序在FLAC3D中生成计算模型。...
  • 1.模型验证 使用特性约束模型属性 可以使用System.ComponentModel.DataAnnotations提供的...对实体类使用特性后,可以使用ModelState.IsValid来判断验证是否通过。 例: 实体: public class DataModel { ...

     1.模型验证

    使用特性约束模型属性

    可以使用System.ComponentModel.DataAnnotations提供的特性来限制模型。

    例如,Required特性表示字段值不能为空,Range特性限制数值类型的范围。

    对实体类使用特性后,可以使用ModelState.IsValid来判断验证是否通过。

    例:

    实体:

    public class DataModel
    {
            public int Id { get; set; }
    
            public string Field1Name {get;set;}
            [Required]
            public string Field2Name { get; set; }
    
    }

     

    控制器操作:

            [HttpPost]
            public IHttpActionResult ModelValid(DataModel model)
            {
                if (!ModelState.IsValid)
                {
                    throw new HttpResponseException(HttpStatusCode.BadRequest);
                }
                return Ok(model);
            }

     

    客户端调用:

                HttpClient client = new HttpClient();
                string url = "http://localhost/WebApi_Test/api/account/modelvalid";
                using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url))
                {
                    var cont = new { Id = 1, Field1Name = "1name" };
                    HttpContent content = new StringContent(JsonConvert.SerializeObject(cont));
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    request.Content = content;
                    HttpResponseMessage response = client.SendAsync(request).Result;
                    Console.WriteLine("状态码:{0}",(int)response.StatusCode);
                    var task = response.Content.ReadAsStringAsync();
                    task.Wait();
                    Console.WriteLine("结果:{0}", task.Result);
                }

     

    输出结果:

     

    服务端运行截图:

     

    若客户端传值为:var cont = new { Id = 1, Field1Name = "1name", Field2Name="2name" };

     

    默认赋值

    Web API会对客户端未指定的模型属性赋初值。对于int,double等数值类型默认的初值为0,对于字符串或引用类型默认的初值是null。如果未对属性使用特性加以约束,那么ModelState.IsValid的值就是true,若对这样的属性应用Required特性,那么当客户端为对其赋初值时,验证将无法通过,即ModelState.IsValid的值为false。

    例:

    上例中不对Id属性赋值,运行客户端结果为:

    可见框架自动为int型的Id赋初值0

     

    过载

    此外当客户端所用实体属性于服务端时,服务端会忽略多出来的属性,但建议控制器操作(Action)所用参数列表的参数或类属性与客户端所传参数完全匹配。

    例:

    若使用上述客户端,但传值为

    var cont = new { Field1Name = "1name", Field2Name = "2name",FieldOverLoad ="overload"};

    其中DataModel不包含FieldOverLoad 字段。

    运行结果如下:

     

    过滤验证结果

    可以自定义操作过滤器来统一处理模型验证失败的情形。自定义操作过滤器派生自ActionFilterAttribute,我们需要重写OnActionExecuting方法,以便在操作(Action)调用之前处理。

    例:

    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http.Controllers;
    using System.Web.Http.Filters;
    using System.Web.Http.ModelBinding;
    
    namespace MyApi.Filters
    {
        public class ValidateModelAttribute : ActionFilterAttribute
        {
            public override void OnActionExecuting(HttpActionContext actionContext)
            {
                if (actionContext.ModelState.IsValid == false)
                {
                    actionContext.Response = actionContext.Request.CreateErrorResponse(
                        HttpStatusCode.BadRequest, actionContext.ModelState);
                }
            }
        }
    }

     

    WebApiConfig的Register方法中将上述自定义过滤器添加进来,这样过滤器对每一个操作(Action)都起作用,如果不想使其对每一个操作都起作用,而是想应用于个别操作(Action),可以将此特性应用到目标操作(Action)

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Filters.Add(new ValidateModelAttribute());
    
            // ...
        }
    }
    
    public class ProductsController : ApiController
    {
        [ValidateModel]
        public HttpResponseMessage Post(Product product)
        {
            // ...
        }
    }

     

    2模型绑定

    默认的绑定规则

    1)如果操作(Action)参数是简单类型,Web API框架会从URI中获取值。简单类型是指:.NET 框架定义的原始类型(int, bool, double等)、TimeSpan、DateTime、Guid、decimal、string;另外还有包含类型转换器的类型,改转换器可将字符串转换为此类型。这里从URI获取值具体指:从路由词典中获取值或者从URI的查询字符串中获取值。具体过程见介绍路由那篇博文。

    2)对于复杂类型,Web API会使用多媒体格式化器从消息体中获得值。

     

    类型转换

    默认的模型绑定规则中提及了包含类型转换器的类型也是简单类型。类型转换器可以使类也被看做简单类型。这样按照默认的规则就可以从URI中获取值来构建参数列表了。

    例:使用TypeConverter特性指明所使用的类型转换器。

    [TypeConverter(typeof(GeoPointConverter))]
    public class GeoPoint
    {
        public double Latitude { get; set; } 
        public double Longitude { get; set; }
    
        public static bool TryParse(string s, out GeoPoint result)
        {
            result = null;
    
            var parts = s.Split(',');
            if (parts.Length != 2)
            {
                return false;
            }
    
            double latitude, longitude;
            if (double.TryParse(parts[0], out latitude) &&
                double.TryParse(parts[1], out longitude))
            {
                result = new GeoPoint() { Longitude = longitude, Latitude = latitude };
                return true;
            }
            return false;
        }
    }
    
    class GeoPointConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }
    
        public override object ConvertFrom(ITypeDescriptorContext context, 
            CultureInfo culture, object value)
        {
            if (value is string)
            {
                GeoPoint point;
                if (GeoPoint.TryParse((string)value, out point))
                {
                    return point;
                }
            }
            return base.ConvertFrom(context, culture, value);
        }
    }

     

    使用[FromUri]

    为了强制Web API从URI中取值,可以使用FromUri特性。这样即使操作(Action)参数是复杂类型,框架也会中URI中取值来为参数赋值。

     

    使用[FromBody]

    为了强制Web API从消息体中取值,可以使用FromBody特性。这样即使操作(Action)参数是简单类型,框架也会从消息体中取值来为参数赋值。当使用FromBody特性时,Web API使用请求的Content-Type标头来选择格式化器。

    注意:对多个参数使用FromBody不起作用。

    例:

    服务端操作为:

            [HttpPost]
            public IHttpActionResult ModelValid([FromBody]DataModel model)
            {
                if (!ModelState.IsValid)
                {
                    throw new HttpResponseException(HttpStatusCode.BadRequest);
                }
                return Ok(model);
            }

     

    客户端调用为:

                HttpClient client = new HttpClient();
                string url = "http://localhost/WebApi_Test/api/account/modelvalid";
                using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url))
                {
                    //var cont = new { Id = 1, Field1Name = "111" };
                    var cont = new { Field1Name = "1name", Field2Name = "2name"};
                    HttpContent content = new StringContent(JsonConvert.SerializeObject(cont));
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    request.Content = content;
                    HttpResponseMessage response = client.SendAsync(request).Result;
                    Console.WriteLine("状态码:{0}",(int)response.StatusCode);
                    var task = response.Content.ReadAsStringAsync();
                    task.Wait();
                    Console.WriteLine("结果:{0}", task.Result);
                }

    运行客户端可以正常获得结果,若使用FromUri,无法通过模型绑定验证,也无法获得结果。

     

    改变客户端传值的方式:

                HttpClient client = new HttpClient();
                string url = "http://localhost/WebApi_Test/api/account/modelvalid?Field1Name=1name&Field2Name=2name";
                using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url))
                {
                    HttpResponseMessage response = client.SendAsync(request).Result;
                    Console.WriteLine("状态码:{0}",(int)response.StatusCode);
                    var task = response.Content.ReadAsStringAsync();
                    task.Wait();
                    Console.WriteLine("结果:{0}", task.Result);
                }

     

    运行结果为:

     

    自定义模型绑定器

    模型绑定器从值提供器(value provider)中获得原始输入,这种设计拆分出两个不同的功能:

    1)值提供器使用HTTP请求并且填充一个词典。

    2)模型绑定器使用这个词典填充模型。

    默认的值提供器从请求URI的查询字符串和路由词典中获取值。要绑定的参数的名称保存在ModelBindingContext.ModelName属性中,模型绑定器在词典中找相应的键值对。如果键值对存在,并且能够转换为待处理模型,模型绑定器分配绑定值给ModelBindingContext.Model属性。模型绑定器不会限制简单类型的转换。自定义模型绑定器需要实现IModelBinder接口。

    例:

    public class GeoPointModelBinder : IModelBinder
    {
        // List of known locations.
        private static ConcurrentDictionary<string, GeoPoint> _locations
            = new ConcurrentDictionary<string, GeoPoint>(StringComparer.OrdinalIgnoreCase);
    
        static GeoPointModelBinder()
        {
            _locations["redmond"] = new GeoPoint() { Latitude = 47.67856, Longitude = -122.131 };
            _locations["paris"] = new GeoPoint() { Latitude = 48.856930, Longitude = 2.3412 };
            _locations["tokyo"] = new GeoPoint() { Latitude = 35.683208, Longitude = 139.80894 };
        }
    
        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType != typeof(GeoPoint))
            {
                return false;
            }
    
            ValueProviderResult val = bindingContext.ValueProvider.GetValue(
                bindingContext.ModelName);
            if (val == null)
            {
                return false;
            }
    
            string key = val.RawValue as string;
            if (key == null)
            {
                bindingContext.ModelState.AddModelError(
                    bindingContext.ModelName, "Wrong value type");
                return false;
            }
    
            GeoPoint result;
            if (_locations.TryGetValue(key, out result) || GeoPoint.TryParse(key, out result))
            {
                bindingContext.Model = result;
                return true;
            }
    
            bindingContext.ModelState.AddModelError(
                bindingContext.ModelName, "Cannot convert value to Location");
            return false;
        }
    }

     

    使用上述自定义的模型绑定器的方式有多种。

    方式一、对于一个操作(Action)。

    例:

    public HttpResponseMessage Get([ModelBinder(typeof(GeoPointModelBinder))] GeoPoint location)

     

    方式二、对于一个控制器。

    例:

    [ModelBinder(typeof(GeoPointModelBinder))]
    public class GeoPoint
    {
        // ....
    }

     

    方式三、注册模型绑定器后,依然要使用在操作上使用特性,不过不用指定类型

    例:

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            var provider = new SimpleModelBinderProvider(
                typeof(GeoPoint), new GeoPointModelBinder());
            config.Services.Insert(typeof(ModelBinderProvider), 0, provider);
    
            // ...
        }
    }
    public HttpResponseMessage Get([ModelBinder] GeoPoint location) { ... }

     

    自定义值提供器

    模型绑定器从值提供器中获取值,自定义值提供器需要实现IValueProvider接口。

    例:

    public class CookieValueProvider : IValueProvider
    {
        private Dictionary<string, string> _values;
    
        public CookieValueProvider(HttpActionContext actionContext)
        {
            if (actionContext == null)
            {
                throw new ArgumentNullException("actionContext");
            }
    
            _values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            foreach (var cookie in actionContext.Request.Headers.GetCookies())
            {
                foreach (CookieState state in cookie.Cookies)
                {
                    _values[state.Name] = state.Value;
                }
            }
        }
    
        public bool ContainsPrefix(string prefix)
        {
            return _values.Keys.Contains(prefix);
        }
    
        public ValueProviderResult GetValue(string key)
        {
            string value;
            if (_values.TryGetValue(key, out value))
            {
                return new ValueProviderResult(value, value, CultureInfo.InvariantCulture);
            }
            return null;
        }
    }

     

    创建值提供器工厂,其派生自ValueProviderFactory

    public class CookieValueProviderFactory : ValueProviderFactory
    {
        public override IValueProvider GetValueProvider(HttpActionContext actionContext)
        {
            return new CookieValueProvider(actionContext);
        }
    }

     

    注册值提供器工厂。

    public static void Register(HttpConfiguration config)
    {
        config.Services.Add(typeof(ValueProviderFactory), new CookieValueProviderFactory());
    
        // ...
    }

     

    使用值提供器工厂,指定使用CookieValueProvider。

    public HttpResponseMessage Get(
    [ValueProvider(typeof(CookieValueProviderFactory))] GeoPoint location)

     

    自定义HttpParameterBinding

    ModelBinderAttribute继承自ParameterBindingAttributeParameterBindingAttribute继承自AttributeParameterBindingAttribute只有一个方法GetBinding,改=该方法返回HttpParameterBindingHttpParameterBinding代表了参数与值之间的绑定关系。

    public class ModelBinderAttribute : ParameterBindingAttribute
    {......}
    public abstract class ParameterBindingAttribute : Attribute
    {
            protected ParameterBindingAttribute();
    
            // 获得参数绑定
            // parameter:参数描述
            public abstract HttpParameterBinding GetBinding(HttpParameterDescriptor parameter);
    }

     

    例:利用请求头中的if-matchif-none-match获得ETags

    public class ETag
    {
        public string Tag { get; set; }
    }
    public enum ETagMatch
    {
        IfMatch,
        IfNoneMatch
    }
    public class ETagParameterBinding : HttpParameterBinding
    {
        ETagMatch _match;
    
        public ETagParameterBinding(HttpParameterDescriptor parameter, ETagMatch match) 
            : base(parameter)
        {
            _match = match;
        }
    
        public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, 
            HttpActionContext actionContext, CancellationToken cancellationToken)
        {
            EntityTagHeaderValue etagHeader = null;
            switch (_match)
            {
                case ETagMatch.IfNoneMatch:
                    etagHeader = actionContext.Request.Headers.IfNoneMatch.FirstOrDefault();
                    break;
    
                case ETagMatch.IfMatch:
                    etagHeader = actionContext.Request.Headers.IfMatch.FirstOrDefault();
                    break;
            }
    
            ETag etag = null;
            if (etagHeader != null)
            {
                etag = new ETag { Tag = etagHeader.Tag };
            }
            actionContext.ActionArguments[Descriptor.ParameterName] = etag;
    
            var tsc = new TaskCompletionSource<object>();
            tsc.SetResult(null);
            return tsc.Task;
        }
    }

     

    为使用自定义的HttpParameterBinding,定义一个派生自ParameterBindingAttribute的类。

    public abstract class ETagMatchAttribute : ParameterBindingAttribute
    {
        private ETagMatch _match;
    
        public ETagMatchAttribute(ETagMatch match)
        {
            _match = match;
        }
    
        public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
        {
            if (parameter.ParameterType == typeof(ETag))
            {
                return new ETagParameterBinding(parameter, _match);
            }
            return parameter.BindAsError("Wrong parameter type");
        }
    }
    
    public class IfMatchAttribute : ETagMatchAttribute
    {
        public IfMatchAttribute()
            : base(ETagMatch.IfMatch)
        {
        }
    }
    
    public class IfNoneMatchAttribute : ETagMatchAttribute
    {
        public IfNoneMatchAttribute()
            : base(ETagMatch.IfNoneMatch)
        {
        }
    }

     

    在控制器操作(Action)中使用它。

    public HttpResponseMessage Get([IfNoneMatch] ETag etag) { ... }

     

    另外一种使用自定义的HttpParameterBinding的方式是利用HttpConfiguration.ParameterBindingRules这个属性。

    例:

    config.ParameterBindingRules.Add(p =>
    {
        if (p.ParameterType == typeof(ETag) && 
            p.ActionDescriptor.SupportedHttpMethods.Contains(HttpMethod.Get))
        {
            return new ETagParameterBinding(p, ETagMatch.IfNoneMatch);
        }
        else
        {
            return null;
        }
    });

     

    可插拔服务IActionValueBinder

    整个模型绑定过程是由IActionValueBinder服务控制器的。其默认实现完成以下工作:

    1)在参数中查找ParameterBindingAttribute,包括[FromBody], [FromUri], and [ModelBinder], 或者自定义特性。

    2)如果步奏1)中没有找到,那么在HttpConfiguration.ParameterBindingRules中寻找一个返回值为HttpParameterBinding的方法。

    3)如果没有找到就使用默认规则。

    如果操作(Action)参数是简单类型,Web API框架会从URI中获取值。简单类型是指:.NET 框架定义的原始类型(int, bool, double等)、TimeSpan、DateTime、Guid、decimal、string;另外还有包含类型转换器的类型,改转换器可将字符串转换为此类型。这里从URI获取值具体指:从路由词典中获取值或者从URI的查询字符串中获取值。具体过程见介绍路由那篇博文。对于复杂类型,Web API会使用多媒体格式化器从消息体中获得值。

     

    参考:

    https://docs.microsoft.com/en-us/aspnet/web-api/

    部分示例自于该网站

     

    转载与引用请注明出处。
    
    时间仓促,水平有限,如有不当之处,欢迎指正。

    转载于:https://www.cnblogs.com/hdwgxz/p/8759886.html

    展开全文
  • 通用工具类篇 --Spring ValidationSpring ValidationJSR-303 简介JSR-303 基本的校验规则空检查布尔检查长度检查日期检查正则检查数值检查使用 Spring Validation 验证POM定义验证工具类修改实体类注入工具类注解...

    Spring Validation

    JSR-303 简介

    JSR-303 是 JavaEE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是 Hibernate Validator。

    此实现与 Hibernate ORM 没有任何关系。JSR-303 用于对 Java Bean 中的字段的值进行验证。 Spring MVC 3.x 之中也大力支持 JSR-303,可以在控制器中使用注解的方式对表单提交的数据方便地验证。

    Spring 4.0 开始支持 Bean Validation 功能。

    JSR-303 基本的校验规则

    空检查

    • @Null 验证对象是否为 null
    • @NotNull 验证对象是否不为 null, 无法查检长度为 0 的字符串
    • @NotBlank 检查约束字符串是不是 Null 还有被 Trim 的长度是否大于 0,只对字符串,且会去掉前后空格
    • @NotEmpty 检查约束元素是否为 NULL 或者是 EMPTY

    布尔检查

    • @AssertTrue 验证 Boolean 对象是否为 true
    • @AssertFalse 验证 Boolean 对象是否为 false

    长度检查

    • @Size(min=, max=) 验证对象(Array, Collection , Map, String)长度是否在给定的范围之内
    • @Length(min=, max=) 验证字符串长度介于 minmax 之间

    日期检查

    • @Past 验证 DateCalendar 对象是否在当前时间之前,验证成立的话被注释的元素一定是一个过去的日期
    • @Future 验证 DateCalendar 对象是否在当前时间之后 ,验证成立的话被注释的元素一定是一个将来的日期

    正则检查

    • @Pattern 验证 String 对象是否符合正则表达式的规则,被注释的元素符合制定的正则表达式
      • regexp:正则表达式
      • flags:指定 Pattern.Flag 的数组,表示正则表达式的相关选项

    数值检查

    注意: 建议使用在 String ,Integer 类型,不建议使用在 int 类型上,因为表单值为 “” 时无法转换为 int,但可以转换为 String“”Integernull

    • @Min 验证 Number 和 String 对象是否大等于指定的值
    • @Max 验证 Number 和 String 对象是否小等于指定的值
    • @DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过 BigDecimal 定义的最大值的字符串表示 .小数 存在精度
    • @DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过 BigDecimal 定义的最小值的字符串表示 .小数 存在精度
    • @Digits 验证 Number 和 String 的构成是否合法
    • @Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,integer 指定整数精度,fraction 指定小数精度
    • @Range(min=, max=) 被指定的元素必须在合适的范围内
    • @Range(min=10000,max=50000,message=”range.bean.wage”)
    • @Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个 map,则对其中的值部分进行校验.(是否进行递归验证)
    • @CreditCardNumber 信用卡验证
    • @Email 验证是否是邮件地址,如果为 null,不进行验证,算通过验证
    • @ScriptAssert(lang= ,script=, alias=)
    • @URL(protocol=,host=, port=,regexp=, flags=)

    使用 Spring Validation 验证

    POM

    这里我们使用 Hibernate Validator 5.x 来实现 Spring Validation 接口,pom.xml 文件如下:

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

    主要是增加了 org.hibernate:hibernate-validator 依赖

    定义验证工具类

    已为大家封装好了工具类,享用即可。创建一个名为 BeanValidator 的工具类,代码如下:

    
    
    package com.funtl.my.shop.commons.validator;
    
    import org.springframework.beans.factory.annotation.Autowired;
    
    import javax.validation.ConstraintViolation;
    import javax.validation.ConstraintViolationException;
    import javax.validation.Validator;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * JSR303 Validator(Hibernate Validator)工具类.
     * <p>
     * ConstraintViolation 中包含 propertyPath, message 和 invalidValue 等信息.
     * 提供了各种 convert 方法,适合不同的 i18n 需求:
     * 1. List<String>, String 内容为 message
     * 2. List<String>, String 内容为 propertyPath + separator + message
     * 3. Map<propertyPath, message>
     * <p>
     * 详情见wiki: https://github.com/springside/springside4/wiki/HibernateValidator
     *
     * <p>Title: BeanValidator</p>
     * <p>Description: </p>
     *
     * @author Lusifer
     * @version 1.0.0
     * @date 2018/6/26 17:21
     */
    public class BeanValidator {
    
        @Autowired
        private static Validator validator;
    
        public static void setValidator(Validator validator) {
            BeanValidator.validator = validator;
        }
    
        /**
         * 调用 JSR303 的 validate 方法, 验证失败时抛出 ConstraintViolationException.
         */
        private static void validateWithException(Validator validator, Object object, Class<?>... groups) throws ConstraintViolationException {
            Set constraintViolations = validator.validate(object, groups);
            if (!constraintViolations.isEmpty()) {
                throw new ConstraintViolationException(constraintViolations);
            }
        }
    
        /**
         * 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 中为 List<message>.
         */
        private static List<String> extractMessage(ConstraintViolationException e) {
            return extractMessage(e.getConstraintViolations());
        }
    
        /**
         * 辅助方法, 转换 Set<ConstraintViolation> 为 List<message>
         */
        private static List<String> extractMessage(Set<? extends ConstraintViolation> constraintViolations) {
            List<String> errorMessages = new ArrayList<>();
            for (ConstraintViolation violation : constraintViolations) {
                errorMessages.add(violation.getMessage());
            }
            return errorMessages;
        }
    
        /**
         * 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 Map<property, message>.
         */
        private static Map<String, String> extractPropertyAndMessage(ConstraintViolationException e) {
            return extractPropertyAndMessage(e.getConstraintViolations());
        }
    
        /**
         * 辅助方法, 转换 Set<ConstraintViolation> 为 Map<property, message>.
         */
        private static Map<String, String> extractPropertyAndMessage(Set<? extends ConstraintViolation> constraintViolations) {
            Map<String, String> errorMessages = new HashMap<>();
            for (ConstraintViolation violation : constraintViolations) {
                errorMessages.put(violation.getPropertyPath().toString(), violation.getMessage());
            }
            return errorMessages;
        }
    
        /**
         * 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 List<propertyPath message>.
         */
        private static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e) {
            return extractPropertyAndMessageAsList(e.getConstraintViolations(), " ");
        }
    
        /**
         * 辅助方法, 转换 Set<ConstraintViolations> 为 List<propertyPath message>.
         */
        private static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations) {
            return extractPropertyAndMessageAsList(constraintViolations, " ");
        }
    
        /**
         * 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 List<propertyPath + separator + message>.
         */
        private static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) {
            return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator);
        }
    
        /**
         * 辅助方法, 转换 Set<ConstraintViolation> 为 List<propertyPath + separator + message>.
         */
        private static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations, String separator) {
            List<String> errorMessages = new ArrayList<>();
            for (ConstraintViolation violation : constraintViolations) {
                errorMessages.add(violation.getPropertyPath() + separator + violation.getMessage());
            }
            return errorMessages;
        }
    
        /**
         * 服务端参数有效性验证
         *
         * @param object 验证的实体对象
         * @param groups 验证组
         * @return 验证成功:返回 null;验证失败:返回错误信息
         */
        public static String validator(Object object, Class<?>... groups) {
            try {
                validateWithException(validator, object, groups);
            } catch (ConstraintViolationException ex) {
                List<String> list = extractMessage(ex);
                list.add(0, "数据验证失败:");
    
                // 封装错误消息为字符串
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < list.size(); i++) {
                    String exMsg = list.get(i);
                    if (i != 0 ){
                        sb.append(String.format("%s. %s", i, exMsg)).append(list.size() > 1 ? "<br/>" : "");
                    } else {
                        sb.append(exMsg).append(list.size() > 1 ? "<br/>" : "");
                    }
                }
    
                return sb.toString();
            }
    
            return null;
        }
    }
    

    修改实体类

    修改实体类,增加验证注解,以后我们只需要在实体类的属性上使用 JSR-303 注解即可完成相关数据的验证工作,关键代码如下:

    @Length(min = 6, max = 20, message = "用户名长度必须介于 6 和 20 之间")
    private String username;
    @Length(min = 6, max = 20, message = "密码长度必须介于 6 和 20 之间")
    private String password;
    @Pattern(regexp = RegexpUtils.PHONE, message = "手机号格式不正确")
    private String phone;
    @Pattern(regexp = RegexpUtils.EMAIL, message = "邮箱格式不正确")
    private String email;
    

    注入工具类

    修改 spring-context.xml 文件,注入 Validator 工具类,配置如下:

    <!-- 配置 Bean Validator 定义 -->
    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
    <bean id="beanValidator" class="com.funtl.my.shop.commons.validator.BeanValidator">
        <property name="validator" ref="validator" />
    </bean>
    

    注解注入

    @Component
    public class BeanValidator {
    
        @Autowired
        private Validator validatorInstance;
    
        private static Validator validator;
    
        @PostConstruct
        public void init() {
            BeanValidator.validator = validatorInstance;
        }
      }
    

    RegexpUtils(正则表达式邮箱手机)

    package com.funtl.myshop.commons.utils;
    
    /**
     * 正则表达式工具类
     * <p>Title: RegexpUtils</p>
     * <p>Description: </p>
     *
     * @author Lusifer
     * @version 1.0.0
     * @date 2018/6/16 23:48
     */
    public class RegexpUtils {
        /**
         * 验证手机号
         */
        public static final String PHONE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
    
        /**
         * 验证邮箱地址
         */
        public static final String EMAIL = "\\w+(\\.\\w)*@\\w+(\\.\\w{2,3}){1,3}";
    
        /**
         * 验证手机号
         * @param phone
         * @return
         */
        public static boolean checkPhone(String phone) {
            return phone.matches(PHONE);
        }
    
        /**
         * 验证邮箱
         * @param email
         * @return
         */
        public static boolean checkEmail(String email) {
            return email.matches(EMAIL);
        }
    }
    
    

    Controlle效果

    @RestController
    @RequestMapping(value = "reg")
    public class RegController extends AbstractBaseController<TbUser> {
    
        @Autowired
        private TbUserService tbUserService;
    
        @Autowired
        private RegService regService;
    
        @ApiOperation(value = "用户注册", notes = "参数为实体类,注意用户名和邮箱不要重复")
        @PostMapping(value = "user")
        public AbstractBaseResult reg(@ApiParam(name = "tbUser", value = "用户模型") TbUser tbUser) {
            // 数据校验
            String message = BeanValidator.validator(tbUser);
            if (StringUtils.isNotBlank(message)) {
                return error(message, null);
            }
    
            // 验证密码是否为空
            if (StringUtils.isBlank(tbUser.getPassword())) {
                return error("密码不可为空", null);
            }
    
            // 验证用户名是否重复
            if (!tbUserService.unique("username", tbUser.getUsername())) {
                return error("用户名已存在", null);
            }
    
            // 验证邮箱是否重复
            if (!tbUserService.unique("email", tbUser.getEmail())) {
                return error("邮箱重复,请重试", null);
            }
    
            // 注册用户
            try {
                tbUser.setPassword(DigestUtils.md5DigestAsHex(tbUser.getPassword().getBytes()));
                TbUser user = tbUserService.save(tbUser);
                if (user != null) {
                    regService.sendEmail(user);
                    response.setStatus(HttpStatus.CREATED.value());
                    return success(request.getRequestURI(), user);
                }
            } catch (Exception e) {
                // 这里补一句,将 RegService 中的异常抛到 Controller 中,这样可以打印出调试信息
                return error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "注册邮件发送失败", e.getMessage());
            }
    
            // 注册失败
            return error("注册失败,请重试", null);
        }
    }
    

    效果演示

    配置完成后,在浏览器端测试直接提交数据,效果如下:
    在这里插入图片描述

    展开全文
  • 1⃣️验证信息的发送者是合法的,实体认证,包括信源、信宿的认证和识别 2⃣️验证消息的完整性,验证数据在传输过程中合存储过程中是否被篡改、重放或延迟 MAC的性质 MAC和单向Hash函数一样,但是包括了一个密钥,...

    认证的两个目的

    1⃣️验证信息的发送者是合法的,实体认证,包括信源、信宿的认证和识别
    2⃣️验证消息的完整性,验证数据在传输过程中合存储过程中是否被篡改、重放或延迟

    MAC的性质

    • MAC和单向Hash函数一样,但是包括了一个密钥,只有拥有密钥的人才能鉴别这个hash函数,所以消息认证码MAC提供的可鉴别性是很有用的。
    • 因为不同的钥匙会产生不同的Hash函数,如果共享钥匙X和消息M改变了都无法得到正确的Hash函数值,所以MAC能在验证发送者的消息没有经过篡改的同时又可以验证消息的发送者。即同时验证消息完整性和发送者是否合法。

    消息认证码MAC实现的过程:

    消息认证码的实现过程
    对上图做出以下的解释:
    M是信息发送方要发送的消息,K是收发双方共同拥有的钥匙(如何保证收发双方能够在不安全的信道中安全地共享密钥可以采用对称密钥交换协议中的Diffie-Hellman算法

    MAC是如何实现的消息认证和用户认证的呢?

    发送方发送消息M和经过收发双方共有的密钥K加密后的消息认证码。
    接收方不是像加密过程一样进行解密,而是进行验证,验证的过程就是将发送方送过来的消息M用自己有的密钥K进行重新计算消息认证码,将接收方自己计算的消息认证码和发送方送过来的消息认证码进行比较,如果两者相同那么验证成功,如果不同则说明要么是发送者不合法(发送方的密钥K和接收方的密钥K不相同)要么是消息完整性被破坏(接收到的消息M有问题)为什么MAC消息验证码既能完成发送方身份认证又能完成消息完整性验证

    展开全文
  • 进一步,通过三维打印得到实体实验模型,并对实验模型进行工程受力验证,进而根据工程验证情况调整热扩散程度,使得优化模型的厚度更加逼近实际受力要求;最后通过循环迭代方式得到满足受力要求的重量优化模型.实验结果...
  • DELTA 主要基于 TensorFlow 构建,能同时支持 NLP(自然语言处理)和语音任务及数值型特征的训练,整合了包括文本分类、命名实体识别、自然语言推理、问答、序列到序列文本生成、语音识别、说话人验证、语音情感识别等...
  • 分析了非线性干涉误差的理论模型, 提出了基于数值拟合的非线性干涉光谱数据重构算法, 并进行了仿真验证。仿真结果表明, 采用数值拟合的重构算法可成功复原目标光谱, 消除非线性干涉误差; 与采用线性拟合的重构算法...
  • 只允许输入数值型。将输入转换成Number类型 v-model.lazy 并不是实时改变,而是在失去焦点或者按回车时才会更新 二. JSR303数据校验 SpringMVC映射的实体类可以通过添加注解的方式进行数据校验 基本校验注解 (1)...
  • 在激光熔覆成形过程中,送粉喷嘴性能的好坏对熔覆成形件的质量具有重要影响。为探究影响送粉喷嘴性能的关键参数,...依据该关键参数制造出送粉喷嘴的实体,进行了粉末汇聚、激光熔覆成形实验,验证了该送粉喷嘴的效果。
  • 采用FLAC数值模拟与现场应力计监测相互验证的方法,对上层煤开采对底板岩巷的影响进行研究分析,模拟结果表明:123上05工作面回采后对下部岩层有应力扰动作用,在实体煤侧形成增压区,在采空区侧形成卸压区;垂直应力与...
  • 针对制造商在传统实体渠道的基础上积极开辟网络渠道的双渠道供应链,从消费者效用理论角度构建单一渠道和双渠道供应链Stackelberg博弈模型,在零售商创新投入和消费者渠道...最后通过数值仿真结果验证了协调机制的可行性.
  • 为解决山西焦煤集团屯兰矿18401工作面沿空留巷的应用问题,通过理论分析、数值模拟以及工程实践及观测,验证了膏体混凝土作为充填材料的可行性,确定合理的充填宽度,通过巷旁支护结构的加强支护,现场应用及巷道位移观测...
  • 中国电信计费模型:数据模型

    热门讨论 2009-03-31 11:18:20
    3.2.13 产品计费事件类型(Product_Usage_Event_Type)实体 65 3.2.14 商品关系(Product_Offer_Relationship)实体 66 3.2.15 商品明细(Product_Offer_Detail)实体 67 3.2.16 商品限制(Product_Offer_Restrication)实体...
  • 针对同一机构实体对应多个机构名称的问题,提出了一种基于Jaccard相似度数据空间转换的机构别名挖掘方法。根据机构与作者间的隶属关系,建立机构-作者二部图模型;采用Jaccard相似度度量两机构名称所对应作者姓名...
  • 针对FLAC3D数值模拟软件在复杂三维建模以及网格划分等前处理中存在的不直观、工作量大等问题,提出了基于Auto CAD与HYPERMESH软件自动生成复杂地质体FLAC3D模型的方法。该方法以地质地形图及岩层柱状图为原始资料,...
  • DB_004_创建表

    2019-06-28 09:06:00
    包括字段名称、数据类型、验证规则、主键和实体的完整性、索引等内容 创建表与表的关系:定义外键和参照完整性 表中数据的操作:显示、插入、修改、删除等数据方法 2 字段的数据类型 字段决定存储数据的长度...
  • 针对铰接式自卸车的铰接体在转向时受力复杂的特点,采用三维造型软件CATIA对其进行三维实体建模,通过有限元数值模拟对铰接系统的结构和强度进行分析和计算,获得车辆转向过程中的最大载荷。有限元分析结果表明,车辆...
  • 为探求工作面过空巷过程中围岩活动规律,利用突变理论从势能积聚的角度分析了工作面与前方空巷之间煤柱的失稳机理,并运用...采用数值模拟方法分析了回采过程中煤柱和基本顶塑性区范围,模拟结果有力验证了理论分析结果。
  • 初识Filemaker(一)

    2021-03-08 12:54:19
    学习Filemaker开发什么是Filemaker主要内容第一章:数据和数据库(一)(一)数据建模以及创建ER表1)找出表中的实体以及属性2)建立表与表的关系3)创建ER表(二)新建字段 新建字段 字段数据类型文本...
  • 新协议由于在签名过程中只使用了一个标量乘,验证过程中只使用了两个标量乘,并且没有对运算和模拟运算,因此比以前的方案效率更高.通过在新协议中重复使用初始值实现了MN与HA之间的重新同步;通过构造一个不断变化...
  • 提出了基于光传输建模分析,数值计算、工程实践3个层次相融合的大型光学系统准直误差分析研究方法,并以空间滤波器系统为对象进行了深入的研究与分析。针对模块准直精度建立了带误差传递的光传输模型,借助误差分析...
  • 采用现场调研、理论分析、数值模拟等方法研究综放窄煤柱沿空掘巷围岩变形破坏特征、灾变失稳过程及相应控制技术,研究结果表明:①受不稳定覆岩运动影响,沿空掘巷靠煤柱侧顶板煤体破碎严重,煤柱帮与实体煤帮变形...
  • 为研究锚固剂-围岩界面剪应力分布规律,基于锚杆、锚固剂...采用FLAC3D软件开展锚杆、锚固剂实体单元数值计算,验证了锚固剂-围岩界面剪应力沿锚固长度呈递减分布的规律,发现剪应力在锚固段始端前1/3位置递减明显。
  • 为解决深井高应力沿空巷道围岩变形大、支护困难的问题,以孙村煤矿2216工作面地质和开采条件为背景,采用数值模拟软件FLAC3D建立计算模型,分析比较了采用普通锚索、普通锚索+巷旁切顶和注浆锚索+巷旁切顶3种支护...
  • ASPNETValidator/RENumber.aspx 数值格式验证 ASPNETValidator/REPhone.aspx 电话号码格式验证 ASPNETValidator/REUrl.aspx URL地址格式验证 ASPNETValidator/SummaryDialog.aspx 对话框式...
  • 14、数据验证相关 15、类操作相关 16、清除缓存/文件相关工具类 17、剪贴板相关工具类 18、关闭操作流相关 19、常量相关 20、转换操作相关 21、倒计时 22、崩溃相关 23、日期操作相关 24、设备信息相关 25、使用UUID...

空空如也

空空如也

1 2 3 4
收藏数 66
精华内容 26
关键字:

验证数值实体