👏作者简介:大家好,我是笙一X,java大二练习生,喜欢算法和Java相关知识。
📕正进行的系列:算法 、JUC从入门到成神、Spring
关于SpringMVC
SpringMVC 用于开发 Web 应用,是目前主流的实现MVC设计模式的框架,我们需要深入了解它的工作流程。
SpringMVC工作流程
我们可以通过一张图来了解SpringMVC的大概工作流程
先对其中这些组件进行解释:
① DispatcherServlet:由SpringMVC提供的前端控制器,配置web.xml使其生效。用于接收请求、响应结果,它是整个流程处理的核心。
② HandlerMapping:由SpringMVC提供的处理器映射器,进行IoC配置生效。内部缓存了handler(controller方法)和它对应的访问路径,用于根据请求的 URL 来查找 对应的Handler。
③ HandlerAdapter:由SpringMVC提供的处理器适配器,进行IoC配置生效。当 DispatcherServlet 从HandlerMapping中查询到所需的Handler后,由它去通知Handler执行对应的请求,并且接收Handler传回的信息(如:ModeAndView)。它具体实现两个优化:1.简化参数处理,将原始获得的request参数转化为Handler内方法所需要的参数。2.数据响应,将Handler返回的数据提交给DispatcherServlet。起到了转化器的作用。
④ Handler:我们自己定义的 Controller 类的内部方法,接收参数,调用业务,响应结果。
⑤ ViewResovler:SpringMVC提供的视图解析器,进行IoC配置生效。用于简化视图页面查找操作,将解析的视图返回给DispatcherServelt。注意:视图解析器并不一定是必须的。如果只要求返回JSON数据而不要页面,就不需要视图解析器。
⑥ 视图:DispatchServlet根据视图解析器解析的视图结果,调用具体的视图,进行视图渲染。
最后我们从头到尾梳理一遍SpringMVC的工作流程。
1.首先,从用户发送请求给 DispatcherServlet。
2.DispatcherServlet 在接收到请求后,根据请求的URL在HandlerMapping中找到其缓存的Handler。
3.查询到Handler后,返回给DispatcherServlet。
4.DispatcherServlet 将得到的request对象传递给 HandlerAdapter。
5.HandlerAdapter 处理request,转化为Handler所需的参数后传递给Handler。
6.Handler 进行具体业务后,将结果(ModeAndView)返回给HandlerAdapter。
7.HandlerAdapter 再将结果返回给DispatcherServlet。
8.如果有需要返回的页面,DispatcherServlet 会将 ModelAndView 中的逻辑视图名称和模型数据传递给ViewResovler。
9.ViewResovler 将根据逻辑视图名称和模型数据解析出实际的视图对象,返回给DispatcherServlet。
10.DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图,进行视图渲染。
11.最终,生成响应内容,并将其发送给客户端用户。注意:如果没有视图,直接返回JSON数据。
使用SpringMVC-验证
项目要转成maven/web程序
pom中导入
<properties>
<spring.version>6.0.6</spring.version>
<servlet.api>9.1.0</servlet.api>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- springioc相关依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- web相关依赖 -->
<!-- 在 pom.xml 中引入 Jakarta EE Web API 的依赖 -->
<!--
在 Spring Web MVC 6 中,Servlet API 迁移到了 Jakarta EE API,因此在配置 DispatcherServlet 时需要使用
Jakarta EE 提供的相应类库和命名空间。错误信息 “‘org.springframework.web.servlet.DispatcherServlet’
is not assignable to ‘javax.servlet.Servlet,jakarta.servlet.Servlet’” 表明你使用了旧版本的
Servlet API,没有更新到 Jakarta EE 规范。
-->
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-web-api</artifactId>
<version>${servlet.api}</version>
<scope>provided</scope>
</dependency>
<!-- springwebmvc相关依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
Controller类
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@RequestMapping("springmvc/hello") // 到handlerMapping中注册
@ResponseBody // 直接返回字符串给前端,不要找视图解析器
public String hello() {
System.out.println("HelloController.hello");
return "hello springmvc";
}
}
配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
@Configuration
@ComponentScan("com.sheng1.controller")
public class MvcConfig {
@Bean
public RequestMappingHandlerMapping handlerMapping() {
return new RequestMappingHandlerMapping();
}
@Bean
public RequestMappingHandlerAdapter handlerAdapter() {
return new RequestMappingHandlerAdapter();
}
}
SpringMVC环境搭建(替代web.xml声明servlet的过程)
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/**
* 可以被web项目加载,会初始化ioc容器,会设置dispatcherServlet的地址
*/
public class SpringMvcInit extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
// 设置项目对应的配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{MvcConfig.class};
}
// 配置springmvc内部自带的servlet访问地址
// “/” : 此处处理了所有请求
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
如果用web.xml的方式如何做呢?(了解)
<?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">
<servlet>
<servlet-name>ds</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ds</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
部署项目(Tomcat)
运行后访问