首页 > 其他分享 >2. SpringMVC入门案例

2. SpringMVC入门案例

时间:2023-06-28 18:55:42浏览次数:47  
标签:入门 SpringMVC Spring 配置 案例 bean class 加载

1. 入门案例之创建步骤

SpringMVC 的制作过程和上述流程几乎是一致的,具体的实现流程是什么?

1.创建 web 工程(Maven 结构)

2.设置 tomcat 服务器,加载 web 工程(tomcat 插件)

3.导入坐标(SpringMVC+Servlet)

4.定义处理请求的功能类(UserController)

5.设置请求映射(配置映射关系)

6.将 SpringMVC 设定加载到 Tomcat 容器中

因为 SpringMVC 是一个 Web 框架,将来是要替换 Servlet,所以先来回顾下以前 Servlet 是如何进行开发的?

1.创建 web 工程(Maven 结构)

2.设置 tomcat 服务器,加载 web 工程(tomcat 插件)

  • 配置 Tomcat 插件

      <build>
        <plugins>
          <!-- 配置Tomcat插件 -->
          <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
              <port>8080</port>
              <path>/</path>
              <uriEncoding>UTF-8</uriEncoding>
            </configuration>
          </plugin>
        </plugins>
      </build>
    

    3.导入坐标(Servlet)

 <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.10.RELEASE</version>
    </dependency>
  </dependencies>

说明:servlet 的坐标为什么需要添加<scope>provided</scope>​?

  • scope 是 maven 中 jar 包依赖作用范围的描述,
  • 如果不设置默认是compile​ 在在编译、运行、测试时均有效
  • 如果运行有效的话就会和 tomcat 中的 servlet-api 包发生冲突,导致启动报错
  • provided 代表的是该包只在编译和测试的时候用,运行的时候无效直接使用 tomcat 中的,就避免冲突

4.定义处理请求的功能类(UserServlet)

  • 创建配置类

    @Configuration
    @ComponentScan("com.north")
    public class SpringConfig {
    
    }
    
  • 创建 Controller 类

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

    5.设置请求映射(配置映射关系)

  • 使用配置类替换 web.xml ——> 将 web.xml 删除,换成 ServletContainersInitConfig

    public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    
        // 加载SpringMVC配置类
        protected WebApplicationContext createServletApplicationContext() {
            // 初始化WebApplicationContext
            AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
            // 加载指定配置类
            context.register(SpringConfig.class);
            return context;
        }
    
        // 设置由SpringMVC控制器处理的请求映射路径
        @Override
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    
        // 加载Spring配置类
        @Override
        protected WebApplicationContext createRootApplicationContext() {
            return null;
        }
    }
    

    6.将 SpringMVC 设定加载到 Tomcat 容器中

image

注意事项:

  • SpringMVC 是基于 Spring 的,在 pom.xml 只导入了spring-webmvc​jar 包的原因是它会自动依赖 spring 相关坐标

  • AbstractDispatcherServletInitializer 类是 SpringMVC 提供的快速初始化 Web3.0 容器的抽象类

  • AbstractDispatcherServletInitializer 提供了三个接口方法供用户实现

    • createServletApplicationContext 方法,创建 Servlet 容器时,加载 SpringMVC 对应的 bean 并放入 WebApplicationContext 对象范围中,而 WebApplicationContext 的作用范围为 ServletContext 范围,即整个 web 容器范围
    • getServletMappings 方法,设定 SpringMVC 对应的请求映射路径,即 SpringMVC 拦截哪些请求
    • createRootApplicationContext 方法,如果创建 Servlet 容器时需要加载非 SpringMVC 对应的 bean,使用当前方法进行,使用方式和 createServletApplicationContext 相同。
    • createServletApplicationContext 用来加载 SpringMVC 环境
    • createRootApplicationContext 用来加载 Spring 环境

知识点 1:@Controller

名称 @Controller
类型 类注解
位置 SpringMVC 控制器类定义上方
作用 设定 SpringMVC 的核心控制器 bean

知识点 2:@RequestMapping

名称 @RequestMapping
类型 类注解或方法注解
位置 SpringMVC 控制器类或方法定义上方
作用 设置当前控制器方法请求访问路径
相关属性 value(默认),请求访问路径

