发表于: 2025-05-24 19:59:48

0 48


今天完成的事情:学习深度思考。

2.什么是参数校验,前端和后端需要分别做校验吗?Validation的好处和坏处分别是什么,在真实项目中需要使用Validation吗?

1. 背景介绍:


    参数验证是一个常见的问题,无论是前端还是后台,都需对用户输入进行验证,以此来保证系统数据的正确性。

    对于web来说,有些人可能理所当然的想在前端验证就行了,但这样是非常错误的做法,前端代码对于用户来说是透明的,

    稍微有点技术的人就可以绕过这个验证,直接提交数据到后台。参数验证随处可见,也是必不可少的。

    前端做验证只是为了用户体验,后端才是最终的保障。

   (1) 常见的参数检验方式:

    a、表现层验证:SpringMVC提供对JSR-303的表现层验证,或者直接将拿到的参数在controller层里面用if判断

    b、业务逻辑层验证:Spring3.1提供对业务逻辑层的方法验证

    c、DAO层验证:Hibernate提供DAO层的模型数据的验证

    d、数据库端的验证:通过数据库约束来进行 


    原理都是基于javax validation,有特殊需求的话,可以自定义校验

 (2) JSR 303

    JSR 303(Java Specification Requests 规范提案)是JAVA EE 6中的一项子规范,

    一套JavaBean参数校验的标准,叫做Bean Validation。

    JSR 303用于对Java Bean中的字段的值进行验证,Spring MVC 3.x之后之中也大力支持 JSR303


    JSR303提供的校验注解---------可以注解在javabean的field和properties上,也可以注解在map、list上,注解很灵活

    @Null 被注释的元素必须为 null

    @NotNull 被注释的元素必须不为 null

    @AssertTrue 被注释的元素必须为 true

    @AssertFalse 被注释的元素必须为 false 

    @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 

    @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值

    @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值

    @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值

    @Size(max=, min=) 被注释的元素的大小必须在指定的范围内

    @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内

    @Past 被注释的元素必须是一个过去的日期 

    @Future 被注释的元素必须是一个将来的日期

    @Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式

    

    (3) Hibernate Validator

    Hibernate Validator是JSR-303的一个参考实现,它除了支持所有标准的校验注解外,还支持如下扩展注解

    @Email 被注解的元素必须是电子邮箱地址

    @Length(min=,max=) 被注解的字符串的大小必须在指定的范围内

    @NotBlank 验证字符串非null,且长度必须大于0

    @NotEmpty 被注释的字符串的必须非空 

    @Range(min=,max=)  被注解的元素必须在合适的范围内


    (4) Spring校验框架

    Spring的org.springframework.validation是校验框架所在的包。LocalValidatorFactoryBean既实现了

    Spring的Validator接口,又实现了JSR-303的Validator接口。只要在Spring容器中定义一个LocalValidatorFactoryBean

    即可将其注入需要数据校验的Bean中。


3. 常见问题:


    (1) SpringValidation和javax validation的区别

    JSR303是一项标准,他们规定一些校验规范即校验注解,位于javax.validation.constraints包下,.只提供规范不提供实现

    Hibernate validation,他提供了相应的实现,并增加了一些其他校验注解

    spring validation其在springmvc模块中添加了自动校验,并将校验信息封装进了特定的类中


    (2) 参数校验的基本使用

    多个属性的校验

    在日志或者控制台输出校验的信息

    部分注解仅能用于部分数据类型

    如@notblank注解仅用于字符串,使用时需注意


    (3) 自定义消息错误消息

    Spring中定义了一个MessageSource接口,以用于支持信息的国际化和包含参数的信息的替换。

    ApplicationContext接口继承了MessageSource接口,

    所以所有的ApplicationContext实现类都实现了MessageSource接口。

    也就是我们我们可以通过ApplicationContext来调用MessageSource接口方法以实现信息的国际化和替换信息中包含的参      数。

    

<mvc:annotation-driven validator="validator" />

<bean id="validator"     class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" >

   <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />

   <!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties -->

   <property name="validationMessageSource" ref="messageSource" />

</bean>


