spring 参数校验
1.了解下资源文件加载
MessageSource 需要国际化处理时使用这个类 (在需要处理国际化的地方使用messageSource.getMessage(this.getResponseCode(),this.getArgs(),"", locale))
ResourceBundleMessageSource 不能定时刷新资源文件
ReloadableResourceBundleMessageSource 可以定时刷新资源文件
PropertyPlaceholderConfigurer 应用程序内部占位符替换(将占位符替换为具体的值)
2.spring BeanPropertyBindingResult 的用法,
HelloParams params=new HelloParams();
Errors errors=new BeanPropertyBindingResult(params,HelloParams.class.getName());
errors.rejectValue("clientId", "NOTNULL", null);
System.out.println(errors);
3.了解一下springmvc处理流程
dispatcherServlet--->
handlerMappings-->根据request---》HandlerExecutionChain (包括了拦截器和 handler)
[org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@1effc30a,
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping@1a544088,
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@463d761b,
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping@19b6e142,
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@793186ed,
org.springframework.boot.autoconfigure.web.servlet.WelcomePageHandlerMapping@41d9c943]
---》根据handler 获取对应的handlerAdapter-->
[org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter@150afe2,
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter@6cf9e2cd,
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter@426bb2e1]
--->handlerAdapter调用handler处理request
--->handler 调用 HandlerMethodArgumentResolver
[org.springframework.web.method.annotation.RequestParamMethodArgumentResolver@5acedd4b,
org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver@4c91253d,
org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver@76da1b10,
org.springframework.web.servlet.mvc.method.annotation.PathVariableMapMethodArgumentResolver@24bc9d2a,
org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMethodArgumentResolver@8342873,
org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMapMethodArgumentResolver@4d495c85,
org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor@6beddca7,
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor@4412d4dd,
org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver@2bf8493d,
org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver@2268b81,
org.springframework.web.method.annotation.RequestHeaderMapMethodArgumentResolver@50c4234,
org.springframework.web.servlet.mvc.method.annotation.ServletCookieValueMethodArgumentResolver@1aed6,
org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver@6959be4a,
org.springframework.web.servlet.mvc.method.annotation.SessionAttributeMethodArgumentResolver@5f955a63,
org.springframework.web.servlet.mvc.method.annotation.RequestAttributeMethodArgumentResolver@38efae47,
org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver@3595c092,
org.springframework.web.servlet.mvc.method.annotation.ServletResponseMethodArgumentResolver@111a8384,
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor@64a98586,
org.springframework.web.servlet.mvc.method.annotation.RedirectAttributesMethodArgumentResolver@217192c2,
org.springframework.web.method.annotation.ModelMethodProcessor@3a7b472e,
org.springframework.web.method.annotation.MapMethodProcessor@7fb8e546,
org.springframework.web.method.annotation.ErrorsMethodArgumentResolver@5795ca82,
org.springframework.web.method.annotation.SessionStatusMethodArgumentResolver@7a5fa530,
org.springframework.web.servlet.mvc.method.annotation.UriComponentsBuilderMethodArgumentResolver@1afddf62,
org.springframework.web.method.annotation.RequestParamMethodArgumentResolver@22578bae,
org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor@5b6f84bc]
--->HttpMessageConverter
普通的读取form里的参数
ServletModelAttributeMethodProcessor
没有convert
有@requestbody
RequestResponseBodyMethodProcessor
[org.springframework.http.converter.ByteArrayHttpMessageConverter@3d37203b,
org.springframework.http.converter.StringHttpMessageConverter@45bb2aa1,
org.springframework.http.converter.StringHttpMessageConverter@7fd26ad8,
org.springframework.http.converter.ResourceHttpMessageConverter@1894593a,
org.springframework.http.converter.ResourceRegionHttpMessageConverter@14b0e127,
org.springframework.http.converter.xml.SourceHttpMessageConverter@10823d72,
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter@7cea0110,
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@3e84111a,
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@468dda3e,
org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter@5527b211]
一、HandlerMethodArgumentResolver
RequestResponseBodyMethodProcessor
bject arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
String name = Conventions.getVariableNameForParameter(parameter); if (binderFactory != null) {
WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
if (arg != null) {
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
}
}
if (mavContainer != null) {
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
}
}
ServletModelAttributeMethodProcessor
//主要操作,绑定参数和校验参数
bindRequestParameters(binder, webRequest);
}
validateIfApplicable(binder, parameter);
读取form里的参数
public static Map<String, Object> getParametersStartingWith(ServletRequest request, @Nullable String prefix) {
Assert.notNull(request, "Request must not be null");
Enumeration<String> paramNames = request.getParameterNames();
Map<String, Object> params = new TreeMap<>();
if (prefix == null) {
prefix = "";
}
while (paramNames != null && paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
if ("".equals(prefix) || paramName.startsWith(prefix)) {
String unprefixed = paramName.substring(prefix.length());
String[] values = request.getParameterValues(paramName);
if (values == null || values.length == 0) {
// Do nothing, no values found at all.
}
else if (values.length > 1) {
params.put(unprefixed, values);
}
else {
params.put(unprefixed, values[0]);
}
}
}
return params;
}
二 、HandlerMethodReturnValueHandler
RequestResponseBodyMethodProcessor
三、介绍HttpMessageConverter
@requestbody 和 @responsebody
Jaxb2RootElementHttpMessageConverter
@requestbody 和 @responsebody 加上的同时,要在类上加@XmlRootElement 同时使用application/xml contentType和accept
MappingJackson2HttpMessageConverter
//hibernate 使用那些文件的国际化配置
1.使用jsr303对应的国际化文件 default "ValidationMessages.properties"
Validation.byDefaultProvider().configure()
.getDefaultMessageInterpolator()
2.使用spring对应的国际化文件
public void setValidationMessageSource(MessageSource messageSource) {
this.messageInterpolator = HibernateValidatorDelegate.buildMessageInterpolator(messageSource);
}
//获取local
@Override
public String interpolate(String message, Context context) {
return this.targetInterpolator.interpolate(message, context, LocaleContextHolder.getLocale());
}
3.使用校验注解标注在属性上(dto)
4.使用方法
参照: https://www.cnblogs.com/mr-yang-localhost/p/7812038.html
@GroupSequence也可以定义在po类上,定义找个类那些组先执行,那些组后执行。
5.自定义校验:
1.解析对象,缓存对线的校验对象
public void checkConfigLoaded(Class<?> dtoClass){
Boolean isloaded=annotationFlag.get(dtoClass);
if(isloaded==null){
synchronized(annotationFlag){
checkAnotation(dtoClass);
checkClazzAnotation(dtoClass);
annotationFlag.put(dtoClass, Boolean.TRUE);
}
}
}
2.根据类初始化它的校验对象
VNumber vn=ReflectUtils.getAnnotation(pd,VNumber.class);
if(vn!=null){
this.addValidator(new NumberValidator(vn),dtoClass,pd.getName());
}
VLength vl=ReflectUtils.getAnnotation(pd,VLength.class);
if(vl!=null){
this.addValidator(new LengthValidator(vl),dtoClass,pd.getName());
}
VRegex vr=ReflectUtils.getAnnotation(pd,VRegex.class);
if(vr!=null){
this.addValidator(new RegexValidator(vr),dtoClass,pd.getName());
}
3.执行过程中
1.当前对象循环,2.子对象循环,3.校验过滤器覆盖
public void _validate(Object dto,String parentPath,int idx) throws Throwable{ PropertyDescriptor[] pds=Introspector.getBeanInfo(dto.getClass()).getPropertyDescriptors();
String realParentPath=parentPath;
if(idx>-1 && parentPath!=null){
realParentPath=(parentPath+"["+idx+"]");
}
ValidateContext context=new DefaultValidateContext(this.bean,realParentPath,dto,errors);
//
ConfigLoader configLoader=validateSupport.getConfigLoader();
configLoader.checkConfigLoaded(dto.getClass());
//----------------------------
for(int i=0;i<pds.length;i++){
PropertyDescriptor pd=pds[i];
if(pd.getReadMethod()==null)continue;
Object value=pd.getReadMethod().invoke(dto);
//---------------------------------------------------------------------
//根据参数名取得验证器集合
String realPath=null;
String idxPath=(parentPath==null?pd.getName():(parentPath+"."+pd.getName()));;
if(idx>-1 && realParentPath!=null){
realPath=realParentPath+"."+pd.getName();
}else{
realPath=idxPath;
}
boolean isArray=pd.getPropertyType().isArray();
int isBaseArray=0;//0未知,1是,2否
if(isArray){
if(isBaseType(pd.getPropertyType().getComponentType())){
isBaseArray=1;
}else{
isBaseArray=2;
}
}
ValidatorsSet validators=null;
//--------------------------------------------------------------------
ValidatorsSet temp=configLoader.getValidators(dto.getClass(),pd.getName());
if(temp!=null){//如果未绑定任何验证器
if(validators==null){
validators=new ValidatorsSet();
}
validators.addAll(temp);
} if(pathValidators!=null && idx>-1 && parentPath!=null){
temp=pathValidators.get(idxPath);
if(temp!=null){
if(validators==null){
validators=new ValidatorsSet();
}
validators.addAll(temp);
}
}else if(pathValidators!=null){
temp=pathValidators.get(realPath);
if(temp!=null){
if(validators==null){
validators=new FieldValidators();
}
validators.addAll(temp);
}
}
if(isArray && isBaseArray==1){
if(validators !=null){
if(value==null){
validators.validate(context,pd,null,realPath,log);
}else{
int arrLen=Array.getLength(value);
if(arrLen==0){
validators.validate(context,pd,null,realPath,log);
}else{
for(int m=0;m<arrLen;m++){
Object arrItem=Array.get(value,m);
if(arrItem!=null ){
validators.validate(context,pd,arrItem,realPath+"["+m+"]",log);
}
}
}
}
}
}else{
if(validators!=null){
//进行验证
validators.validate(context,pd,value,realPath,log);
}
}
//---------------------------------------------------------------------
if(value!=null){
if(validateSupport.supports(pd.getPropertyType())){
_validate(value,idxPath,-1);
}
else if(isArray && isBaseArray==2){
int arrLen=Array.getLength(value);
for(int m=0;m<arrLen;m++){
Object arrItem=Array.get(value,m);
if(arrItem!=null ){
if(validateSupport.supports(arrItem.getClass())){
_validate(arrItem,idxPath,m);
}
}
}
}else if(value instanceof Collection){
Collection<?> list=(Collection<?>)value;
int tempInt=-1;
for(Object obj:list){
tempInt++;
if(obj!=null && validateSupport.supports(obj.getClass())){
_validate(obj,idxPath,tempInt);
} }
}else if(value instanceof Map){
Map<?,?> map=(Map<?,?>)value;
Set<?> list=map.entrySet();
for(Object entryObj:list){
Map.Entry<?,?> entry=(Map.Entry<?,?>)entryObj;
Object vv=entry.getValue();
if(vv!=null && validateSupport.supports(vv.getClass())){
_validate(vv,idxPath+"."+entry.getKey(),-1);
}
}
}
}
}
}
spring 参数校验的更多相关文章
- Spring Boot 参数校验
1.背景介绍 开发过程中,后台的参数校验是必不可少的,所以经常会看到类似下面这样的代码 这样写并没有什么错,还挺工整的,只是看起来不是很优雅而已. 接下来,用Validation来改写这段 2.Spr ...
- Spring基础系列-参数校验
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9953744.html Spring中使用参数校验 概述 JSR 303中提出了Bea ...
- spring注解式参数校验
很痛苦遇到大量的参数进行校验,在业务中还要抛出异常或者返回异常时的校验信息,在代码中相当冗长,今天我们就来学习spring注解式参数校验. 其实就是:hibernate的validator. 开始啦. ...
- Spring Boot参数校验
1. 概述 作为接口服务提供方,非常有必要在项目中加入参数校验,比如字段非空,字段长度限制,邮箱格式验证等等,数据校验常用到概念:JSR303/JSR-349: JSR303是一项标准,只提供规范不提 ...
- Spring Boot 2.x基础教程:JSR-303实现请求参数校验
请求参数的校验是很多新手开发非常容易犯错,或存在较多改进点的常见场景.比较常见的问题主要表现在以下几个方面: 仅依靠前端框架解决参数校验,缺失服务端的校验.这种情况常见于需要同时开发前后端的时候,虽然 ...
- 如何在 Spring/Spring Boot 中做参数校验?你需要了解的都在这里!
本文为作者原创,如需转载请在文首著名地址,公众号转载请申请开白. springboot-guide : 适合新手入门以及有经验的开发人员查阅的 Spring Boot 教程(业余时间维护中,欢迎一起维 ...
- Spring Boot 之:接口参数校验
Spring Boot 之:接口参数校验,学习资料 网址 SpringBoot(八) JSR-303 数据验证(写的比较好) https://qq343509740.gitee.io/2018/07/ ...
- 如何在 Spring/Spring Boot 中做参数校验
数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据. 本文结合自己在项目 ...
- spring 接口校验参数(自定义注解)
1. 注解类 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.l ...
随机推荐
- Java-POJ1004-Financial Management
题目大意:求出一年十二个月Larry平均每个月得到的利息 读入:12行每行一个浮点数 关于控制浮点数输出位数的资料:https://blog.csdn.net/hsliwei/article/deta ...
- rocketmq4.4配置日志路径等级
公司使用了最新的rocketmq框架,然后2天日志跑了快2个g.... 无奈网上只有4.2的教程...只好自己研究 环境rocketmq4.4 springboot 看源码找到配置日志等级和路径的地方 ...
- HTML学习(16)颜色
HTML 颜色由红色.绿色.蓝色混合而成. 颜色值 HTML 颜色由一个十六进制符号来定义,这个符号由红色.绿色和蓝色的值组成(RGB). 每种颜色的最小值是0(十六进制:#00).最大值是255(十 ...
- Vue实例 动态组件实现选项卡
动态组件 选项卡 有n种实现方法 哈哈哈哈 <style> #app{ width: 260px; height: 200px; background: #fff; box-shadow: ...
- pyppeteer硬钢掉淘宝登入的滑块验证
完整代码我也不好公布,我可以给你们思路,以及部分代码动动脑子看看文档应该也能搞定 一.初始化Chromium浏览器相关属性 browser = await pyppeteer.launch({'hea ...
- java把带小数点的字符串转换成int类型
String number ="1.0000"; int num =Double.valueOf(number).intValue();//转换为Int类型
- GitHub网页版基本操作
创建存储库 登录GitHub进入主页,点击头像左边的加号,创建存储库 填写存储库名称.描述,根据需求设置其他选项.点击“Create repository”按钮 创建分支 打开之前创建好的存储库,点击 ...
- tf.train.examle函数
在自定义数据集中: example = tf.train.Example(features=tf.train.Features(feature={ 'img_raw': tf.train.Featur ...
- Kubernetes 与 Helm:使用同一个 Chart 部署多个应用
k8s 集群搭建好了,准备将 docker swarm 上的应用都迁移到 k8s 上,但需要一个一个应用写 yaml 配置文件,不仅要编写 deployment.yaml 还要编写 service.y ...
- 使用git上传项目解决码云文件次数上传限制(原文)
起因:个人免费版的码云上传文件时限制: 1个小时内只能上传20个文件 解决方法:在码云创建空的项目仓库,使用git客户端下载码云的项目,把需要上传的文件复制到该项目中去,用git提交! 1.配置git ...