欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

RequestMappingHandlerMapping注入的正确姿势

程序员文章站 2022-03-10 21:37:32
文章目录简述基本知识点第一种方式:Controller注入第二种方式:从IOC的ApplicationContext里面获取简述RequestMappingHandlerMapping是springMVC里面的核心Bean,spring把我们的controller解析成RequestMappingInfo对象,然后再注册进RequestMappingHandlerMapping中,这样请求进来以后就可以根据请求地址调用到Controller类里面了。Controller毕竟是写死的,在有的情况下我们可...

简述

RequestMappingHandlerMapping是springMVC里面的核心Bean,spring把我们的controller解析成RequestMappingInfo对象,然后再注册进RequestMappingHandlerMapping中,这样请求进来以后就可以根据请求地址调用到Controller类里面了。
Controller毕竟是写死的,在有的情况下我们可能还需要动态地注册一些API到springMVC的容器中,就需要注入了。但是注入的时候,会发现不一定好使,本文专门做一下解释说明。

基本知识点

  1. RequestMappingHandlerMapping对象本身是spring来管理的,可以通过ApplicationContext取到,所以并不需要我们新建。
  2. 在SpringMVC框架下,会有两个ApplicationContext,一个是Spring IOC的上下文,这个是java web框架的Listener里面配置,就是我们经常用的web.xml里面的org.springframework.web.context.ContextLoaderListener,由它来完成IOC容器的初始化和bean对象的注入。
  3. 另外一个是ApplicationContext是由org.springframework.web.servlet.DispatcherServlet完成的,具体是在org.springframework.web.servlet.FrameworkServlet#initWebApplicationContext()这个方法做的。而这个过程里面会完成RequestMappingHandlerMapping这个对象的初始化。

第一种方式:Controller注入

你直接在Controller按照下述方法写:

    @Autowired
    RequestMappingHandlerMapping requestMappingHandlerMapping;

这样就可以了,很简单,非Controller,Autowired是不行的。

第二种方式:从IOC的ApplicationContext里面获取

这个方式是自己当时发现的,从IOC的applicationContext里面获取。
如果你不想在Controller里面引用的话,就可以考虑这种方式,可以在任何地方使用。
如下所示:

    private RequestMappingHandlerMapping requestMappingHandlerMapping;
    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }
    private RequestMappingHandlerMapping getRequestMappingHandlerMapping(){
        if (this.requestMappingHandlerMapping==null){
            XmlWebApplicationContext xmlApplicationContext=(XmlWebApplicationContext) applicationContext;
            ApplicationContext servletApplicationContext=(ApplicationContext)(xmlApplicationContext.getServletContext().getAttribute(FrameworkServlet.SERVLET_CONTEXT_PREFIX+xmlApplicationContext.getServletConfig().getServletName()));
            this.requestMappingHandlerMapping=servletApplicationContext.getBean(RequestMappingHandlerMapping.class);
        }
        return this.requestMappingHandlerMapping;
    }

里面用到了ApplicationContextAware,这个比较简单。

上面的那个代码看着可能有点长,但是比较简单。
整体来讲就是:
springMVC有一个ApplicationContext,但是他初始化完了以后,就把这个对象塞到了ServletContext的属性里面去了,属性名是:FrameworkServlet.SERVLET_CONTEXT_PREFIX+xmlApplicationContext.getServletConfig().getServletName()。而这个ServletContext可以从SpringIOC的容器里面取出来,所以就可以通过SpringIOC的Context取到SpringMVC的Context,所以就可以取到RequestMappingHandlerMapping。
在不知道这个事情的时候,看了网上的一些文章,就直接用注解自动注入,但是一直报错没有这个bean,最后花了我不少心思找到了这个,亲测可用。

这边稍微有一个问题注意下,就是使用这个方法的时机,一定要在servlet加载完了以后再使用,否则这个对象也是没有的。servlet加载的时候才会初始化这个Context。
如果你希望在启动过程中去动态注册API的话,那么我推荐你使用Controller里面的注解注入,同时使用PostContruct注解;或者重写一下DispatcherServlet这个类的init方法,完成父类的init方法以后,再去执行你的业务逻辑,也肯定没有问题,我是这样干的。

本文地址:https://blog.csdn.net/ywg_1994/article/details/112800703