当前位置: 首页 > news >正文

天天爱天天做网站江苏 建设 招标有限公司网站

天天爱天天做网站,江苏 建设 招标有限公司网站,众v创业营网站建设,网站建设兼职劳务协议概述 当我们想提供可靠的 API 接口#xff0c;对参数的校验#xff0c;以保证最终数据入库的正确性#xff0c;是必不可少的活。前、后端校验都是保证参数的准确性的手段之一#xff0c;前端校验并不安全#xff0c;任何人都可以通过接口来调用我们的服务#xff0c;就算…概述 当我们想提供可靠的 API 接口对参数的校验以保证最终数据入库的正确性是必不可少的活。前、后端校验都是保证参数的准确性的手段之一前端校验并不安全任何人都可以通过接口来调用我们的服务就算加了一层token的校验有心人总会转空子来传各式各样错误的参数如果后端不校验导致数据库数据混乱。传统的方式使用if-else进行参数校验太太繁琐了如果有几十个字段要校验,那这个方法里面将会变得非常臃肿,实在不够优雅。 虽然使用if else进行参数校验可以实现基本的校验功能但是这种方式存在以下几个问题 代码冗余如果需要对多个接口进行参数校验就需要在每个接口中编写相同的校验逻辑代码冗余维护成本高。可读性差如果校验逻辑比较复杂那么使用 if else 进行校验的代码可读性较差不利于代码的维护和优化。安全性差如果使用 if else 进行校验那么恶意用户可能会利用漏洞绕过校验从而导致安全问题。 因此使用参数校验框架可以有效地解决上述问题具有以下几个优点 简化代码使用参数校验框架可以简化校验逻辑减少代码冗余提高代码的可读性和可维护性。提高安全性参数校验框架可以避免参数注入、SQL 注入、XSS 攻击等安全问题提高系统的安全性和可靠性。提高效率使用参数校验框架可以提高开发效率减少开发时间和成本并且可以方便地进行扩展和定制。 总之使用参数校验框架可以有效地提高系统的安全性、可靠性和可维护性减少代码冗余提高开发效率是开发过程中不可或缺的一部分。 为什么要使用 Spring Validation 权限校验框架 有哪些参数校验框架呢 以下是几个常用的参数校验框架 Hibernate Validator Hibernate Validator 是一个基于 Bean Validation 标准的参数校验框架可以实现对 Java Bean 属性的校验支持多种校验注解和自定义校验规则。 Spring Validation Spring Validation 是 Spring 框架提供的参数校验框架基于 Bean Validation 标准可以实现对 Java Bean 属性和方法参数的校验支持多种校验注解和自定义校验规则。 Apache Commons Validator Apache Commons Validator 是一个通用的参数校验框架支持多种校验规则和自定义校验规则可以实现对字符串、数字、日期等数据类型的校验。 JSR-303 JSR-303 是 Java EE 6 中定义的 Bean Validation 标准提供了一套参数校验规范和 API可以实现对 Java Bean 属性的校验支持多种校验注解和自定义校验规则。 Bean-ValidationBean-Validation 是一款轻量级的参数校验框架基于 JSR-303 标准可以实现对 Java Bean 属性的校验支持多种校验注解和自定义校验规则。 这些框架都可以实现对参数的校验提供了一套完整的校验规范和 API 可以有效地避免非法参数和恶意攻击提高系统的安全性和可靠性。根据不同的业务需求和技术栈可以选择不同的框架进行参数校验。 为什么使用 Spring Validation 基于 Bean Validation 标准Spring Validation 是基于 Bean Validation 标准的参数校验框架可以实现对 Java Bean 属性和方法参数的校验提供了一套完整的校验规范和 API可以很方便地进行扩展和定制。 支持多种校验注解Spring Validation 支持多种校验注解比如 NotNull、Size、Min、Max 等可以满足不同的校验需求同时也支持自定义校验注解。 集成方便Spring Validation 是 Spring 框架提供的参数校验框架与 Spring 框架集成非常方便可以通过简单的配置实现参数校验。 可扩展性强Spring Validation 提供了很好的扩展性可以自定义校验注解和校验器满足不同的校验需求。 可读性高Spring Validation 的校验注解非常简洁明了代码可读性高可以很方便地查看和维护校验逻辑。 总之使用 pring Validation 参数校验框架可以提高代码的可读性和可维护性减少代码冗余提高开发效率同时还可以有效地避免非法参数和恶意攻击提高系统的安全性和可靠性。 1、SpringBoot之validation 1.1 validation注解说明 validation 包下其它常用的校验注解 注意 字段上面的注解千万不要用错了不然会报内部错误 注解含义Null任何类型必须为null。NotBlank字符串、字符类不能为null并且去掉空格后长度大于0。NotNull任何类型不能为null。Length(min 6, max 8, message “密码长度为6-8位。”)字符串的长度必须在指定的范围内。NotEmpty适用于String、Collection集合、Map、数组等参数不能为null且长度大于0。AssertTrueBoolean、boolean属性必须是true。AssertFalseBoolean、boolean属性必须是false。Min(10)必须是一个数字且其值必须大于等于指定的最小值整型。Max(10)必须是一个数字且其值必须小于等于指定的最大值整型。DecimalMin(“10”)必须是一个数字且其值必须大于等于指定的最小值字符串可以是小数。DecimalMax(“10”)必须是一个数字且其值必须小于等于指定的最大值字符串可以是小数。Size(max 10, min 1)限定集合的大小必须在指定范围内。Digits(integer 3, fraction 2, message “请输入有效的数字”)用于验证数字的整数位数和小数位数限制。Past时间、日期必须是一个过去的时间或日期。Future时间、日期必须是一个未来的时间或日期。Email字符串必须是一个有效的邮箱格式。Pattern(regexp “[a-zA-Z]*”, message “密码不合法”)字符串、字符必须匹配指定的正则表达式。Range(max 150, min 1, message “年龄范围应该在1-150内。”)数字类型原子和包装必须在指定的范围内。URL(protocol, host, port, regexp, flags)被注释的字符串必须是一个有效的URL。CreditCardNumber被注释的字符串必须通过Luhn校验算法通常用于银行卡、信用卡等号码。ScriptAssert(lang, script, alias)要求存在支持Java Scripting APIJSR 223的实现。SafeHtml(whitelistType, additionalTags)要求classpath中存在jsoup包用于验证HTML内容的安全性。 1.2 Valid和Validated区别 Validjavax.validation包下 和 Validatedorg.springframework.validation.annotation包下注解。两者大致有以下的区别 名称是否实现声明式校验是否支持嵌套校验是否支持分组校验ValidfalsetruefalseValidatedtruefalsetrue 绝大多数场景下我们使用 Validated 注解即可。而在有嵌套校验的场景我们使用 Valid 注解添加到成员属性上。 Valid 来源Valid 是 JSR-303/JSR-349 Bean Validation API 的一部分该 API 被广泛称为 Bean Validation 或 Hibernate Validator尽管 Hibernate Validator 是该 API 的一个流行实现。使用场景它通常用于方法级别的参数验证如 Spring MVC 控制器中的方法参数。功能触发方法参数或返回类型的验证。在 Spring MVC 中它会自动触发 Spring 的数据绑定和验证机制。限制默认情况下Valid 不能用在类型级别如类级别进行组验证尽管可以通过一些配置或自定义逻辑来实现。 Validated 来源Validated 是 Spring Framework 提供的注解用于扩展 Valid 的功能。使用场景它不仅可以用于方法级别的参数验证还可以用于类级别以支持组验证。功能除了基本的验证功能外Validated 还支持分组验证允许你根据不同的上下文应用不同的验证规则。分组验证这是 Validated 相对于 Valid 的主要优势。通过定义不同的验证组可以在不同的情况下应用不同的验证规则。 比较 基本功能两者都用于触发 Bean 验证。来源Valid 来自 JSR-303/JSR-349 Bean Validation API而 Validated 是 Spring 特有的。分组验证Validated 支持分组验证而 Valid 不直接支持尽管可以通过其他方式实现。使用场景对于简单的验证场景Valid 通常就足够了。但是如果你需要更复杂的验证逻辑比如分组验证那么 Validated 是更好的选择。 结论 在大多数基本情况下Valid 和 Validated 可以互换使用因为它们都触发了 Bean 验证。然而当你需要利用分组验证或其他 Spring 特有的验证功能时Validated 提供了更多的灵活性和控制。因此在选择使用哪个注解时你应该根据你的具体需求和上下文来决定。 基本使用 参数校验分为简单校验、嵌套校验、分组校验。 1.3 SpringBoot Validation 快速失败(failFast) SpringBoot Validation 快速失败是指在使用Spring Boot进行参数校验时当遇到第一个校验失败的情况时立即停止后续的校验并抛出异常。这种机制有助于减少不必要的资源消耗并使得错误信息更加明确和易于处理。以下是关于SpringBoot Validation 快速失败的一些关键点和实现方式 1、背景与问题 在使用Spring Boot进行开发时通常会使用Hibernate Validator或Spring的spring-boot-starter-validation来进行参数校验。默认情况下如果一个对象中有多个字段需要校验并且这些字段使用了多个校验注解如NotNull、Max等Hibernate Validator会按顺序依次校验这些字段。如果某个字段校验失败它不会立即停止校验而是会继续校验其他字段直到所有字段都被校验完毕。这可能会导致以下问题 返回给前端的错误信息过多不够明确。浪费系统资源因为不必要的校验操作仍在继续。 2、实现方式 为了解决上述问题可以配置Hibernate Validator以启用快速失败模式failFast。这样当遇到第一个校验失败时就会立即停止后续的校验。以下是几种实现方式 Configuration public class ValidatorConfig {// 第一种BeanConditionalOnMissingBean(Validator.class)public LocalValidatorFactoryBean validator() {LocalValidatorFactoryBean factoryBean new LocalValidatorFactoryBean();factoryBean.getValidationPropertyMap().put(BaseHibernateValidatorConfiguration.FAIL_FAST, Boolean.TRUE.toString());return factoryBean;}// 第二种Beanpublic Validator validator(AutowireCapableBeanFactory springFactory) {try (ValidatorFactory factory Validation.byProvider(HibernateValidator.class).configure()// 快速失败.failFast(true)// 解决 SpringBoot 依赖注入问题.constraintValidatorFactory(new SpringConstraintValidatorFactory(springFactory)).buildValidatorFactory()) {return (Validator) factory.getValidator();}}}1.4 validation实战 1、导入依赖 新建项目导入以下依赖 dependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdcom.github.xiaoymin/groupIdartifactIdswagger-bootstrap-ui/artifactIdversion1.9.6/version/dependencydependencygroupIdio.swagger/groupIdartifactIdswagger-annotations/artifactIdversion1.6.1/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-validation/artifactId/dependency/dependencies2、创建工具类 在项目的根目录下面创建utils包并在此包下面创建全局统一的返回结果对象Results类 /*** 用于返回* param T*/ ApiModel(统一返回类) public class ResultsT {public static final String ERROR 500;public static final String SUCCESS 200;/*** 返回码*/ApiModelProperty(返回码,正确码为200)private String resCode ;/*** 返回消息*/ApiModelProperty(返回消息)private String msg ;/*** 返回实体*/ApiModelProperty(返回实体)private T obj;public static T ResultsT success(){return success(SUCCESS,成功,null);}public static T ResultsT success(String msg){return success(SUCCESS,msg,null);}public static T ResultsT success(T obj){return success(SUCCESS,成功,obj);}public static T ResultsT success(String msg,T obj){return success(SUCCESS,msg,obj);}public static T ResultsT success(String resCode,String msg,T obj){ResultsT result new ResultsT();result.setResCode(resCode);result.setMsg(msg);result.setObj(obj);return result;}public static T ResultsT failed() {return failed(ERROR,失败,null);}public static T ResultsT failed(String msg) {return failed(ERROR,msg,null);}public static T ResultsT failed(String msg,T obj) {return failed(ERROR,msg,obj);}public static T ResultsT failed(String resCode,String msg) {return failed(resCode,msg,null);}public static T ResultsT failed(Integer resCode,String msg) {return failed(String.valueOf(resCode),msg);}public static T ResultsT failed(String resCode,String msg,T obj) {ResultsT result new ResultsT();result.setResCode(resCode);result.setMsg(msg);result.setObj(obj);return result;}public static T ResultsT failedNoPermission() {return failed(90005,没有权限);}public static T ResultsT failedNoPermission(String msg) {return failed(90005,msg);}public static T ResultsT failedParameterException() {return failed(90004,参数异常);}public static T ResultsT failedParameterException(String msg) {return failed(90004,msg);}public static T ResultsT failedLoginException() {return failed(90002,登录失败);}public static T ResultsT failedLoginException(String msg) {return failed(90002,msg);}public String getResCode() {return resCode;}public void setResCode(String resCode) {this.resCode resCode;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg msg;}public T getObj() {return obj;}public void setObj(T obj) {this.obj obj;}Overridepublic String toString() {return Results{ resCode resCode \ , msg msg \ , obj obj };} }3、创建全局异常处理类 在项目的根目录下面创建config包并在此包下面创建全局统一的返回结果对象ExceptionControllerAdvice 类 缺少参数抛出的异常是MissingServletRequestParameterException 单参数校验失败后抛出的异常是ConstraintViolationException get请求的对象参数校验失败后抛出的异常是BindException post请求的对象参数校验失败后抛出的异常是MethodArgumentNotValidException 不同异常对象的结构不同对异常消息的提取方式也就不同。 ConstraintViolationException单个参数校验失败后端实际接收的一个字段 BindException表单对象参数违反约束仅对于表单提交有效接收参数没有加RequestBody注解对于以json格式提交将会失效 MethodArgumentNotValidExceptionJSON请求参数违反约束为json格式有效接收参数加上RequestBody注解 MissingServletRequestParameterException参数缺失 MethodArgumentTypeMismatchException请求参数的类型与处理器方法参数类型不匹配 HttpMessageNotReadableException请求体为空、无效的JSON格式、无法将JSON转换为目标对象 RestControllerAdvice public class ExceptionControllerAdvice {/*** BindException表单对象参数违反约束仅对于表单提交有效接收参数没有加RequestBody注解对于以json格式提交将会失效* MethodArgumentNotValidExceptionJSON请求参数违反约束为json格式有效接收参数加上RequestBody注解* ConstraintViolationException单个参数校验失败后端实际接收的一个字段* param e* return*/ResponseStatus(HttpStatus.OK)ExceptionHandler(value {BindException.class,ConstraintViolationException.class, MethodArgumentNotValidException.class})public Results MethodArgumentNotValidExceptionHandler(Exception e) {// 从异常对象中拿到ObjectError对象BindingResult br null;if (e instanceof MethodArgumentNotValidException) {br ((MethodArgumentNotValidException) e).getBindingResult();} else if (e instanceof BindException) {br ((BindException) e).getBindingResult();} else if (e instanceof ConstraintViolationException) {SetConstraintViolation? violations ((ConstraintViolationException) e).getConstraintViolations();if (CollectionUtils.isEmpty(violations)) {return Results.failed(String.valueOf(500));}MapString, String map violations.stream().collect(Collectors.toMap(o - {PathImpl x (PathImpl) o.getPropertyPath();return x.getLeafNode().toString();}, ConstraintViolation::getMessage, (k1, k2) - k1));return Results.failed(400,map.toString());}if (br.hasFieldErrors()) {ListFieldError fieldErrorList br.getFieldErrors();ListString errors new ArrayList(fieldErrorList.size());for (FieldError error : fieldErrorList) {errors.add(error.getField() : error.getDefaultMessage());}// 然后提取错误提示信息进行返回return Results.failed(400,errors.toString());}// 然后提取错误提示信息进行返回return Results.failed(校验错误);}}4、创建实体类 在项目的根目录下面创建model包并在此包下面创建全局统一的返回结果对象User类 Data public class User {NotNull(message 用户名不能为空)Size(min 5, max 20, message 用户名长度必须在5到20之间)private String username;NotNull(message 姓名不能为空)private String name;NotNull(message 年龄不能为空)Min(value 18, message 年龄必须大于18)private Integer age;Email(message 邮箱格式不对)private String email;NotEmpty(message 爱好不能为空)private ListString hobbies;}5、创建视图层Controller 在项目的根目录下面创建controller包并在此包下面创建全局统一的返回结果对象TestController类 Validated // 单/多个参数校验需要加的注解不加参数校验不生效 RestController public class TestController {// 会进入到MethodArgumentNotValidException异常处理方法PostMapping(/post)public Results post(RequestBody Validated User user) {try {return Results.success(user);} catch (Exception e) {return Results.failed();}}// 多个参数校验需要在controller类上面添加Validated注解(会进入到ConstraintViolationException全局异常方法里面)GetMapping(/getConstraint)public Results getConstraint(NotBlank(message 姓名不能为空) String name, NotNull(message 年龄不能为空)Min(value 18, message 年龄必须大于18) Integer age) {try {return Results.success();} catch (Exception e) {return Results.failed();}}// 会进入到BindException异常处理方法GetMapping(/getBindException)public Results getBindException(Validated User user) {try {return Results.success(user);} catch (Exception e) {return Results.failed();}}// 自定义BindException异常会进入到BindException异常处理方法PostMapping(/testBindException)public Results testBindException(RequestBody Valid User user, BindingResult bindingResult) {try {// 检查验证结果if (bindingResult.hasErrors()) {// 手动抛出BindException触发异常处理throw new BindException(bindingResult);}return Results.success(user);} catch (Exception e) {return Results.failed();}}}6、测试结果 post方法 getConstraint方法 getBindException方法 1.5 分组校验 使用方式(示例说明) 准备工作自定义两个分组。 提示 继承Default并不是必须的。只是说如果继承了Default那么Validated(value Create.class)的校验范畴就 为【Create】和【Default】如果没继承Default那么Validated(value Create.class)的校验范畴只 为【Create】而Validated(value {Create.class, Default.class})的校验范畴才为【Create】和【Default】。 注 Default组和无参构造机制类似当没有指定分组时会默认当前校验属于Default组,但是一旦主动给当前校验指定 了分组(如上图中的name字段主动指定了属于Create组)那么就不会再额外指定属于Default组了。 追注当然也可以画蛇添足的主动指定所属分组为Default。 1、在User类里面添加以下内容 NotBlank(message 密码不能为空,groups {Add.class})private String password;NotNull(message id不能为空,groups {Update.class})private Integer id;public interface Update {}public interface Add extends Default {}2、在controller里面添加以下内容 PostMapping(/addUser)public Results addUser(Validated(User.Add.class) RequestBody User uer) {try {return Results.success();} catch (Exception e) {return Results.failed();}}PostMapping(/updateUser)public Results updateUser(Validated(User.Update.class) RequestBody User user) {try {return Results.success();} catch (Exception e) {return Results.failed();}}3、测试 addUser方法 updateUser方法 1.6 多级嵌套模型的校验 1、在model下面创建用户相关的类 Address 类 Data public class Address {NotBlank(message 城市不能为空,groups {User.Add.class})private String city;NotBlank(message 城市编码不能为空,groups {User.Add.class})private String zipCode; }UserProfile 类 Data public class UserProfile {NotBlank(message 个人简介不能为空,groups {User.Add.class})private String bio;NotBlank(message 头像URL不能为空,groups {User.Add.class})private String avatarUrl;NotBlank(message 社交媒体链接不能为空,groups {User.Add.class})private String linkedinUrl; }2、在User类里面添加以下内容 Validprivate Address address;Validprivate UserProfile userProfile;3、测试 addUser方法 非常感谢以下博主 https://blog.csdn.net/weixin_51262499/article/details/129910551 https://blog.csdn.net/csdnzhang365/article/details/129141189 https://blog.csdn.net/justry_deng/article/details/86571671
http://www.hkea.cn/news/14278043/

