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 ...
随机推荐
- Oracle存储过程----存储过程执行简单的增删改查
1.存储过程执行增加的sql create or replace procedure test_add(id varchar,name varchar,time varchar,age varchar ...
- 题解【POJ2155】Matrix
Description Given an \(N \times N\) matrix \(A\), whose elements are either \(0\) or \(1\). \(A[i, j ...
- angular6 路由拼接查询参数如 ?id=1 并获取url参数
angular6 路由拼接查询参数如 ?id=1 并获取url参数 路由拼接参数: <div class="category-border" [routerLink]=&qu ...
- MP4文件格式分析及分割实现(附源码)
MP4文件格式分析 MP4(MPEG-4 Part 14)是一种常见的多媒体容器格式,它是在“ISO/IEC 14496-14”标准文件中定义的,属于MPEG-4的 ...
- Rabbitmq启动报错
板卡掉电以后发现rabbitmq服务被停了,重启之: root@firefly:/var/lib/rabbitmq/mnesia# cd /usr/lib/rabbitmq/lib/rabbitmq_ ...
- maven一直加载2.0.0.M7 的 config server 失败
之前学习的时候使用F版的SpringBoot管理项目依赖一直好好的,今天不知idea为何抽疯,一直加载失败,各种重启,清除,没用 只能像之前学习注册consul 时将F版的SpringBoot 改为G ...
- linux nmon安装
系统版本红帽7.7: [root@hostuser1 nmon_permon]# cat /etc/redhat-release CentOS Linux release 7.7.1908 (Core ...
- 机器学习(ML)十五之梯度下降和随机梯度下降
梯度下降和随机梯度下降 梯度下降在深度学习中很少被直接使用,但理解梯度的意义以及沿着梯度反方向更新自变量可能降低目标函数值的原因是学习后续优化算法的基础.随后,将引出随机梯度下降(stochastic ...
- nginx的负载均衡配置
1.下载nginx的压缩包,可以去官网下载 2.解压缩,可以看到其中有个conf的文件夹,在该目录中,nginx.conf配置文件就是核心配置文件 3.默认配置 #user nobody; worke ...
- 关于java中MD5加密(可直接使用)
本文转自:http://www.cnblogs.com/solove/archive/2011/10/18/2216715.html 上部分是转载的关于字符串的加密,后半部分则比较全,包括字符串.文件 ...