知识点 3:@ResponseBody

名称 @ResponseBody
类型 类注解或方法注解
位置 SpringMVC 控制器类或方法定义上方
作用 设置当前控制器方法响应内容为当前返回值,无需解析

2. 入门案例总结

  • 一次性工作

    • 创建工程,设置服务器,加载工程
    • 导入坐标
    • 创建 web 容器启动类,加载 SpringMVC 配置,并设置 SpringMVC 请求拦截路径
    • SpringMVC 核心配置类(设置配置类,扫描 controller 包,加载 Controller 控制器 bean)
  • 多次工作

    • 定义处理请求的控制器类
    • 定义处理请求的控制器方法,并配置映射路径(@RequestMapping)与返回 json 数据(@ResponseBody)

3. SpringMVC 工作流程解析

为了更好的使用 SpringMVC,我们将 SpringMVC 的使用过程总共分两个阶段来分析,分别是启动服务器初始化过程​ 和单次请求过程

image

3.1 启动服务器初始化过程

​​image​​

  1. 服务器启动,执行 ServletContainersInitConfig 类,初始化 web 容器

    • 功能类似于以前的 web.xml
  2. 执行 createServletApplicationContext 方法,创建了 WebApplicationContext 对象

    • 该方法加载 SpringMVC 的配置类 SpringMvcConfig 来初始化 SpringMVC 的容器
  3. 加载 SpringMvcConfig 配置类

    image

  4. 执行@ComponentScan 加载对应的 bean

    • 扫描指定包及其子包下所有类上的注解,如 Controller 类上的@Controller 注解
  5. 加载 UserController,每个@RequestMapping 的名称对应一个具体的方法

    image

    • 此时就建立了 /save​ 和 save 方法的对应关系
  6. 执行 getServletMappings 方法,设定 SpringMVC 拦截请求的路径规则

    image

    • /​ 代表所拦截请求的路径规则,只有被拦截后才能交给 SpringMVC 来处理请求

3.2 单次请求过程

  1. 发送请求http://localhost/save

  2. web 容器发现该请求满足 SpringMVC 拦截规则,将请求交给 SpringMVC 处理

  3. 解析请求路径/save

  4. 由/save 匹配执行对应的方法 save()

    • 上面的第五步已经将请求路径和方法建立了对应关系,通过/save 就能找到对应的 save 方法
  5. 执行 save()

  6. 检测到有@ResponseBody 直接将 save()方法的返回值作为响应体返回给请求方

4. bean 加载控制

4.1 问题分析

入门案例的内容已经做完了,在入门案例中我们创建过一个SpringMvcConfig​ 的配置类,再回想前面咱们学习 Spring 的时候也创建过一个配置类SpringConfig​。这两个配置类都需要加载资源,那么它们分别都需要加载哪些内容?

我们先来看下目前我们的项目目录结构:

​​image​​

  • config 目录存入的是配置类,写过的配置类有:

    • ServletContainersInitConfig
    • SpringConfig
    • SpringMvcConfig
    • JdbcConfig
    • MybatisConfig
  • controller 目录存放的是 SpringMVC 的 controller 类

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

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

controller、service 和 dao 这些类都需要被容器管理成 bean 对象,那么到底是该让 SpringMVC 加载还是让 Spring 加载呢?

  • SpringMVC 加载其相关 bean(表现层 bean),也就是 controller 包下的类

  • Spring 控制的 bean

    • 业务 bean(Service)
    • 功能 bean(DataSource,SqlSessionFactoryBean,MapperScannerConfigurer 等)

分析清楚谁该管哪些 bean 以后,接下来要解决的问题是如何让 Spring 和 SpringMVC 分开加载各自的内容。

在 SpringMVC 的配置类SpringMvcConfig​ 中使用注解@ComponentScan​,我们只需要将其扫描范围设置到 controller 即可,如

​​image​​

在 Spring 的配置类SpringConfig​ 中使用注解@ComponentScan​,当时扫描的范围中其实是已经包含了 controller,如:

image

