SpringMVC(一)【入门】

前言

学完了大数据基本组件,SpringMVC 也得了解了解,为的是之后 SpringBoot 能够快速掌握。SpringMVC 可能在大数据工作中用的不多,但是 SSM 毕竟是现在就业必知必会的东西了。SpringBoot 在数仓开发可能会经常用到,所以不废话学吧。

1、SpringMVC 概述

1.1、请求响应模式演进过程

1.1.1、三层架构

  • web:页面数据的收集以及产生页面
  • service:业务处理
  • dao:数据持久化

弊端:一个 Servlet 只能一个处理请求。

1.1.2、MVC 模式

浏览器将请求发送给控制器,控制器调用 Service 层,再由 Service 层调用 dao 层得到数据,将得到的数据组织成数据模型(封装成对象),然后将页面和数据模型封装到一起返回给浏览器。这样,一个 Servlet 就可以处理多个请求了。

MVC 模式下的 view 一般用的是 jsp,但是现在我们一般都用的是 HTML、CSS、E lementUI、Vue 这些技术:

1.13、异步调用

异步调用模式下,我们不再需要将 jsp 和 model 共同返回给浏览器展示了,而是页面和 model 分开,页面用 html、vue 这些前端技术,model 需要将它封装成 json 对象返回给我们的前端(因为 java 对象不能直接返回给页面):

这样,我们的前端页面就可以从 json 中把数据抽取出来,然后组织成页面展示到浏览器上面。

异步调用下 SpringMVC 的任务
  • Controller 层的开发
  • 数据转为 json 格式返回给前端

2、SpringMVC 入门案例

2.1、入门案例

使用 Servlet 开发 web 程序的过程:

  1. 创建 web 工程
  2. 设置 tomcat 服务器
  3. 导入依赖(Servlet)
  4. 定义处理请求的功能类(UserServlet)
  5. 配置请求映射关系

使用 SpringMVC 开发 web 程序的过程:

  1. 创建 web 工程
  2. 设置 tomcat 服务器
  3. 导入依赖(SpringMVC + Servlet)
  4. 定义处理请求的功能类(UserController)
  5. 配置请求映射关系
  6. 将 SpringMVC 设定加载到 Tomcat 容器中

0、配置环境

1、导入依赖

XML 复制代码
<build>
    <plugins>
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <port>85</port>
          <path>/</path>
          <ignorePackaging>true</ignorePackaging>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.0.RELEASE</version>
    </dependency>
  </dependencies>

2、初始化SpringMVC环境

java 复制代码
@Configuration
public class SpringMvcConfig {
}

3、创建 SpringMVC 控制器类(等同于 Servlet 功能)

java 复制代码
@Controller
public class UserController {

    @RequestMapping("/save")
    public void save(){
        System.out.println("user save ...");
    }

}

4、设定SpringMVC加载对应的Bean

java 复制代码
@Configuration
@ComponentScan("com.lyh.controller") // 扫描
public class SpringMvcConfig {

}

5、初始化 Servlet 容器,加载SpringMVC 环境,并设置 SpringMVC 请求拦截的路径

java 复制代码
/**
 * Servlet 容器配置类
 */
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {

    /**
     * 加载SpringMVC容器对象
     * @return
     */
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }

    /**
     * 请求由谁来处理?tomcat/springmvc
     * @return
     */
    protected String[] getServletMappings(){
        return new String[]{"/"};  // 所有请求都由 springmvc 来处理
    }

    /**
     * 加载 Spring 的配置对应的容器对象
     * @return
     */
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }
}

6、报错1

访问 localhost:85/save 报错:

7、设置请求返回值为 json 信息 并添加注解@ResponseBody 代表返回内容就是响应内容

8、重新请求 localhost:85/save

2.2、注解&配置类说明

2.2.1、注解

|-----------------|------|---------|-----------------------|-----------------------------------------------------|
| 名称 | 类型 | 位置 | 作用 | 参数 |
| @Controller | 类注解 | 控制器类上方 | 设置SpringMVC的核心控制器Bean | 无参 |
| @RequestMapping | 方法注解 | 控制器方法上面 | 设置当前控制器方法请求访问路径 | @RequestMapping("/save") 访问的时候就访问 localhost:85/save |
| @ResponseBody | 方法注解 | 控制器方法上面 | 设置当前控制器方法的返回值就是响应内容 | 无参 |

2.2.2、AbstractDispatcherServletInitializer

AbstractDispatcherServletInitializer 是 SpringMVC 提供的快速初始化 Web3.0 容器的抽象类,它提供了三个接口抽象方法供用户实现:

1)createServletApplicationContext

作用:加载 SpringMVC 容器,一旦 tomcat 启动,就会把这个容器加载到 tomcat 容器中。

2)getServletMappings

作用:设定 SpringMVC 对应的请求路径,也就是哪些请求由 SpringMVC 管,哪些由 tomcat 管。返回 "/" 代表拦截所有请求交给 SpringMVC 处理。

3)createRootApplicationContext

作用:加载除了 SpringMVC 之外的所有容器的内容(Bean)

这里我们没有其它容器,所以直接返回 null。

2.3、总结

对于一次性工作,我们以后做项目直接 CV 大法然后改一改就好了。我们真正做的最多的还是多次工作:定义控制器、定义控制器中的方法等。

