一、定义参数解析注解
@Target(value = ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface ParameterModel {
}
二、定义抽象类AbstractCustomizeResolver继承HandlerMethodArgumentResolver
public abstract class AbstractCustomizeResolver implements HandlerMethodArgumentResolver {
//校验
protected void valid(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory, Object arg) throws Exception {
String name = Conventions.getVariableNameForParameter(parameter);
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());
}
}
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
}
/**
* Validate the binding target if applicable.
* <p>The default implementation checks for {@code @javax.validation.Valid},
* Spring's {@link Validated},
* and custom annotations whose name starts with "Valid".
* @param binder the DataBinder to be used
* @param parameter the method parameter descriptor
* @since 4.1.5
* @see #isBindExceptionRequired
*/
protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) {
Annotation[] annotations = parameter.getParameterAnnotations();
for (Annotation ann : annotations) {
Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) {
Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(ann));
Object[] validationHints = (hints instanceof Object[] ? (Object[]) hints : new Object[]{hints});
binder.validate(validationHints);
break;
}
}
}
protected boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter parameter) {
int i = parameter.getParameterIndex();
Class<?>[] paramTypes = parameter.getMethod().getParameterTypes();
boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1]));
return !hasBindingResult;
}
}
三、定义UnderlineToCamelArgumentResolver继承AbstractCustomizeResolver
public class UnderlineToCamelArgumentResolver extends AbstractCustomizeResolver {
/**
* Whether the given {@linkplain MethodParameter method parameter} is
* supported by this resolver.
* @param parameter the method parameter to check
* @return {@code true} if this resolver supports the supplied parameter;
* {@code false} otherwise
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(ParameterModel.class);
}
/**
* 装载参数
*
* @param methodParameter 方法参数
* @param modelAndViewContainer 返回视图容器
* @param nativeWebRequest 本次请求对象
* @param webDataBinderFactory 数据绑定工厂
* @return the resolved argument value, or {@code null}
* @throws Exception in case of errors with the preparation of argument values
*/
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
Object org=handleParameterNames(methodParameter, nativeWebRequest);
valid(methodParameter,modelAndViewContainer,nativeWebRequest,webDataBinderFactory,org);
return org;
}
//处理参数
private Object handleParameterNames(MethodParameter parameter, NativeWebRequest webRequest) {
Object obj = BeanUtils.instantiate(parameter.getParameterType());
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(obj);
Iterator<String> paramNames = webRequest.getParameterNames();
while (paramNames.hasNext()) {
String paramName = paramNames.next();
Object o = webRequest.getParameter(paramName);
wrapper.setPropertyValue(StringHelpers.underLineToCamel(paramName), o);
}
return obj;
}
}
4、定义工具类StringHelpers处理驼峰与下划线的互换
public class StringHelpers {
/**
* 匹配_加任意一个字符
*/
private static final Pattern UNDER_LINE_PATTERN = Pattern.compile("_(\\w)");
/***
* 下划线命名转为驼峰命名
*
* @param source
* 下划线命名的字符串
*/
public static String underlineToHump(String source) {
StringBuffer result = new StringBuffer();
String a[] = source.split("_");
for (String s : a) {
if (result.length() == 0) {
result.append(s.toLowerCase());
} else {
result.append(s.substring(0, 1).toUpperCase());
result.append(s.substring(1).toLowerCase());
}
}
return result.toString();
}
/***
* 驼峰命名转为下划线命名
*
* @param source
* 驼峰命名的字符串
*/
public static String humpToUnderline(String source) {
StringBuffer sb = new StringBuffer(source);
int temp = 0;//定位
for (int i = 0; i < source.length(); i++) {
if (Character.isUpperCase(source.charAt(i))) {
sb.insert(i + temp, "_");
temp += 1;
}
}
return sb.toString().toUpperCase();
}
/**
* Create by lrt<br/>
* Date:2018/10/10
* Description: 下划线转为驼峰格式
*
* @param source 原字符串
* @return java.lang.String 返回转换后的驼峰格式字符串
*/
public static String underLineToCamel(String source) {
//用Pattern类的matcher()方法生成一个Matcher对象
Matcher matcher = UNDER_LINE_PATTERN.matcher(source);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(result, matcher.group(1).toUpperCase());
}
matcher.appendTail(result);
return result.toString();
}
}