从包结构来看的话,Spring 已经多把 SpringMVC 的 controller 类也给扫描到,所以针对这个问题该如何解决,就是咱们接下来要学习的内容。

概括的描述下咱们现在的问题就是因为功能不同,如何避免 Spring 错误加载到 SpringMVC 的 bean?

4.2 思路分析

针对上面的问题,解决方案也比较简单,就是:

  • 加载 Spring 控制的 bean 的时候排除掉 SpringMVC 控制的 bean

具体该如何排除:

  • 方式一:Spring 加载的 bean 设定扫描范围为精准范围,例如 service 包、dao 包等
  • 方式二:Spring 加载的 bean 设定扫描范围为 com.itheima,排除掉 controller 包中的 bean
  • 方式三:不区分 Spring 与 SpringMVC 的环境,加载到同一个环境中[了解即可]

4.3 设置 bean 加载控制

方式一:修改 Spring 配置类,设定扫描范围为精准范围。

@Configuration
@ComponentScan({"com.itheima.service","comitheima.dao"})
public class SpringConfig {
}

说明:

上述只是通过例子说明可以精确指定让 Spring 扫描对应的包结构,真正在做开发的时候,因为 Dao 最终是交给MapperScannerConfigurer​ 对象来进行扫描处理的,我们只需要将其扫描到 service 包即可。

方式二:修改 Spring 配置类,设定扫描范围为 com.itheima,排除掉 controller 包中的 bean

@Configuration
@ComponentScan(value="com.itheima",
    [email protected](
    	type = FilterType.ANNOTATION,
        classes = Controller.class
    )
)
public class SpringConfig {
}
  • excludeFilters 属性:设置扫描加载 bean 时,排除的过滤规则

  • type 属性:设置排除规则,当前使用按照 bean 定义时的注解类型进行排除

    • ANNOTATION:按照注解排除
    • ASSIGNABLE_TYPE:按照指定的类型过滤
    • ASPECTJ:按照 Aspectj 表达式排除,基本上不会用
    • REGEX:按照正则表达式排除
    • CUSTOM:按照自定义规则排除

    大家只需要知道第一种 ANNOTATION 即可

  • classes 属性:设置排除的具体注解类,当前设置排除@Controller 定义的 bean

如何测试 controller 类已经被排除掉了?

public class App{
	public static void main (String[] args){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        System.out.println(ctx.getBean(UserController.class));
    }
}

如果被排除了,该方法执行就会报 bean 未被定义的错误

image

注意:测试的时候,需要把 SpringMvcConfig 配置类上的@ComponentScan 注解注释掉,否则不会报错

出现问题的原因是,

  • Spring 配置类扫描的包是com.itheima
  • SpringMVC 的配置类,SpringMvcConfig​ 上有一个@Configuration 注解,也会被 Spring 扫描到
  • SpringMvcConfig 上又有一个@ComponentScan,把 controller 类又给扫描进来了
  • 所以如果不把@ComponentScan 注释掉,Spring 配置类将 Controller 排除,但是因为扫描到 SpringMVC 的配置类,又将其加载回来,演示的效果就出不来
  • 解决方案,也简单,把 SpringMVC 的配置类移出 Spring 配置类的扫描范围即可。

最后一个问题,有了 Spring 的配置类,要想在 tomcat 服务器启动将其加载,我们需要修改 ServletContainersInitConfig

public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    protected WebApplicationContext createRootApplicationContext() {
      AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringConfig.class);
        return ctx;
    }
}

对于上述的配置方式,Spring 还提供了一种更简单的配置方式,可以不用再去创建AnnotationConfigWebApplicationContext​ 对象,不用手动register​ 对应的配置类,如何实现?

public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

知识点 1:@ComponentScan

名称 @ComponentScan
类型 类注解
位置 类定义上方
作用 设置 spring 配置类扫描路径,用于加载使用注解格式定义的 bean
相关属性 excludeFilters:排除扫描路径中加载的 bean,需要指定类别(type)和具体项(classes)
includeFilters:加载指定的 bean,需要指定类别(type)和具体项(classes)

标签:入门,SpringMVC,Spring,配置,案例,bean,class,加载
From: https://www.cnblogs.com/NorthPoet/p/17512301.html

