【小家Spring】Spring注解驱动开发---Servlet 3.0整合Spring MVC(不使用web.xml部署描述符,使用ServletContainerInitializer)(上)

简介: 【小家Spring】Spring注解驱动开发---Servlet 3.0整合Spring MVC(不使用web.xml部署描述符,使用ServletContainerInitializer)(上)

前言


诚如各位所知,Servlet3.0是一次Java EE规范的一次重要升级。支持到可以全部采用注解驱动,大大简化了配置web.xml的麻烦。现在启动一个web容器并不强制依赖于web.xml部署描述符了。


然后我们印象深刻的是,之前我们在使用Spring MVC的时候,DispatcherServlet是必须要要在web.xml里配置,现在没有了这个,我们该怎么办呢?


本文主要以全注解驱动整合Spring MVC(注意:非Spring Boot环境,否则内部细节都看不到了)抛出问题,从而从内部原理方面去了解里面的门道。


Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)

Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)

Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)


准备工作


准备一个Spring MVC的maven工程


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.fsx</groupId>
    <artifactId>demo-war</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.0.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
            <version>1.18.4</version>
        </dependency>
        <!-- 记录log日志  logback-core并不需要显示导入-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- Spring MVC自动数据封装依赖的包  否则可能出现下面的错误,若使用@RequestBody的时候 -->
        <!-- Content type 'application/json' not supported 当然还有其余配置,原理了解-->
        <!-- 此处需要导入databind包即可, jackson-annotations、jackson-core都不需要显示自己的导入了-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
        <!-- fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.57</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- 该插件是为了没有web.xml情况下,打war包。编译不要报错 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <!-- 编译环境在1.8编译 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <compilerVersion>${java.version}</compilerVersion>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
       <!--
            directory:属性指定资源文件放置的目录。
            includes:包含哪些配置文件(.class文件不用写)
            filtering:如果设置为false的话,则表示上文的filters配置失效;如果设置为true,则会根据${env}.properties里面的键值对来
                       填充includes指定文件里的${xxxx}占位符(若不做环境区分,一般就是false即可)
        -->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                    <include>**/*.tld</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
</project>


然后个logback.xml一个最小配置:


<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>


备注:运行本war包的web容器为:tomcat-8.0(最高支持到了Servlet3.1~)


写一个最基本的Servlet,然后就可以访问了http://localhost:8080/demowar_war/hello


/**
 * @author fangshixiang
 * @description
 * @date 2019-02-16 22:04
 */
@WebServlet(urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("hello servlet...");
    }
}


我们发现,比之前采用web.xml配置的方式,省事太多了,可谓非常方便。


ServletContainerInitializer


之前web容器要整合其余模块,都是通过web.xml来的。那么现在注解驱动的话,怎么做呢?


这就是Servlet3.0给我们提供的特别特别重要的一个类ServletContainerInitializer来整个其它模块组件。通过读Servlet3.0的官方文档如下:

image.png


大致可以看出如下意思,它有如下能力:


Shared libraries(共享库) / runtimes pluggability(运行时插件能力)


     1.Servlet容器启动会扫描,当前应用里面每一个jar包ServletContainerInitializer的实现


     2.coder可以自己提供ServletContainerInitializer的实现类;然后自己书写逻辑。但是,但是,但是要记住,一定要必须绑定在,META-INF/services/javax.servlet.ServletContainerInitializer这个文件里,文件内容为就是ServletContainerInitializer实现类的全类名;


这样web容器在启动的时候,就会执行该接口的实现方法,从而我们就可以书写我们自己的模块初始化的一些逻辑。

image.png

