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 MapgetParametersStartingWith(ServletRequest request, @Nullable String prefix) { Assert.notNull(request, "Request must not be null"); Enumeration paramNames = request.getParameterNames(); Map 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){ 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 ){ 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 ){ 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); } } } } } }