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

时间:2023-03-09 01:04:40
springmvc学习指南 之---第27篇 spring如何实现servlet3.0无web.xml 配置servlet对象的

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

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

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

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

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

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实现了

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

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

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

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

这些类有的在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);

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

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

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

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

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

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

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

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

还有

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

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

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

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