zoukankan      html  css  js  c++  java
  • tomcat与springmvc 结合 之---第16篇 servlet如何解析成员变量和DispatcherServlet如何解析

    writedby 张艳涛,用了两个星期将深入刨析tomcat看完了,那么接下来该看什么呢?真是不知道,知识这东西上一个月看的jvm,锁.多线程并发 又都忘了....

    tomcat学完,我打算看springmvc因为,spring本质就是一个servlet, 叫DispatcherServlet,那么俩者联系紧密,打算结合二者,进行学习

    昨天看了一天发现spring源码,看起来比tomcat要难,因为springmv太杂了

    以前看过知道web.xml中的<servlet>标签解析,那么遇到了

     <servlet>
            <servlet-name>loginServlet</servlet-name>
            <servlet-class>com.qcc.study.servlet02.LoginServlet</servlet-class>
            <!-- 配置Servlet初始化参数 -->
            <init-param>
                <param-name>initParam</param-name>
                <param-value>qcc</param-value>
            </init-param>
            <!-- Web容器启动时就加载并实例化该Servlet -->
            <load-on-startup>0</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>loginServlet</servlet-name>
            <url-pattern>/login</url-pattern>    
        </servlet-mapping>
    </servlet>

    以上的参数该如何解析呢?这个init-param目的就是要给成员变量初始化值,看如何使用

    package com.qcc.study.servlet02;
     
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
    public class LoginServlet extends HttpServlet {
         成员变量1 initParam = null;
        成员变量2=null;
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取servlet初始化参数: String initParam = getServletConfig().getInitParameter("initParam"); System.out.println("initParam: ---->" + initParam); }

    那么可以看到,

    <init-parm>配置在<servlet>标签中,用来初始化当前的Servlet的,属于当前Servlet的配置,因此存放在 servletConfig对象中;
    通过getServletConfig().getInitParameter("initParam")的方式获取;
    如果通过源码来看webruleset中对"web-app/servlet/init-param" 解析

    看 addInitParameter StandardWrapper中

    可以看到其实参数以hashmap的方法来组织成键值对,如果使用的时候,实际上是从wrapper容器中取得的,和servlet.class没关系

    如果在形成的servlet对象的成员变量赋值写在init()方法里面,最后形成的servlet对象的成员变量就是完全体了,这其实就是dispatchServlet的做法


    先看一个dispatchservlet的配置文件web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
             id="WebApp_ID" version="3.0">
        <display-name>springmvcFirst</display-name>
        <!-- springMVC前端控制器 -->
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- contextConfigLocation配置springmvc加载的配置文件(配置处理器、映射器等) 如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml) -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc.xml</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <!-- url-pattern:*.action的请交给DispatcherServlet处理。 -->
            <url-pattern>*.action</url-pattern>
        </servlet-mapping>
    
    </web-app>

    看这其实是给servlet设值,那么看dispatchservlet的成员变量

    重点看FrameworkServlet,是dispatcherServlet的父类, 其中有一个成员变量叫contextConfigLocation,对应了标签中的参数名

    那么在哪里赋值的呢?

    在HttpServletBean的init()方法里面

    其中init(servletConfig)的调用逻辑 

    GenericServlet===>

        public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
        }

    本类的this.init(),其实这里使用了模板方法,这个this是指的dispatchservlet对象,

        public void init() throws ServletException {
    
        }

    所以调用的init()方法在 HttpServletBean 中

        public final void init() throws ServletException {
            if (logger.isDebugEnabled()) {
                logger.debug("Initializing servlet '" + getServletName() + "'");
            }
    
            // Set bean properties from init parameters.
            try {
                PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
                BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
                ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
                bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
                initBeanWrapper(bw);
                bw.setPropertyValues(pvs, true);
            }
            catch (BeansException ex) {
                logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
                throw ex;
            }
    
            // Let subclasses do whatever initialization they like.
            initServletBean();
    
            if (logger.isDebugEnabled()) {
                logger.debug("Servlet '" + getServletName() + "' configured successfully");
            }
        }

    这个方法 在servlet调用getServletConfig()实际上是StandardWrapperFacade,他是StandardWrapper的门面类...

    最后能看到BW是通过反射来实现属性的注入的


    另外说一点,这servlet类的设计,使用了模板方法,是在GenericServlet中的

        public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
        }

    那么看tomcat的调用

    这个servlet对象就是dispatchservelet,这样子类调用父类的GenericServlet的init(servletconfig)方法,接着调用this(这个this是子类disptacherservlet对象,可以sout(this)验证).init()方法,

    整个dispatcherservlet的调用思路就弄清楚了

  • 相关阅读:
    LocalImprove算法
    Improve算法
    CSU-ACM2014年校队选拔赛指导赛解题报告
    CSU-ACM暑假集训基础组训练赛(4)解题报告
    CSU-ACM暑假集训基础组七夕专场
    CSU-ACM暑假集训基础组训练赛(2) 解题报告
    CSU-ACM2014暑假集训基础组训练赛(1) 解题报告
    Aizu 2164 CSUOJ 1436 Revenge of the Round Table
    插头DP小结
    Codeforces 128C Games with Rectangle
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/15034036.html
Copyright © 2011-2022 走看看