spring的annotation-driven_weixin_34080903的博客-程序员秘密

argument resolvers


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

     先定义注解:


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



里面可以扩展你需要对用户处理的逻辑。


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

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

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

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


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

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

		// Annotation-based argument resolution
		resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false)); [email protected]注解
		resolvers.add(new RequestParamMapMethodArgumentResolver());
		resolvers.add(new PathVariableMethodArgumentResolver());[email protected]注解
		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;
	}



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


回归正题,我们现在集成接口后需要实现两个方法。

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

里面返回值就是你需要处理的对象,需要封装你自己的处理逻辑针对注解。

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里面还是有一点不一样。下面会介绍。

转载于:https://my.oschina.net/zooy/blog/672452

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34080903/article/details/91633559

智能推荐

YApi结合swag管理和生成go项目restful API文档_米兰的小铁匠1943的博客-程序员秘密

swag通常用来生成go项目的API文档,但是管理功能较弱,多个项目的文档需要做统一管理。YApi是一个强大的接口管理工具,两者结合可以让开发人员减轻维护api文档的负担

vs2019MFC对话框怎样添加数据_vs组合框怎么添加内容_是小艾呀~的博客-程序员秘密

方法一: 找到编辑框,右键属性正在上传…重新上传取消找到数据,在里面添加内容即可 注意:如果数据想换行,在vc里是crtl+enter来进行换行。 但是在vs中进行换行是用;(分号而且必须是英文分号)方法二:正在上传…重新上传取消m_Combox1.AddString("河北省石家庄市"); m_Combox1.AddString("河北省保定市"); m_Combox1.AddString("河北省张家口市"); m_Combox1.AddString("河北省邢台市".

SpringBoot1 和Spring Boot 2差别_springboot1和2的区别_我知道你是高手的博客-程序员秘密

转载自:https://blog.csdn.net/xiandafu/article/details/78474491 有差别,但差别不大。基本上基于SpringBoot的代码不需要改动,但有些配置属性和配置类,可能要改动,改动原因是配置已经不存在或者改名类已经不存在改名听着挺吓人,但我实际切换过程中改动的地方很少。一般正常的MVC,数据库访问这些都不需要改动,下面按照本书章节说明我...

7-3-树的同构-编程题_请你返回这两颗最大同构子树的个数求最大同构自树个数_西阿西瓜瓜小花的博客-程序员秘密

7-3-树的同构-编程题解题代码测试结果问题整理解题代码#include&lt;stdio.h&gt;#include&lt;stdlib.h&gt;typedef enum{false,true} bool;typedef struct TNode* Tree;struct TNode { char Data; int Left; int Right;};Tree newT...

APP启动异常崩溃--pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug_Hanrovey的博客-程序员秘密

一、问题场景APP启动异常崩溃 BlockChainStep(1332,0x7000057ad000) malloc: * error for object 0x600000008300: pointer being freed was not allocated * set a breakpoint in malloc_error_break to debug二、...

随便推点

cocos-creator使用记录7_前后台切换_cocos 切换到后台_爱睡觉的猫L的博客-程序员秘密

1.cocos creator前后台切换当玩家在玩游戏时,突然接了一个电话,此时游戏会被切到后台待机,所有的声音播放都会停止,等打完电话,回到游戏,游戏又会被切回前台来,需要手动播放声音。可使用如下代码onLoad: function () { cc.game.on(cc.game.EVENT_HIDE, function(){ console.log(&quot;游戏进入后台&quot;); this.doSo...

如何将计算机网络设置为家庭网络连接打印机共享,怎样设置家庭网络打印机共享..._提提虎的新衣的博客-程序员秘密

家里只有一台打印机,其它电脑想打印文档就得先把文件发送到那一台上,操作麻烦又浪费时间。如果两台电脑都安装了Win7系统,我们可以使用家庭网络打印机共享来解决这个问题,只要在Win7上创建一个家族组,让家中其它Win7电脑都加入到这个组,就可以实现打印机共享了。设置家庭网络打印机共享步骤图解:在连接了打印机的Win7电脑单击“开始”按钮,打开“控制面板”。在搜索框中输入“家庭”就可以找到“家庭组”选...

HTTP Authorization_sauzny的博客-程序员秘密

谨以此文献给那些需要实现HTTP AUTH的“程序猿”们。关于HTTP AUTH的文档不多。RFC在 http://www.ietf.org/rfc/rfc2617.txtwiki在 http://en.wikipedia.org/wiki/Basic_access_authentication使用HTTP AUTH需要在server端配置http auth信息(一般是webse...

oracle的sqlnet.ora、tnsnames.ora、listener.ora的常规配置_li_shihao的博客-程序员秘密

文件一:sqlnet.ora 定义数据库连接时连接字符串的寻找方式,一般不用手动配置,默认就好,如 # sqlnet.ora Network Configuration File: E:\az\oracle\product\10.2.0\db_1\network\admin\sqlnet.ora# Generated by Oracle configuration tools....

GMM高斯混合模型学习笔记(EM算法求解)_giqem算法模型_July_Zh1的博客-程序员秘密

提出混合模型主要是为了能更好地近似一些较复杂的样本分布,通过不断增加component个数,可以任意地逼近任何连续的概率分布,所以我们认为任何样本分布都可以用混合模型来建模。因为高斯函数具有一些很实用的性质,所以高斯混合模型被广泛地使用。     GMM与kmeans类似,也是属于clustering,不同的是,kmeans是把每个样本点聚到其中一个cluster,而GMM是给出这些样本点到每个c