• springmvc学习指南 之---第27篇 spring如何实现servlet3.0无web.xml 配置servlet对象的


    writedby 张艳涛 基于web.xml配置,有人说麻烦,tomcat给按照servlet3.0,实现了基于注解@WebServlet,有人说springmvc的springmvc.xml配置麻烦

    于是有了springboot,如果让我问,这好吗?  我是不喜欢的,如果你看了深入刨析tomcat后,你就知道使用注解是多么恶心的事情了,打个比方,如果给你一个

    宇宙飞船,你不会开,那么给你两种途经,一个是基于飞船的各个系统部件的说明,告诉你这个是开关,开关在哪里,这个是刹车,刹车在哪里;而另外一种是

    给给开关贴一个标签,给刹车一个标签,给飞船一个扫描仪,然后让飞船自己运行;多么智能,问题是飞船坏了不会修呢. 我是不喜欢这种复杂的简单,所以

    现在只能从xml的配置来 学习注解,现在开始看spring,被逼的要从spirng2.5开始看,问题是资料太少了....

     我是一个活在旧时代的sha子,时间越久,越发现别人都在进步,而自己止步不前,一个时代的人终究会在自己的笼子里做困兽之斗,正如sporty做的调查,35岁后的听歌喜好,不会接受35之后的歌曲了. 就这样吧,活的真惨

    xml时代,无配置时代的springboot,可是我有点选择吗?没有

    xml时代,tomcat是如何解析<servlet>标签的呢?

    1,先看webrule的解析规则

            digester.addRule(prefix + "web-app/servlet",
                             new WrapperCreateRule(digester));
            digester.addSetNext(prefix + "web-app/servlet",
                                "addChild",
                                "org.apache.catalina.Container");
    
            digester.addCallMethod(prefix + "web-app/servlet/init-param",
                                   "addInitParameter", 2);
            digester.addCallParam(prefix + "web-app/servlet/init-param/param-name",
                                  0);
            digester.addCallParam(prefix + "web-app/servlet/init-param/param-value",
                                  1);

    分析,先创建一个规则rule,这个规则会在遇到遇到web-app/servlet标签的时候,执行规则的begin,再次遇到的时候会执行end

    /**
     * A Rule that calls the factory method on the specified Context to
     * create the object that is to be added to the stack.
     */
    
    final class WrapperCreateRule extends Rule {
    
        public WrapperCreateRule(Digester digester) {
            super(digester);
        }
    
        public void begin(Attributes attributes) throws Exception {
            Context context =
                (Context) digester.peek(digester.getCount() - 1);
            Wrapper wrapper = context.createWrapper();
            digester.push(wrapper);
            if (digester.getDebug() > 0)
                digester.log("new " + wrapper.getClass().getName());
        }
    
        public void end() throws Exception {
            Wrapper wrapper = (Wrapper) digester.pop();
            if (digester.getDebug() > 0)
                digester.log("pop " + wrapper.getClass().getName());
        }
    
    }

    看到关键代码是创建了standwrapper,推进去了digester栈中,

    2,执行standardcontext的addChild方法将wrapper加入其中,接着,将servlet装入context的children成员变量中


    上边的解析非常清晰,如果遇到不懂的标签,自己看下webruleset的规则,秒懂了,而现在呢?我想看spring如何实现了servlet3.0的无xml配置dispatcherservlet的?

    真是恶心,看了1个小时才看懂点,下面将分析过程说明如下

    servlet为了实现无xml,那么就得基于注解,就得在某个类中使用注解,现在是有两种实现方法的

    其一是使用@WebServlet(name="xxxx",url="xxx")

    其二是使用ServletContainerInitializer 接口,原理是,在tomcat等servlet容器启动的时候,会去lib包下扫描springmvc.x.y.z的jar包内的所有类,如果类是ServletContainerInitializer 接口的实现那么就执行这个实现类的onStartup方法.那么我们来就spirng实现了

    那末会有几个实现呢?答案是6个

      

    这些类有的在webmvc,web,security-web,自定义继承AbstractAnnotationConfigDispatcherServletInitializer类,等包中

    那么就需要筛选,排除interface 和abstract类,那莫就剩下了自己的自定义类

    package org.springframework.samples.mvc.config;
    
    import javax.servlet.Filter;
    
    import org.springframework.web.filter.DelegatingFilterProxy;
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    
    /**
     * Initialize the Servlet container. This class is detected by the Servlet
     * container on startup.
     */
    public class MvcShowcaseAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
    
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[] { RootConfig.class };
        }
    
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class[] { WebMvcConfig.class };
        }
    
        @Override
        protected String[] getServletMappings() {
            return new String[] { "/" };
        }
    
        @Override
        protected Filter[] getServletFilters() {
            return new Filter[] { new DelegatingFilterProxy("csrfFilter") };
        }
    
    }

    接下来就是执行这个MvcShowcaseAppInitializer,的  initializer.onStartup(servletContext);

    他自己没有onstartup方法,看他的父类AbstractDispatcherServletInitializer

    那么还是挑重点的讲,进入registerDispatcherServlet

    创建了dispatcherServlet对象,然后将对象添加到standardcontext中去,

    看这个servletContext.addServlet(),就是tomcat8.5的代码了,

    还有

    能看到将也是创建wrapper,设置wrapper属性,然后交给stardardcontext.addChild(wrapper)给children的成员变量

    至此对象创建完成,还没解析的有servletmaping标签,和初始化参数等吧,

    这么看来,其实解析一个无xml配置,真的好费劲呢,所以对能否学好springboot感到迷惑呢

  • 相关阅读:
    Ubuntu16.04.1 安装Nginx
    Ubuntu16.04.1 安装Redis-Cluster
    SeekBar的简单使用
    Async异步处理
    SQLite
    Shareprefrence
    android中的主线程
    Fragment的简单使用
    ArrayAdapter的使用
    用Intent传递对数
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/15086999.html
Copyright © 2020-2023  润新知