• 基于servlet3.0搭建spring mvc应用 无web.xml 无spring boot


    1、概述

    还记得我刚学Java Web的时候,是17年,那时候servlet和jsp还在延续它的辉煌,ssh和ssm仍然是企业潮流,开发工具还是eclipse,有时候一个Tomcat字符集乱码的问题都要解决很久,老师教我们从servlet,到jsp,再到ssh和ssm,可是学到最后,即使我们的项目能跑了,可再让我们手工搭一遍,根本就摸不着头脑,因为配置太多了,我们搞不清楚原理,搞不清楚为什么要这么配置,自然也就记不住。

    然后,往往是这些复杂的配置,才能更好地反映我们的基本功扎不扎实,现在的spring boot封装太过完美了,以及有了更强大的开发工具IDEA,几分钟就能搭建出一个能跑的项目来。还记得当年我们都是在web.xml里配置各种servlet,filter,用了spring boot之后,突然一瞬间就再也没碰过web.xml了,以前由于有各种东西要学,其中的猫腻也就没有追究了。

    如今的我,已经不是当年的我。本文的目的,不是为了回味当年的servlet、jsp和web.xml的,我会教你如何不用web.xml,去搭建一个spring mvc应用,注意,我不会引入spring boot,也不会引入持久层框架,而是专注于一个最小化的、能跑的spring mvc应用,我会在IDEA中配置Tomcat,然后将应用放到Tomcat中。最终的效果是,我们能在浏览器上访问静态资源,也能在浏览器上访问Controller。

    相信我,你会学到很多基础但很重要的东西。

    2、Spring MVC请求流程

    1. 请求到达DispatcherServlet
    2. DispatcherServlet会将请求委托给控制器,但控制器会有多个,因此需要先查找一个或多个处理器映射(handler mapping)
    3. 找到控制器,且控制器处理好后,就会将模型与视图(逻辑名,需要解析)返给DispatcherServlet
    4. DispatcherServlet再去调用视图解析器,视图解析器将解析出来的视图返给DispatcherServlet
    5. 最后将视图和模型打包发给前端

    3、Spring MVC不需要web.xml的原理

    传统方式,servlet会配置在web.xml中,然后打成war包。但是基于servlet3.0规范和3.1增强,就不需要web.xml了。

    原理:

    • 在servlet3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果能发现的话就会用它来配置Servlet容器。Spring提供了这个接口的实现,名为SpringServletContainerInitializer,这个类会查找实现WebApplicationInitializer的类并将配置的任务交给他们来完成,Spring3.2引入了一个便利的WebApplicationInitializer基础实现,就是AbstractAnnotationConfigDispatcherServletInitializer。
    • 也就是说,AbstractAnnotationConfigDispatcherServletInitializer的任意子类都会自动地配置DispatcherServlet和Spring应用上下文;
    • 继承AbstractAnnotationConfigDispatcherServletInitializer,需要实现三个方法:
      • getServletMappings:将一个或多个路径映射到DispatcherServlet上
      • getRootConfigClasses:用于定义DispatcherServlet应用上下文中的bean
      • getServletConfigClasses:配置ContextLoaderListener创建的上下文中的bean
    • Tomcat7.0以上版本支持servlet3.0

    两个上下文的关系:

    • 当DispatcherServlet启动时,它会创建Spring应用上下文,并加载配置文件或配置类中声明的bean
    • 在Spring web环境中,还有一个上下文,这个上下文是由ContextLoaderListener创建的
    • 一般DispatcherServlet用于加载包含web组件的bean,如控制器、视图解析器、处理器映射,而ContextLoaderListener负责加载应用中其它的bean,如dao
    • AbstractAnnotationConfigDispatcherServletInitializer会同时创建DispatcherServlet和ContextLoaderListener

    4、搭建Spring MVC项目

    1、项目整体架构

    在这里插入图片描述

    2、pom.xml

    首先,在IDEA中创建一个Maven项目,完整的pom.xml如下所示。

    
    <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.0modelVersion>
    
        <groupId>com.bobogroupId>
        <artifactId>spring-mvcartifactId>
        <version>1.0-SNAPSHOTversion>
        <properties>
            <spring.version>5.2.5.RELEASEspring.version>
            <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
            <java.version>1.8java.version>
            <resource.delimiter>@resource.delimiter>
            <maven.compiler.source>${java.version}maven.compiler.source>
            <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
            <maven.compiler.target>${java.version}maven.compiler.target>
        properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-webmvcartifactId>
                <version>${spring.version}version>
            dependency>
            <dependency>
                <groupId>javax.servletgroupId>
                <artifactId>javax.servlet-apiartifactId>
                <version>3.1.0version>
                <scope>providedscope>
            dependency>
        dependencies>
    project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    3、WebAppInitializer

    这个类就是上文提到的AbstractAnnotationConfigDispatcherServletInitializer类的子类。

    package com.bobo.springmvc.config;
    
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    
    public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[]{RootConfig.class};
        }
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class[]{WebConfig.class};
        }
        @Override
        protected String[] getServletMappings() {
            System.out.println("getServletMappings executed");
            return new String[]{"/"};
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    4、RootConfig

    ComponentScan用于扫描项目中的组件。

    package com.bobo.springmvc.config;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ComponentScan("com.bobo.springmvc")
    public class RootConfig {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5、WebConfig

    需要使用@EnableWebMvc启用Spring MVC,并且配置视图解析器。

    WEB-INF目录是web应用的安全目录,里面的资源不能被浏览器直接访问。如果资源是放到src/main/web目录下的,是可以被浏览器直接访问的。

    package com.bobo.springmvc.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.ViewResolver;
    import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import org.springframework.web.servlet.view.InternalResourceViewResolver;
    
    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = {"com.bobo.springmvc"})
    public class WebConfig implements WebMvcConfigurer {
        @Bean
        public ViewResolver viewResolver(){
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setPrefix("/WEB-INF/views/");
            resolver.setSuffix(".html");
            resolver.setExposeContextBeansAsAttributes(true);
            return resolver;
        }
    
        /**
         * 配置静态资源的处理.将静态资源的请求转发到servlet容器中的默认servlet,而不是让DispathcerServlet去处理
         * @param configurer
         */
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    6、HelloController

    package com.bobo.springmvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    public class HelloController {
        @RequestMapping(method = RequestMethod.GET,value = "/toHello")
        public String toHello(){
            System.out.println("请求到达HelloController.toHello方法");
            return "hello";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    7、web目录

    仔细看,src/main/web文件夹中间有一个实心的蓝色圆点,它标志这是一个web目录,这个是怎么生成的呢?

    在IDEA的Project Structure->Modules找到对应的项目,然后右键->Add->选择Web,然后在Web Resource Directories新增一个选项,如下图所示。
    在这里插入图片描述
    首页index.html和hello.html的内容随意,只要最后能被访问到就行。

    8、配置Tomcat

    下载:https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.83/bin/ ,解压

    修改logging.properties,凡是UTF-8都改为GBK,否则IDEA控制台会中文乱码,如下图所示。
    在这里插入图片描述

    将项目导出为artifact,如下图所示。
    在这里插入图片描述
    这里有一个Output directory,如下图所示,我们先记住它。
    在这里插入图片描述
    在IDEA中配置好Tomcat,然后部署项目,如下图所示。
    在这里插入图片描述
    添加进来后,将下面的路径改为/。其实不改也行,主要是为了方便。
    在这里插入图片描述

    5、运行测试

    一切都准备好后,运行项目,我们发现在Output Directory目录下多了些东西,这是Tomcat启动时生成的。使用tree /F命令,输出如下所示。

    F:.
    │  index.html
    │
    ├─META-INFMANIFEST.MF
    │
    └─WEB-INF
        ├─classes
        │  └─com
        │      └─bobo
        │          └─springmvc
        │              ├─config
        │              │      RootConfig.class
        │              │      WebAppInitializer.class
        │              │      WebConfig.class
        │              │
        │              └─controller
        │                      HelloController.class
        │
        ├─lib
        │      spring-aop-5.2.5.RELEASE.jar
        │      spring-beans-5.2.5.RELEASE.jar
        │      spring-context-5.2.5.RELEASE.jar
        │      spring-core-5.2.5.RELEASE.jar
        │      spring-expression-5.2.5.RELEASE.jar
        │      spring-jcl-5.2.5.RELEASE.jar
        │      spring-web-5.2.5.RELEASE.jar
        │      spring-webmvc-5.2.5.RELEASE.jar
        │
        └─views
                hello.html
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在浏览器上分别访问首页http://localhost:8080/和Controller http://localhost:8080/toHello 进行测试,如果能成功访问,那就说明大功告成啦!

  • 相关阅读:
    云原生--kubectl命令汇总
    java 每日一练 (5)
    宇视大屏出现不规则闪烁故障排查方法
    入门者必看-Ansible:自动化运维的利器
    JavaScript 19 JavaScript 字符串方法
    ubuntu安装docker
    防火墙部署模式 -- 镜像流量(旁路模式)
    JAVA 版小程序商城免费搭建 多商家入驻 直播带货 商城系统 B2B2C 商城源码之 B2B2C产品概述
    嵌入式开发套件
    深度学习100例 —— 卷积神经网络(CNN)识别眼睛状态
  • 原文地址:https://blog.csdn.net/xl_1803/article/details/127767293