小议SpringMvc参数绑定流程

写点笔记

共 3897字,需浏览 8分钟

 ·

2021-06-17 11:06

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

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

        我们看一下效果:

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

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



浏览 21
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报