3、SpringMVC 工作流程分析

工作流程主要分为两部分:

  1. 启动服务器
  2. 发送一次请求

3.1、服务器初始化过程

在 Web3.0 的规范中,我们不再需要 web.xml 来配置,而是通过一个配置类(继承 AbstractDispatcherServletInitializer 抽象类)来完成。

3.2、单次请求工作流程

4、Bean 加载控制

4.1、Controller 加载控制与业务 Bean 加载控制

现在我们的项目结构是这样的:

  • config目录存入的是配置类,我们之后的配置类会有:

    • ServletContainersInitConfig

    • SpringConfig

    • SpringMvcConfig

    • JdbcConfig

    • MybatisConfig

  • controller目录存放的是SpringMVC的controller类

  • service目录存放的是service接口和实现类

  • dao目录存放的是dao/Mapper接口

4.1.1、SpringMVC 相关 Bean 加载控制

  • SpringMVC 加载的 Bean 都放在 com.lyh.controller 包下

controller 包下的所有 Bean 会被 SpringMVC 来加载,而其它包(dao、service等)下的 Bean 都应该由 Spring 来加载,但是如何控制 Spring 不去加载 SpringMVC 中的 Bean ?

4.1.2、Spring 相关 Bean 加载控制

  • 方式一:Spring 加载的 Bean 设定扫描范围为 com.lyh,排除掉 controller 包内的 Bean
  • 方式二:Spring 加载的 Bean 设定扫描范围为精准范围,比如 service、dao包等
  • 方式三:不区分 Spring 和 SpringMVC 的环境,都加载到同一个环境中。

方式一:只加载 Spring 管理的 Bean:

java 复制代码
@Configuration
@ComponentScan({"com.lyh.service","com.lyh.dao"})
public class SpringConfig {

}

方式二:按照注解进行过滤,过滤掉由 SpringMVC 管理的包下的 Bean:

java 复制代码
@Configuration
@ComponentScan(value = "com.lyh",
        excludeFilters = @ComponentScan.Filter(
                type = FilterType.ANNOTATION,
                classes = Controller.class
        ))
public class SpringConfig {

}

测试

java 复制代码
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 如果Controller类被Spring注册了,会输出对象地址
        // 如果没有被注册,那么会报错
        System.out.println(ctx.getBean(UserController.class));
    }
}

注意:在测试时,SpringMvcConfig 的注解 Configuration 需要去掉,因为 SpringConfig 中我们设置 Spring 会扫描所有 com.lyh 目录下的目录(除了 exclude 之外的),但是 Spring 会把所有带有 @Configuration 注解的类加载一遍,而 SpringMvcConfig 上面除了 @Configuration 之外还有一个注解 @ComponentScan 用来扫描 controller 包,所以 Spring 又会把 controller 目录下的 Bean 加载一遍。

所以我们可以把这两个带有 @Configuration 注解的配置类放到 com.lyh 包外边,防止被 Spring 加载。

到这里,我们需要把由 Spring 加载的环境配置放到 ServletContainersInitConfig 中:

这样,当服务器启动后,tomcat 容器中就不只有 SpringMVC 的容器了,还有 Spring 的容器。

4.1.3、简化开发

目前,我们需要在 Servlet 容器中分别指定两个配置类(SpringMVC 和 Spring),能不能再简化一些呢? 答案是可以的,我们只需要继承抽象类 AbstractAnnotationConfigDispatcherServletInitializer 即可:

本节注解说明

|----------------|-----|-------|------------------------------------------------------------------------------------------------------------|
| 名称 | 位置 | 作用 | 参数 |
| @ComponentScan | 类注解 | 类定义上方 | excludeFilters:排除扫描路径中加载的bean,需要指定类别(type)和具体项(classes) includeFilters:加载指定的bean,需要指定类别(type)和具体项(classes) |

5、Postman

目前我们测试请求都是直接在地址栏输入参数,但是这种方式只能模拟 get 请求,对于 post 请求我们还需要创建表单,对于更复杂的 Ajax 请求我们不只需要表单,还是配置 JavaScript 代码来完成异步提交。

postman 的作用就是用来模拟各种网页请求的,所以作为一个后端程序员,我们就再也不用去写一些恶心的前端代码去测试了。

相关推荐
budingxiaomoli15 小时前
Spring Web MVC 知识总结
spring·mvc
虾米Life2 天前
MVC与MVVM 架构
架构·mvc·mvvm
笛卡尔的心跳4 天前
Spring MVC 注解
java·spring·mvc
小松加哲4 天前
Spring MVC 核心原理全解析
java·spring·mvc
那个失眠的夜5 天前
RESTful 语法规范 核心注解详解
java·spring·mvc·mybatis
羌俊恩5 天前
Centos环境django项目部署过程
django·flask·centos·mvc·mtv·web项目框架
Zzzzmo_7 天前
【JavaEE】多线程04—线程池/定时器
java·线程池·定时器·javaee
Foreer黑爷7 天前
Spring MVC原理与源码:从请求到响应的全流程解析
java·spring·mvc
曹牧8 天前
Spring MVC中使用HttpServletRequest和HttpServletResponse
java·spring·mvc
曹牧8 天前
Spring MVC配置文件
java·spring·mvc