相关文章

  • angular入门
    程序设计原则:1、YAGNI:YouAre'tGonnaNeedIt(不写不需要的代码)2、DRY:Don'tRepeatYourself(不要cv自己的代码)3、OCP:OpenClosePrinciple(开闭原则:对扩展开放、对修改封闭)4、LowCoupling,HighCohesion(高内聚低耦合)5、DimeterLaw(迪米特法则,也称为"最少知识法则")一个对象/......
  • api接口接入淘宝/天猫平台采集添加到购物车数据调用演示案例
    ​淘宝添加到购物车API接口的作用是向淘宝购物车中添加指定的商品,实现用户将商品加入购物车的功能。通过该API接口,用户可以将商品加入购物车,方便后续进行结算和购买。使用淘宝添加到购物车API接口,可以帮助开发者和商家进行以下操作:购物车管理:允许用户将商品添加到购物车并进行......
  • api接口接入淘宝/天猫平台获取商品销量详情调用演示案例
    ​淘宝商品销量详情接口的作用是获取淘宝平台上某一商品的销售情况信息,包括商品的总销量、近期销量、销售趋势等。通过该接口,可以获取到商品销量的原始数据,用于分析商品的受欢迎程度和市场需求。使用淘宝商品销量详情接口,可以帮助商家和开发者进行以下操作:市场分析:通过获取商......
  • 【服务器数据恢复】ext3文件系统下raid5热备盘同步失败导致阵列崩溃的数据恢复案例
    服务器数据恢复环境:两组分别由4块SAS硬盘组建的raid5磁盘阵列,ext3文件系统,通过LVM管理磁盘存储。服务器故障:一组raid5磁盘阵列中的1块硬盘故障离线,热备盘成功启用并开始同步数据,在同步还没有完成的情况下该组raid5阵列中的另外一块硬盘故障掉线,该组Raid5阵列崩溃,LVM结构损坏,文件......
  • Spring Boot:快速入门教程
      来源  https://www.cnblogs.com/xifengxiaoma/p/11019240.html  SpringBoot:快速入门教程......
  • git 入门、reset的3种模式、回滚文件、还原文件、变基、merge
    git基础知识盗用网上的一张图,git有工作目录、索引区(也叫暂存区)、历史区,这3个区,一定要记在脑子里,基本上git所有的操作都是操作这3个区。新建一个文件并提交的一般操作是,新建文件gitadd到索引区gitcommit到历史区(添加-a参数会自动提交到索引区,相当于第2步+第3步)gitreset有3种......
  • ROS入门
    背景知识工作空间指的是包含了ROS2应用包的文件夹。在使用ROS2之前,需要在你将要进行工作的终端上,source你安装了ROS2的工作空间。这使得ROS2的应用包可以在所打开的终端上使用。你还有一个选择是source一个上层工作空间,也就是第二工作空间。第二工作空间指的是你添加了一些新......
  • C++入门
    c++入门--变量与基本类型如果你还没有接触过编程,想先体验一下编程的乐趣。请看我的c++入门(1)--输入输出,代码运行顺序及其控制。此文开始学习变量以及基本类型。原始内置类型(PrimitiveBuild-inTypes)两类:算术类型(arithmetictypes)和void。我们主要讲解算术类型。算术类型(Arithmetic......
  • 新手怎么投资黄金?黄金投资入门知识
    黄金作为市场上热门的投资产品,受到不少新手投资者的青睐。但是在实际交易过程中,还是应该先从黄金投资入门知识学起,真正了解市场之后再正式开始投资。黄金投资入门知识一、投资品种黄金从投资品种方面一共可以分为实物黄金、纸黄金、黄金基金、杠杆黄金四种,这四种之间都是会有区别的......
  • 【Flutter专题】Android Flutter入门笔记、技术解析与项目实战
    Flutter是一个跨平台、高性能的移动UI框架,其采用Dart语言开发,并使用自己的渲染引擎来绘制UI,保证了自身的高性能,保证了在Android和iOS上UI的一致性。目前Flutter已经支持iOS、Android、Web、Windows、macOS、Linux、Fuchsia(Google新的自研操作系统)等众多平台。与其他跨平......