spring的annotation-driven

argument resolvers


  1.   spring的请求处理都是方法级别,围绕方法上的处理,当你须要针对请求参数作一些特殊的处理,不一样的类型得到不一样的处理。我这边项目有一个需求是在controller里面得到session里面的用户信息,咱们普通采用的方法是直接从session里面获取,须要指定具体的key。从里面得到,若是调用登陆用户的地方不少的时候,处理的逻辑也是至关冗余的。
  2. 这边利用spring的argument resolvers(参数解析),针对自定义注解来注入用户到方法级别。

     先定义注解: java


@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UserAttribute {
}



里面能够扩展你须要对用户处理的逻辑。


在是实现spring的HandlerMethodArgumentResolver --这个接口是操做处理方法的参数处理。 web

spring在处理请求参数时,针对不一样注解或者不一样类型例如HttpRequest,HttpResponse的值的赋值。默认都是有一个组合的处理器,注册一些默认的处理方式,我下面把注册的地方添加进来。 spring

在RequestMappingHandlerAdapter类里面的afterPropertiesSet方法里面。 session

public void afterPropertiesSet() {
		// Do this first, it may add ResponseBody advice beans
		initControllerAdviceCache();
                //请求参数初始的解析器
             if (this.argumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
			this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
                //初始绑定参数的解析器
		if (this.initBinderArgumentResolvers == null) {
			List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
			this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
		}
                //初始方法返回值的包装器
		if (this.returnValueHandlers == null) {
			List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
			this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
		}
	}


每个都有一个默认配置,如下是请求参数的默认解析器。 app

private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
		List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();

		// Annotation-based argument resolution
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false)); --@requestParam注解
		resolvers.add(new RequestParamMapMethodArgumentResolver());
		resolvers.add(new PathVariableMethodArgumentResolver());--@pathVariable注解
		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()));

		// 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());

		// Custom arguments
                // 添加自定义解析器
		if (getCustomArgumentResolvers() != null) {
			resolvers.addAll(getCustomArgumentResolvers());
		}

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

		return resolvers;
	}



感兴趣的话能够这些请求参数的解析方式都看一下,了解一下每个种类型的解析方式。


回归正题,咱们如今集成接口后须要实现两个方法。 ui

supportsParameter 和 resolveArgument,默认自定义的解析器是在最后面。判断supportsParameter支持是否为true,若是为true就走下面resolveArgument方法, this

里面返回值就是你须要处理的对象,须要封装你本身的处理逻辑针对注解。 spa

public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        HttpSession session = request.getSession();

        UserInfo user = (UserInfo)session.getAttribute(Constant.USER_INFO_SESSION);

        return user;
    }



这样就能经过注解在方法上获取到登陆的用户信息。

return-value-handlers的处理方式在spring里面仍是有一点不同。下面会介绍。 code

相关文章
相关标签/搜索