SSM框架的学习与应用(Spring + Spring MVC + MyBatis)-Java EE企业级应用开发学习记录(第十一天)初识SpringMVC
今天我们要来学习一下SSM框架的最后一个框架SpringMVC
一、初认SpringMVC
基本概念:
Spring MVC(Model-View-Controller)是一个用于构建Java Web应用程序的开源框架,它提供了一种基于MVC架构的方式来开发Web应用。
SpringMVC是Spring Framework的一部分,它是一种基于模型-视图-控制器(MVC)设计模式的Web框架。它的主要目标是将应用程序的各个部分(模型、视图和控制器)分离开来,以提高代码的可维护性和可测试性。SpringMVC提供了一个结构良好的方式来处理HTTP请求和响应,同时支持灵活的配置和扩展。
在这篇博客中,我们将初步了解Spring MVC的核心概念和基本用法。
Java EE三层架构
我们前几天经常提及的系统经典的三层架构模式:
- 表现层(Controller层):也被称为视图层,负责接受客户端请求,并向客户端响应结果。
- 业务层(Service层):也成为服务层,负责处理业务逻辑,与项目需求相关。
- 持久层(Dao层):负责数据的持久化和访问数据库进行增删改查。
那么SpringMVC在三层架构中是作用于哪层呢?
从该图也可以看出SpringMVC作用于三层架构中的表现层,用于接收客户端请求并进行响应。
SpringMVC的作用流程
Spring MVC中包含了控制器
和视图
,控制器
接收到客户端的请求后对请求数据进行解析和封装,接着将请求交给业务层
处理。业务层
会对请求进行处理,最后将处理结果返回给表现层
。表现层
接收到业务层
的处理结果后,再由视图
对处理结果进行渲染,渲染完成后响应给客户端。
SpringMVC的优点
- 是Spring框架的后续产品,可以方便地使用Spring框架所提供的其他功能。
- 使用简单,很容易设计出干净简洁的Web层。
- 支持各种请求资源的映射策略。
- 具有非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API。
- 支持国际化,可以根据用户区域显示多国语言。
- 支持多种视图技术,它支持JSP、Velocity和FreeMarker等视图技术。
- 灵活性强,易扩展。
SpringMVC的核心组件
- DispatcherServlet(派发器Servlet):DispatcherServlet是SpringMVC的前端控制器,它接收所有的HTTP请求并将请求路由到适当的控制器处理程序。
- Controller(控制器):控制器处理程序是SpringMVC应用程序的核心部分,它负责处理HTTP请求并返回适当的响应。控制器通常是POJO(普通Java对象)类,使用
@Controller
注解进行标记。 - Model(模型):模型表示应用程序的数据。它可以是一个普通的Java对象(POJO),也可以是一个包含业务逻辑的组件。
- View(视图):视图负责呈现模型数据并生成响应。SpringMVC支持多种视图技术,包括JSP、Thymeleaf、FreeMarker等。
SpringMVC的基本工作原理流程如下:
- 客户端发送HTTP请求到DispatcherServlet。
- DispatcherServlet根据请求映射信息将请求路由到适当的控制器处理程序。
- 控制器处理程序处理请求,执行相应的业务逻辑,并返回一个模型(Model)。
- DispatcherServlet选择一个视图(View)来呈现模型数据。
- 视图将模型数据呈现为HTML、JSON或其他响应格式,并将其返回给客户端。
- 客户端接收并渲染视图。
这里我们后面会使用实例来帮助理解这个流程。
二、新建SpringMVC入门程序
这里我们选择使用昨天的项目来做今天的实验,有去下载我昨天的项目资源的读者应该就会发现我的pom中引入了很多的依赖,其实是一个全栈项目的所有依赖,所以会比较多,依赖的引入也是非常重要的,不同版本的依赖之间可能会有冲突,所以需要我们掌握,查看报错并且根据报错修改的能力,跟debug原理是一样的。
使用Maven创建JavaWeb项目
①我们可以选择新建一个Java Web项目又或者在昨天的基础上添加一个webapp文件夹(请按照下图流程进行操作)
这里要进行一下修改,修改webapp文件夹的地址还有告诉程序Web资源的目录在哪
按照下面流程去进行新增artifact
然后点击Apply即可,到此我们的webapp就新建完成了
整体项目架构如下:
②引入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>org.example</groupId>
<artifactId>samTest</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 设置打包类型为 WAR -->
<packaging>war</packaging>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- Tomcat7插件 -->
<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>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>GBK</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- AOP 依赖 -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- AspectJ 依赖,用于AspectJ方式的AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.9</version>
</dependency>
<!-- DBCP数据库连接池依赖 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- 连接池依赖 -->
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.6</version>
</dependency>
<!-- Hamcrest测试框架依赖 -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3</version>
</dependency>
<!-- JavaEE API依赖 -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<!-- JSTL标签库依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- JUnit测试框架依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- Log4j日志框架依赖 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- MyBatis ORM框架依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.2</version>
</dependency>
<!-- MyBatis Spring整合依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- MySQL连接驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!-- Spring AOP依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- Spring Aspects依赖,为AspectJ整合 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- Spring Bean依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- Spring Context依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- Spring Core依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- Spring Expression Language依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- Spring JDBC依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- Spring TX依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- Spring MVC依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- Spring MVC依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
</dependencies>
</project>
PS:这里引入的maven的插件,还引入了tomcat插件,设置了项目打包方式为war,这样才可以被maven识别,并且使得我们可以使用maven方式直接运行Java Web应用。跟项目部署在Tomcat服务器是一样的效果。
接下来要去进行设置才可以使用插件运行Maven项目,单击IDEA工具栏中的“Run”→“Edit Configurations…”选项,弹出Run/Debug Configurations对话框。
②配置前端控制器,在web.xml文件中进行SpringMVC前端控制器的配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--设置default.jsp为首页欢迎页面-->
<welcome-file-list>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
这里稍微解释一下代码吧:
以上代码的简单说明: welcome-file-lis****表示首页欢迎页面
在上述代码中,我们配置了一个名为“springmvc”的Servlet。该Servlet是Dispatcher Servlet类型,它就是Spring MVC的入口(前面介绍过SpringMVC的本质就是一个Servlet),并通过“<load-on-startup>
1</load-on-startup>
”配置标记容器在启动的时候就加载此Dispatcher Servlet,即自动启动。然后通过servlet-mapping映射到“/”,即Dispatcher Servlet需要截获并处理该项目的所有URL请求。
在配置Dispatcher Servlet的时候,通过设置context Config Location参数来指定Spring MVC配置文件的位置,此处使用Spring资源路径的方式进行指定(classpath:springmvc-servlet.xml,下一步将创建这个文件)。
如下图,这里会爆红就因为我们还没有创建SpringMVC的配置文件:spring-mvc.xml,我这里图片是我还未修改的版本,记得自行修改即可
③在resource资源文件夹下创建spring-mvc.xml,配置处理器映射信息和视图解析器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--这段配置会自动扫描指定包中的类,查找带有 Spring 注解(如 @Controller、@Service、@Repository 等)的类,并将它们注册为 Spring Bean。-->
<context:component-scan base-package="controller"/>
<!--配置 Spring MVC,以便启用注解驱动的控制器和处理器映射。当启用此配置时,Spring MVC 将识别和处理与请求映射相关的注解,例如 @RequestMapping,并自动配置一些默认的行为,如请求参数绑定和视图解析等。-->
<mvc:annotation-driven/>
<!-- 完成视图的对应 -->
<!-- 对转向页面的路径解析。prefix:前缀, suffix:后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
如下图:这里爆红是因为我们还没有创建controller包,创建了controller包记得要修改这个配置扫描的包的路径,比如我的就是com.steveDash.controller
④创建controller包,新建我们的控制处理器UserController,用于处理客户端请求并指定响应跳转的页面。
package com.steveDash.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
//设置当前方法的访问映射地址
@RequestMapping("/hello")
//设置当前方法返回值类型为String,用于指定请求完成后跳转的页面
public String sayHello(){
System.out.println("欢迎访问UserController");
return "success";
}
}
这里我们在JavaBean的章节就已经说过了,@Controller标注出这是个Controller层的Bean
要是有疑惑的,可以去看看前面几篇文章。
⑤创建视图View页面,在webapp/WEB-INF/下创建pages文件夹,然后再创建success.jsp文件
为什么要是这个路径呢?因为我们在spring-mvc中已经设置好了路径,要是自己有修改的话,那就记得保持俩个路径一致即可
然后创建success.jsp页面代码如下
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2023/9/12
Time: 23:53
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>SteveDash</title>
</head>
<body>
<h1>你好呀,SteveDash的读者们</h1>
</body>
</html>
⑥启动项目,测试应用:使用插件运行maven项目了
如下图:一般出现这个就是说明正常启动了,我们需要去网页输入http://localhost:8080/hello
这里的http://localhost:8080/是我们自己设定好的Tomcat默认主页地址,8080是我们pom中对tomcat设置好的端口号,后面的hello是我们UserController中设定好的访问地址
return success就是接收到这个http://localhost:8080/hello页面请求,返回success.jsp,为什么会自动拼接.jsp呢?
因为我们在spring-mvc.xml中设置好了,识别好了跳转页面路径,所以上面返回的拼接完成就是
webapp/WEB-INF/pages/success
.jsp
三、Spring MVC工作原理详解
在我们前面已经粗略的讲解了一下流程,又编写了一个简单的实例来帮助我们理解SpringMVC。
现在回过头我们再来详细理解一下SpringMVC的工作原理和执行流程
可能会有疑惑,到底是怎么根据请求来找到对应的控制器呢?
这里要引入这几个组件
- 处理器映射器(Handler Mapping):它的主要任务是根据客户端的请求,找到并映射到对应的控制器。处理器映射器负责决定哪个控制器(Controller)应该处理特定的请求。它根据请求的URL、请求方法、请求参数等条件,将请求映射到合适的控制器处理方法上。可以把它理解成一个Map<URL,Controller>,根据用户请求的URL找到对应的控制器。
- 处理适配器(Handler Adapter):处理适配器的作用是将请求分派给具体的控制器方法,并负责适配不同类型的处理器(例如,控制器类或注解控制器方法)。处理适配器根据控制器的类型和方法签名来调用相应的控制器方法。执行实际的控制器方法,负责处理请求参数、方法调用和响应返回。
- 视图解析器(View Resolver):视图解析器用于解析控制器方法返回的逻辑视图名称,将其转换为实际的视图对象。视图解析器决定了如何呈现模型数据,通常是将数据填充到模板(如JSP、Thymeleaf、FreeMarker等)中,生成最终的HTML响应。说人话就是将控制器方法返回的视图逻辑名称解析为实际的视图对象。它使您能够将逻辑视图名称映射到物理视图(如JSP文件)。向我们上面解释的一样
所以这三个的关系就是:
这三个组件在Spring MVC中的关系如下:
处理器映射器和处理适配器一起工作,将请求路由到合适的控制器和方法上。控制器方法执行业务逻辑,然后返回一个逻辑视图名称。视图解析器接收逻辑视图名称,将其解析为一个具体的视图对象。最终,视图对象使用模型数据(由控制器方法提供)生成响应,这个响应通常是HTML页面。
这三个组件协作,实现了Spring MVC的核心功能,即将请求路由到控制器、执行业务逻辑、生成视图响应。这种松散耦合和关注点分离的设计使得Spring MVC非常灵活和可扩展。
Spring MVC执行流程
这个图源自网络,可以把处理器看成controller,这样就可以理解了。
SpringMVC详细的执行流程如下:
- 客户端发起请求:流程的起始点是客户端发起HTTP请求,通常是在浏览器中输入URL或点击页面链接。
- DispatcherServlet接收请求:请求首先到达Spring MVC的前端控制器,即DispatcherServlet(派发器Servlet)。
- 处理器映射器(Handler Mapping):DispatcherServlet 使用处理器映射器(Handler Mapping)来确定请求应该由哪个控制器处理。处理器映射器将请求URL映射到具体的处理器(Controller)。
- 处理器适配器(Handler Adapter):一旦确定了处理器,DispatcherServlet 使用处理器适配器(Handler Adapter)来调用选定的处理器(Controller)。处理器适配器负责执行控制器的方法,并传递请求的参数。
- 控制器处理请求:控制器是真正执行业务逻辑的地方。控制器方法处理请求,执行相应的操作,通常包括数据处理、业务逻辑、数据库访问等。
- 模型数据准备:在控制器方法中,可以准备模型数据,这些数据将在视图中呈现。模型数据通常被封装在一个Model对象中,并通过方法参数传递给视图。
- 视图解析器(View Resolver):一旦控制器处理完请求并准备好模型数据,DispatcherServlet 使用视图解析器(View Resolver)来确定使用哪个视图来呈现响应。视图解析器将逻辑视图名称映射到具体的视图模板。
- 视图渲染:选定了视图后,视图负责将模型数据渲染到最终的HTML或其他格式中,以生成响应内容。
- 响应返回给客户端:DispatcherServlet 将视图生成的响应返回给客户端,通常是浏览器。
- 请求处理结束:流程结束,客户端收到响应,请求处理完成。
PS:这里讲解的是SpringMVC4.0以后版本的执行流程。
总结
今天我们对SpringMVC的基础知识做了整体的了解,也明白了SpringMVC的概念,也编写了SpringMVC的入门程序,通过这个实例对SpringMVC的工作原理,执行流程进行了详细的讲解。MVC三层架构的作用,它们之间是怎么互相协调的。还学习了部署项目的俩种方式,本地Tomcat运行,或者使用插件运行Maven项目。通过今天的学习,希望各位读者可以对SpringMVC有个大致的了解,为框架开发打下坚实基础。
想要跟着学习的可以去我的资源里面找对应的文件下载,我的md文件也会发上去,项目文件会上传可以自己跟着学习一下。
作者:Stevedash
发表于:2023年9月13日 3点32分