springboot 注册自己的servlet

在springboot中可以注册自己的servlet,通过ServletRegistrationBean这个类即可,也就是我们创建一个ServletRegistrationBean对象并加入spring的上下文即可注册一个servlet了。

所以有必要分析下ServletRegistrationBean

图片.png

有上图可见,它实现了ServletContextInitializer,所以在tomcat的StandardContext的start方法被调用时,他的onStartup方法会被调用

@Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        Assert.notNull(this.servlet, "Servlet must not be null");
        String name = getServletName();
        if (!isEnabled()) {
            logger.info("Servlet " + name + " was not registered (disabled)");
            return;
        }
        logger.info("Mapping servlet: '" + name + "' to " + this.urlMappings);
        Dynamic added = servletContext.addServlet(name, this.servlet);
        if (added == null) {
            logger.info("Servlet " + name + " was not registered "
                    + "(possibly already registered?)");
            return;
        }
        configure(added);
    }


getServletName获取通过ServletRegistrationBean的setName方法设置的name,在addServlet中会设置为一个servlet的name,如果不配就是bean name

ServletRegistration.Dynamic addServlet(String servletName, String servletClass,
            Servlet servlet, Map<String,String> initParams) throws IllegalStateException {

......

        Wrapper wrapper = (Wrapper) context.findChild(servletName);

        // Assume a 'complete' ServletRegistration is one that has a class and
        // a name
        if (wrapper == null) {
            wrapper = context.createWrapper();
            wrapper.setName(servletName);
            context.addChild(wrapper);

.....

} else {
            wrapper.setServletClass(servlet.getClass().getName());
            wrapper.setServlet(servlet);

}

可以看到,这里把名为servletName的servlet包装成了tomcat中的wrapper container,然后放到了standardcontext中 ,之所以要这个name就是为了区分不同的servlet,因为有可能用户使用同一个servlet类,用不同的名字来区分对应到相应的urlmapping。

    protected void configure(ServletRegistration.Dynamic registration) {
        super.configure(registration);
......
        if (!ObjectUtils.isEmpty(urlMapping)) {
            registration.addMapping(urlMapping);
        }
....
    }

然后在configure方法中把urlMapping也放到了wrapper中。


再来说下springboot对应springmvc的dispatcherservlet的自动配置DispatcherServletAutoConfiguration类中的

@Configuration
    @Conditional(DefaultDispatcherServletCondition.class)
    @ConditionalOnClass(ServletRegistration.class)
    protected static class DispatcherServletConfiguration

DefaultDispatcherServletCondition这个类是判断spring上下文中是否有名叫dispatcherServlet 类型为dispatcherServlet.class的bean,如果没有就进行后续的配置。

@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
        public DispatcherServlet dispatcherServlet() {
            return new DispatcherServlet();
        }

        @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
        public ServletRegistrationBean dispatcherServletRegistration() {
            ServletRegistrationBean registration = new ServletRegistrationBean(
                    dispatcherServlet(), this.server.getServletMapping());
            registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
            if (this.multipartConfig != null) {
                registration.setMultipartConfig(this.multipartConfig);
            }
            return registration;
        }

这里他是创建了一个DispatcherServlet的bean,然后通过ServletRegistrationBean把这个servlet放入了standardcontext中,urlmapping可以通过application.properties中的server.servlet-path设置,默认是/。



猜你喜欢

转载自blog.51cto.com/2839840/2346577