前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >小议SpringMvc参数绑定流程

小议SpringMvc参数绑定流程

作者头像
写一点笔记
发布2022-08-11 16:46:09
4630
发布2022-08-11 16:46:09
举报
文章被收录于专栏:程序员备忘录程序员备忘录

在SpringMvc开发过程中,我们通常会用一种注解的参数校验法。因为用起来很方便。所以很受欢迎。今天就扒一扒这个注解异常校验的流程。作者通过不断的debug,终于找到北了。它在dispatchservlet中,总的调度入口如图所示。

最后在InvocableHandlerMethod类中获取传入的参数。

代码语言:javascript
复制
    protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        MethodParameter[] parameters = this.getMethodParameters();
        if (ObjectUtils.isEmpty(parameters)) {
            return EMPTY_ARGS;
        } else {
            Object[] args = new Object[parameters.length];


            for(int i = 0; i < parameters.length; ++i) {
                MethodParameter parameter = parameters[i];
                parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
                args[i] = findProvidedArgument(parameter, providedArgs);
                if (args[i] == null) {
//查看是否有何时的解析器
                    if (!this.resolvers.supportsParameter(parameter)) {
                        throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
                    }
                    try {
//开始解析这个传入的参数
                        args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
                    } catch (Exception var10) {
                        if (logger.isDebugEnabled()) {
                            String exMsg = var10.getMessage();
                            if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
                                logger.debug(formatArgumentError(parameter, exMsg));
                            }
                        }


                        throw var10;
                    }
                }
            }


            return args;
        }
    }

在此类的开头,我们看到这里可以设置很多解析器

代码语言:javascript
复制
代码语言:javascript
复制
public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
    private final ListargumentResolvers =new ArrayList();
    private final Map, HandlerMethodArgumentResolver> argumentResolverCache = new ConcurrentHashMap(256);

    public HandlerMethodArgumentResolverComposite() {
    }
//添加解析器
    public HandlerMethodArgumentResolverComposite addResolver(HandlerMethodArgumentResolver resolver) {
        this.argumentResolvers.add(resolver);
        return this;
    }
//添加解析器
    public HandlerMethodArgumentResolverComposite addResolvers(@Nullable HandlerMethodArgumentResolver... resolvers) {
        if (resolvers != null) {
            Collections.addAll(this.argumentResolvers, resolvers);
        }

        return this;
    }

我们看到这块选出来的是ServletModelAttributeMethodProcessor,然后使用这个解析器进行参数校验。

写了一下午,没保存.....

上边写的这些其实还是没有分析到精髓上,我们大概的了解了一下流程,但是对于像@NotNull等注解的具体解析都没有找到,当然也不知道如何自定义一个注解解析器,并添加到viltaler中。所以上边的分析并不是很好,迷迷糊糊的。但是作者在DispatchServlet中发现了一个异常处理器。其是可以定义多个的,而且会轮询去执行,知道出现一个可以处理该异常的解析器就停止。

作者查看源码,发现在DispatchServlet初始化的时候,从Spring上下文中获取了这些解析器,代码如下图所示。

这块的意思就是说咋通过实现接口HandlerExceptionResolver,然后将其注入到SpringIoc中即可让SpringMvc去执行我们自定义的异常处理机制。也就是全局异常处理,但势必需要让我们自定义的异常处理器执行的比较早。所以我们实践一下。

代码语言:javascript
复制
@Component
public class MyHand implements HandlerExceptionResolver, Ordered {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        System.out.println("12");
        e.printStackTrace();
        System.out.println(o.toString());
        return null;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

我们看一下效果:

最近优点懒,睡得的挺好,一天能睡很久。文章好久都没更了,这是一个坏味道。希望早日回归正常态。

天气很热,注意开空调,节约用电~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 写点笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档