3. servlet 和 springmvc框架關系


在springmvc上我們會編寫很多相關的配置

  • 編寫springmvc.xml
    • 配置映射器
    • 配置 處理適配器
      ...
  • web.xml
    • 配置前端控制器 (DispatcherServlet)

官網: https://spring.io/
弱小和無知並不是生存的障礙,傲慢才是。

=================================================================

=================================================================

  • 注解方式
public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletCxt) {

        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        ac.register(AppConfig.class);
        ac.refresh();

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app/*");
    }
}

=================================================================

  • 配置方式
<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/app-context.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>

</web-app>

=================================================================

* 創建maven項目,然后導入web支持

=================================================================

  • 導入springmvc相關依賴
<dependencies>
        <!--springmvc框架-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.0.8.RELEASE</version>
        </dependency>
        <!--servlet3.0-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- 嵌入式tomcat -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>9.0.20</version>
        </dependency>
        <!--解決JSP異常-->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>9.0.20</version>
        </dependency>
</dependencies>

=================================================================

=================================================================

* 創建一個跟官網上一樣的類

package com.min.mvc;

import com.min.config.AppConfig;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    public void onStartup(ServletContext servletCxt) {

        // 通過 注解的方式 創建 IOC容器
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        // 注冊一個配置類
        ac.register(AppConfig.class);
        // 刷新 IOC 容器配置
        ac.refresh();

        // 創建和注冊servlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        // 注冊 servlet
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        // 啟動加載
        registration.setLoadOnStartup(1);
        // DistpatcherServlet 映射關系
        registration.addMapping("*.do");
    }
}

* 創建配置類

package com.min.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 配置類
 * @Configuration : 通過他注冊一個配置類
 * @ComponentScan : 通過他開啟一個掃描
 */
@Configuration
@ComponentScan(value = "com.min.controller")
public class AppConfig {
}

=================================================================

  • 編寫一個controller

package com.min.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {

    @RequestMapping("/hello.do")
    @ResponseBody
    public String hello(){
        return "Hello World!";
    }
}

=================================================================

* 訪問hello.do


經過一番波折發現通過官網上的代碼也能跑通。。我丟😂😂😂

=================================================================

更有趣的是這哥們跟我們之前寫的Servlet3.0的似曾相識哈哈,那我們一探究竟吧。

=================================================================

  • 會發現這個類也是實現ServletContainerInitializer 接口,@HandlesTypes注解以及重寫onStartup方法


package org.springframework.web;

import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.Nullable;
import org.springframework.util.ReflectionUtils;

@HandlesTypes({WebApplicationInitializer.class})
public class SpringServletContainerInitializer implements ServletContainerInitializer {
    public SpringServletContainerInitializer() {
    }

    public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
        List<WebApplicationInitializer> initializers = new LinkedList();
        Iterator var4;
        if (webAppInitializerClasses != null) {
            var4 = webAppInitializerClasses.iterator();

            while(var4.hasNext()) {
                Class<?> waiClass = (Class)var4.next();
                if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
                        initializers.add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(waiClass, new Class[0]).newInstance());
                    } catch (Throwable var7) {
                        throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
                    }
                }
            }
        }

        if (initializers.isEmpty()) {
            servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
        } else {
            servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
            AnnotationAwareOrderComparator.sort(initializers);
            var4 = initializers.iterator();

            while(var4.hasNext()) {
                WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
                initializer.onStartup(servletContext);
            }

        }
    }
}

=================================================================

  • WebApplicationInitializer接口

package org.springframework.web;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

public interface WebApplicationInitializer {
    void onStartup(ServletContext var1) throws ServletException;
}

所以經過以上的查看和測試,發現其中的原理就是這樣子的!!!
底層源碼

  • 迭代
  • 通過反射實例化對象
  • 調用這些實現類的 startup 方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM