Spring MVC实现自定义参数注解

Spring MVC实现自定义参数注解

如果熟悉SpringMVC原理和相关代码的话,就比较容易实现。关键点就是HandlerMethodArgumentResolver类—>实现请求参数解析

SpringMVC默认提供实现

  1. 常见实现类-类图
    在这里插入图片描述
  2. 常见参数注解说明–更多实现可以查看HandlerMethodArgumentResolver子类
类名支持注解备注说明
PathVariableMapMethodArgumentResolver支持注解@PathVariable能够实现参数转换成Map
RequestParamMapMethodArgumentResolver支持注解@RequestParam能够实现参数转换Map
RequestAttributeMethodArgumentResolver支持注解@RequestAttribute能够获取WebRequest参数转换到Map
RequestHeaderMapMethodArgumentResolver支持注解@RequestHeader能够获取RequestHeader参数转换到Map
  1. 默认添加HandlerMethodArgumentResolver实现类对应的方法–org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getDefaultArgumentResolvers
    注意点:从代码可以参数优先级是通过添加顺序来控制的
	private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
		List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(30);

		// Annotation-based argument resolution
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
		resolvers.add(new RequestParamMapMethodArgumentResolver());
		resolvers.add(new PathVariableMethodArgumentResolver());
		resolvers.add(new PathVariableMapMethodArgumentResolver());
		resolvers.add(new MatrixVariableMethodArgumentResolver());
		resolvers.add(new MatrixVariableMapMethodArgumentResolver());
		resolvers.add(new ServletModelAttributeMethodProcessor(false));
		resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new RequestHeaderMapMethodArgumentResolver());
		resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
		resolvers.add(new SessionAttributeMethodArgumentResolver());
		resolvers.add(new RequestAttributeMethodArgumentResolver());

		// Type-based argument resolution
		resolvers.add(new ServletRequestMethodArgumentResolver());
		resolvers.add(new ServletResponseMethodArgumentResolver());
		resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RedirectAttributesMethodArgumentResolver());
		resolvers.add(new ModelMethodProcessor());
		resolvers.add(new MapMethodProcessor());
		resolvers.add(new ErrorsMethodArgumentResolver());
		resolvers.add(new SessionStatusMethodArgumentResolver());
		resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
		if (KotlinDetector.isKotlinPresent()) {
			resolvers.add(new ContinuationHandlerMethodArgumentResolver());
		}

		// Custom arguments
		if (getCustomArgumentResolvers() != null) {
			resolvers.addAll(getCustomArgumentResolvers());
		}

		// Catch-all
		resolvers.add(new PrincipalMethodArgumentResolver());
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
		resolvers.add(new ServletModelAttributeMethodProcessor(true));

		return resolvers;
	}
  1. 参数属性来源
    1、spring 容器Bean
    2、request 参数
    3、外部化配置属性
    4、servlet 容器参数

实现自定义参数注解步骤

  1. 自定义注解类
import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface MyMvcReqParam {
    String value() default "";
}
  1. 实现HandlerMethodArgumentResolver类,并实现supportsParameter和resolveArgument方法
import org.springframework.core.MethodParameter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.util.Map;

/**
 * 处理@MyMvcReqParam注解
 */
public class MyMvcReqParamMapMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        MyMvcReqParam ann = parameter.getParameterAnnotation(MyMvcReqParam.class);
        return (ann != null && Map.class.isAssignableFrom(parameter.getParameterType()) &&
                !StringUtils.hasText(ann.value()));
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        //将参数转换成map对象
        Map<String, String[]> parameterMap = webRequest.getParameterMap();
        MultiValueMap<String, String> result = new LinkedMultiValueMap<>(parameterMap.size());
        parameterMap.forEach((key, values) -> {
            for (String value : values) {
                result.add(key, value);
            }
        });
        return result;
    }
}
  1. 将实现HandlerMethodArgumentResolver类,添加到SpringMVC对应的RequestMappingHandlerAdapter类中
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
    /**
     * add formatter registry
     *
     * @param registry
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
        registrar.setUseIsoFormat(true);
        registry.addConverter(new StringToDataConverter());
        registrar.registerFormatters(registry);
    }

    /**
     * 添加自定义HandlerMethodArgumentResolver
     * @param resolvers
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new MyMvcReqParamMapMethodArgumentResolver());
        WebMvcConfigurer.super.addArgumentResolvers(resolvers);
    }
}

总结

如果要实现一个简单的自定义注解,只要按照上述步骤进行实现就行,如果要实现比较复杂的实现类,可以参考ModelAttributeMethodProcessor。如果要深入使用,需要对Spring core源码有一定了解,才能更好的利用Spring框架提供的功能进行扩展。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值