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 ...
随机推荐
- php 扩展引入
继承引入参数 <?php class A { private $name; private $age; private $time; public function __construct($n ...
- 第三十三篇 玩转数据结构——红黑树(Read Black Tree)
1.. 图解2-3树维持绝对平衡的原理: 2.. 红黑树与2-3树是等价的 3.. 红黑树的特点 简要概括如下: 所有节点非黑即红:根节点为黑:NULL节点为黑:红节点孩子为黑:黑平衡 4.. 实现红 ...
- js中float失精
https://juejin.im/post/5aa1395c6fb9a028df223516 把小数转为整数,然后计算 https://www.html.cn/archives/7340
- 如何做好 Android 端音视频测试?
在用户眼中,优秀的音视频产品应该具有清晰.低延时.流畅.秒开.抗丢包.高音效等特征.为了满足用户以上要求,网易云信的工程师通过自建源站,在SDK端为了适应网络优化进行QoS优化,对视频编码器进行优化, ...
- mysql 父子表 注意事项
今天遇到一个问题,父子表关联查询时总是多出几条数据,后来排查是父子关系的字段 类型不一致导致的
- 迎娶白富美,走上人生巅峰(python爬虫股票分析)
一.姿势储备 股票交易,线性代数(分析股票),分位数(风险评估)... finace.yahoo.com 雅虎提供几乎所有股票api www.kaggle.com 有问题找社区 未完待续.....
- 解决com.netflix.zuul.FilterProcessor : null异常
ZuulFilter过滤器的filterType方法返回一个字符串代表过滤器的类型,如果return null就会出现以上错误. 在zuul中有以下四种不同生命周期的过滤器类型 pre:路由之前 ro ...
- jquery获取select多选框选中的文本值
$("#select option:selected").text();
- ubuntu16.04spyder闪退
解决办法我试了好用 sudo pip install --upgrade html5lib==.0b8 完事.
- 安装VMware Tools和设置屏幕
在虚拟机窗口的虚拟机-安装VMware Tools,点击安装,直到安装完成,出现以下界面 在主文件夹中新建VM文件夹,将VMware Tools中的VMwareTools-10.0.10-430167 ...