相关文章:

  • 学校网站建设分工北京服装设计公司排名前十强
  • 郑州建设网站设计自己做门户网站
  • 大连建站费用seo单页面优化
  • 最专业微网站多少钱宜宾注册公司
  • 中山网站建设开发长沙建站标协助找有为太极
  • 移动商城积分和积分区别唐山seo
  • 制作网站的模板网站属性
  • 网站推广软件ky99网站建设费用大概多少
  • 网站开发维护承担的法律责任什么网站可以做数据图
  • 做视频网站适合用什么服务器宜宾长宁网站建设
  • 自己如何建设个网站首页wordpress中用户注册
  • 白银网站seo一级a做爰片免费网站神马电影
  • 福田祥菱m2怎么样重庆做网站seo优化选哪家好
  • 来个网站吧好人一生平安百度贴吧电商首页设计思路
  • 电商网站建设与运营方向云南省建设工程信息服务平台
  • 商城网站开发业务网站flash引导页下载
  • 网站建设公司客户开发手册网站建设自查自评报告
  • 06628 网页制作与网站开发app推广拉新
  • 的网站制作网站开发的实施方案
  • 怎么注册英文网站域名视网站亏损了为什么还做
  • 廊坊网站制作公司排名网站 模板下载
  • 南京网站建设哪家好新品发布会的流程
  • 西宁市城中区建设局网站网站开发流程有哪几个阶段
  • dwcc网站前台脚本怎么做音频wordpress 手机验证码插件
  • 杭州城市建设网站如何制作网站教程
  • 免费移动网站建设做网站答辩
  • 融资网站建设建设工程网站有哪些
  • 国外采购网站大全建设银行信用卡管理中心网站首页
  • 怎么在中国做网站网站温州网站关键词排名
  • 网站公司怎么找客户阳泉网站建设公司