<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">

   <property name="basenames" value="classpath:messages" />

   <property name="defaultEncoding" value="UTF-8"/>

   <property name="cacheSeconds" value="60"/>

</bean>

 (1)分组校验

    分组简单说: 解决实体中每个属性都是设置了参数检验,但是在某个方法内只想检验部分属性任务,也可以叫分类,

    采用接口的方式来标识,可以类比java集合中的序列化接口 (Serializable)


     比如说有 用户名,密码,手机号,邮箱,年龄,性别,我想要检验其中的任意2个属性(假设为手机号,年龄),

      当然可以直接加入对应的注解,如果换成手机号和密码,肯定又要写2个注解,

     当字段过多,并且使用场景频繁时,分组是个不错的选择


     假设有2个分组 interface Group1,interface Group2 

     @NotNull(message = "姓名不能为空",groups = {Group1.class})

     private String name;

     指定分组后,使用@Validated(Group1.class) Student student,只检验指定分组


    (2)自定义校验

  

         这个不建议进行,现有的检验类型基本够,如果有更多要求,建议使用逻辑判断,这样更清晰,记录日志方便,出现问题可以及时排查。

3.SpringMVC分页查询和显示

SpringMVC分页查询背景:

当线上研发代码编写不规范,使用mybatis编写sql语句时使用万能匹配查询语句:where 1 = 1 之后,如果拼接的if条件都不符合条件,就会出现sql语句查全表的情况,在这种情况下就会导致数据过多,塞满内存,不断GC(垃圾收集),导致整个服务宕掉。

解决办法:

第一种:使用分页查询,引用Limit,限制查询出的数据条数

服务器性能、资源:如果数据量过大时,使用分页查询后,可以避免一次查询全表数据过多,硬生生把内存塞满,不断GC,整个服务宕掉的情况。用户体验:分页查询可以使页面显示更加美观整洁。

第二种:使用<choose></choose>固定查询范围

一、概述:

1.物理分页

物理分页依赖的是某一物理实体,这个物理实体就是数据库,比如MySQL数据库提供了limit关键字,程序员只需要编写带有limit关键字的SQL语句,数据库返回的就是分页结果。

2.逻辑分页

逻辑分页依赖的是程序员编写的代码。数据库返回的不是分页结果,而是全部数据,然后再由程序员通过代码获取分页数据,常用的操作是一次性从数据库中查询出全部数据并存储到List集合中,因为List集合有序,再根据索引获取指定范围的数据。

limit的语法select * from table where ... limit start,size; </p>

start:从第几条记录开始。

size : 读取几条记录。

首先需要知道,从第几条[下标]开始读,要往后读取多少条。

即分页显示的话,需要传给sql语句两个参数,某一页面中第一条在表中的下标,以及页面中数据的条数。

size:默认指定一个,或者从前台输入后取一个。

start下标:前端传过来要跳转到的页码,后台sql中加入(pageNum-1)*size的计算,即为对应页面的start下标值。

另一种方式是一种方式是,前端js计算完,直接传值过来。不涉及sql语句的计算。




4.“内网IP+端口”和“外网IP+端口”和"域名"三种方式方式的差别是什么?什么时候用内网?什么时候用外网IP,什么时候用域名访问?

1.虚拟服务器设置(端口映射)里的内部端口是指内部服务器的应用所使用的端口,外部端口是指外网访问该映射的服务器应用所使用的端口。

2.例如,内网架设了一台web服务器,默认端口为80(自己也可以更改默认端口为其他),这个80就是内部端口。外网访问如果使用默认的80端口,就可以在虚拟服务器(端口映射)的外部端口栏起始和结束均填写80。若想使用8888端口来访问(有些地区运营商会屏蔽80端口,就需要更改外部端口设置),外部端口栏则填写8888。web访问时地址后需要加 :8888 来访问。

3.而外网端口是Internet用户访问服务器的端口。当访问数据到WAN口时,路由器会将访问请求数据的外部端口替换为内部端口,然后转发给内部服务器,这样服务器就可以正常接收访问。外部端口主要目的就是降低外网对常用端口的扫描攻击、运营商限制等。


明天的计划:继续深度思考学习。


返回列表 返回列表
评论

    分享到