//容器启动的时候会将@HandlesTypes指定的这个类型下面的子类(实现类,子接口等)传递过来;
@HandlesTypes(value = {HelloService.class})
public class MyServletContainerInitializer implements ServletContainerInitializer {
    /**
     * 应用启动的时候,会运行onStartup方法;
     * <p>
     * Set<Class<?>> c:感兴趣的类型的所有子类型;
     * ServletContext ctx:代表当前Web应用的ServletContext;一个Web应用一个ServletContext;
     * <p>
     */
    @Override
    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
      //这里的c会把所有我们感兴趣的类型都拿到
        System.out.println("感兴趣的类型:");
        for (Class<?> claz : c) {
            System.out.println(claz);
        }
    //==========================编码形式注册三大组件============================
        注册组件  ServletRegistration  
        //ServletRegistration.Dynamic servlet = ctx.addServlet("userServlet", new UserServlet());
        配置servlet的映射信息
        //servlet.addMapping("/user");
        //
        注册Listener
        //ctx.addListener(UserListener.class);
        //
        注册Filter  FilterRegistration
        //FilterRegistration.Dynamic filter = ctx.addFilter("userFilter", UserFilter.class);
        配置Filter的映射信息
        //filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
    }
}


image.png


启动容器,我们会看到:


image.png

把我们关心的接口子类型(包含子接口、抽象类、实现类)都放进来了。但是需要注意:不包含自己哦~



使用ServletContext注册Web组件(Servlet、Filter、Listener)


使用编码的方式,在项目启动的时候给ServletContext里面添加组件;


必须在项目启动的时候来添加(为了安全考虑,若已经启动完成再添加,是无效的)

1)、ServletContainerInitializer得到的ServletContext;

2)、ServletContextListener得到的ServletContext;


/不拦截.jsp。而/*都会拦截

DispatcherServlet映射:/

Filter映射:/*

Spring MVC拦截器的映射:/**


相关文章
|
13天前
ssm使用全注解实现增删改查案例——web.xml
ssm使用全注解实现增删改查案例——web.xml
10 0
|
13天前
|
设计模式 前端开发 Java
了解 Spring MVC 架构、Dispatcher Servlet 和 JSP 文件的关键作用
Spring MVC 是 Spring 框架的一部分,是一个 Web 应用程序框架。它旨在使用 Model-View-Controller(MVC) 设计模式轻松构建Web应用程序。
67 0
|
13天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
9月前
|
应用服务中间件
Servlet - 匹配模式加注解源码分析
Servlet - 匹配模式加注解源码分析
56 0
|
13天前
|
前端开发 Java 容器
SpringBoot中注册Servlet、Filter和Listener(代码和注解两种方式)
SpringBoot中注册Servlet、Filter和Listener(代码和注解两种方式)
70 0
|
13天前
|
XML Java 应用服务中间件
SpringMVC与Servlet3.0整合 - ServletContainerInitializer注解配置项目
SpringMVC与Servlet3.0整合 - ServletContainerInitializer注解配置项目
25 1
|
13天前
Servlet3.0+环境下使用注解注册Servlet、Filter和Listener组件
Servlet3.0+环境下使用注解注册Servlet、Filter和Listener组件
44 2
|
7月前
|
SQL 前端开发 Java
JSP网上订餐管理系统myeclipse开发sql数据库BS模式java编程servlet技术mvc框架
JSP 网上订餐管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助servlet技术mvc框架,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,使用java语言开发,系统主要采用B/S模式开发。
41 0
|
9月前
|
前端开发 Java 开发者
深入解析Java中的 @Controller 注解:构建灵活的Web应用
在现代的Java Web开发中,控制层是连接用户界面和后端逻辑的关键环节。Spring框架为我们提供了丰富的注解来构建控制层,其中 @Controller 注解在MVC架构中扮演着重要的角色。本文将带您深入了解 @Controller 注解,探讨其特点、用法、实现方式以及在实际应用中的优势。
|
9月前
|
XML 数据格式
告别web.xml映射Servlet、Filter、Listener,解锁注解新方式开发
告别web.xml映射Servlet、Filter、Listener,解锁注解新方式开发