无配置搭建springmvc项目 见识不一样的springmvc

前言:

springmvc一直在版本更新迭代,其实springboot的诞生并不是那么突兀 和springmvc还是有所关联的,只是很多人都停留在最早那一套ssm框架搭建(application.xml等配置) 在springmvc 5开始 就舍弃了之前那一套流程

回顾:

传统的servlet web项目 : web.xml中注册servlet
     <!-- 两个标签中的servlet name要一致; 进行映射 url pattern指定路径-->
     <servlet>
         <servlet-name>HelloServlet</servlet-name>
         <servlet-class>HelloServlet</servlet-class>
     </servlet>
 
     <servlet-mapping>
         <servlet-name>HelloServlet</servlet-name>
         <url-pattern>/a</url-pattern>
     </servlet-mapping>

servlet3.0之后:@WebServlet

原理: 在3.0之后 servlet采用了注解的形式 注解写在servlet中,那么反射便可以获取到当前类信息 于是web,xml中类名可以省略,那么就还剩一个最重要的节点 ,所以很明显 @WebServlet(“value”) value就是url地址了,这样web.xml便可以省略。

分割线===========================================

下面看看springmvc 5之后是怎么处理的

  1. tomcat之所以被称为web容器 是因为它遵循了servlet规范,servlet3.0中 规定,web容器启动时,必须调用ServletContainerInitializer (简称SCI)实例中的onStarup方法,而SCI的实现类 通过java SPI声明自己是ServletContainerInitializer 的provider
这里可能会有点绕 我们先来看看springmvc是怎么做的 在META-INF底下建一个services包,写上文件名,文件里面写的 就是SCI的实现类

在这里插入图片描述

demo 代码如下
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

// 测试servlet
public class TestServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        PrintWriter pw = resp.getWriter();
        pw.write("hello spring mvc 5");
        pw.close();
        return;
    }
}



注意看注释内容 讲解都在注释


import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Set;

/**
 * Description:SCI实现类
 *  类比spring mvc中 SpringServletContainerInitializer implements ServletContainerInitializer
 * 在spring mvc中 也正是SpringServletContainerInitializer 暴露在SPI中
 * 同理 我们自定义的类TomcatServletContainerInitializer 也应该暴露在SPI中
 * date: 2021/3/12
 * @author:qkj
 * @since JDK 1.8
 */

/**
 * servlet 容器还会扫描 被@HandlesTypes 注解的接口实现类
 * HandlesTypes :javax.servlet.annotation; 这也是servlet3.0规范
 * TomcatWebApplicationInitializer 类比springmvc中 WebApplicationInitializer
 */
@HandlesTypes(TomcatWebApplicationInitializer.class)
public class TomcatServletContainerInitializer implements ServletContainerInitializer  {
    
    

    @Override
    public void onStartup(Set<Class<?>> set, ServletContext ctx) throws ServletException {
    
    
        if (set != null) {
    
    
            Iterator<Class<?>> iterator = set.iterator();
            while (iterator.hasNext()) {
    
    
                Class<?> clazz = (Class<?>) iterator.next();
                if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())
                        && TomcatWebApplicationInitializer.class.isAssignableFrom(clazz)) {
    
    
                    try {
    
    
                        // 调用TomcatWebApplicationInitializer 接口实现类的 onStartup() 方法
                        ((TomcatWebApplicationInitializer) clazz.newInstance()).onStartup(ctx);
                    } catch (Exception e) {
    
    
                        e.printStackTrace();
                    }
                }
            }
        }
    }

}

import javax.servlet.ServletContext;
// 接口 类比springmvc WebApplicationInitializer
public interface TomcatWebApplicationInitializer {
    
    

    void onStartup(ServletContext servletContext);

}


  1. 重点来了 我们实现的是TomcatWebApplicationInitializer 而不是SCI,为什么还是能执行onStarup方法?因为TomcatWebApplicationInitializer 在上面SCI实现类中 被@HandlesTypes修饰了 所以也会被扫描
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;

public class TomcatServletInitializer implements TomcatWebApplicationInitializer {
    
    

    @Override
    public void onStartup(ServletContext servletContext) {
    
    

        ServletRegistration.Dynamic registration = servletContext.addServlet(TestServlet.class.getName(), TestServlet.class);
        // 如果值为整数或则0,表示容器在应用启动时候加载并且初始化这个Servlet  值越小servlet的优先级越高,就越先被加载
        registration.setLoadOnStartup(1);
        // url
        registration.addMapping("/app");
    }

}
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.webresources.DirResourceSet;
import org.apache.catalina.webresources.StandardRoot;

import java.io.File;

// 启动方法
public class TomcatStartup {
    
    
    public static void main(String[] args) {
    
    
        try {
    
    
            // 创建Tomcat容器
            Tomcat tomcatServer = new Tomcat();
            // 端口号设置
            tomcatServer.setPort(9000);
            // 读取项目路径 加载静态资源
            StandardContext ctx = (StandardContext) tomcatServer.addWebapp("/", new File("src/main").getAbsolutePath());
            // 禁止重新载入
            ctx.setReloadable(false);
            // class文件读取地址
            File additionWebInfClasses = new File("target/classes");
            // 创建WebRoot
            WebResourceRoot resources = new StandardRoot(ctx);
            // tomcat内部读取Class执行
            resources.addPreResources(
                    new DirResourceSet(resources, "/WEB-INF/classes", additionWebInfClasses.getAbsolutePath(), "/"));
            tomcatServer.start();
            // 异步等待请求执行
            tomcatServer.getServer().await();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

}

pom.xml



    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-core -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>8.5.15</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jasper -->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>8.5.15</version>
        </dependency>


    </dependencies>


gitee地址

Guess you like

Origin blog.csdn.net/qq_36268103/article/details/114694725