spring boot 自定义参数解析器实现form表单类型请求或地址栏请求参数下划线转驼峰属性

殳宸
2023-12-01

一、定义参数解析注解

@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();
	}
}

 

 类似资料: