小议SpringMvc参数绑定流程

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

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

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

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

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去执行我们自定义的异常处理机制。也就是全局异常处理,但势必需要让我们自定义的异常处理器执行的比较早。所以我们实践一下。

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

        我们看一下效果:

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值