SpringMVC执行流程有哪些

发布时间:2021-08-05 16:39:39 作者:Leah
来源:亿速云 阅读:124

SpringMVC执行流程有哪些,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

MVC总结

1. 概述

还是之前的三个套路

1.1 是什么?

Spring提供一套视图层的处理框架,他基于Servlet实现,可以通过XML或者注解进行我们需要的配置。

他提供了拦截器,文件上传,CORS等服务。

1.2 为什么用?

原生Servlet在大型项目中需要进过多重封装,来避免代码冗余,其次由于不同接口需要的参数不同,我们需要自己在Servlet层 封装我们需要的参数,这对于开发者来说是一种重复且枯燥的工作,于是出现了视图层框架,为我们进行参数封装等功能。让开发者的注意力全部放在逻辑架构中,不需要考虑参数封装等问题。

1.3 怎么用

再聊怎么用之前,我们需要了解一下MVC的工作原理。

他基于一个DispatcherServlet类实现对各种请求的转发,即前端的所有请求都会来到这个Servlet中,然后这个类进行参数封装和请求转发,执行具体的逻辑。(第二章我们细聊)

1.3.1 XML

下面来看一个完整的web.xml配置

<web-app>

    <servlet>
    <servlet-name>dispatchServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatchServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>
1.3.2 注解

注解方式也是现在主流,SpringBoot基于JavaConfig实现了自动配置

实现方式:

Servlet3.0的时候定义了一个规范SPI规范。

SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。也就是在服务启动的时候会Servlet会自动加载该文件定义的类

SpringMVC执行流程有哪些

我们看一眼这个文件里的内容。他内部定义了SpringServletContainerInitializer容器初始化类,也就是说在Servlet启动的时候会自动初始化这个类,这个类也是注解实现的关键。

这个类中存在一个onStartup方法,这个也是当容器初始化的时候调用的方法,这个方法有两参数

org.springframework.web.SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
    @Override
	public void onStartup(Set<class<?>&gt; webAppInitializerClasses, 		
 ServletContext servletContext)    throws ServletException {
        //启动逻辑
    }
}

具体看一下注解配置方式:

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletCxt) {

        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        //一个配置类,@Configuration
        ac.register(AppConfig.class);
        //spring的那个refresh方法
        ac.refresh();

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app/*");
    }
}

通过实现WebApplicationInitializer接口,来作为MVC的配置类,在加载SpringServletContainerInitializer的时候加载这个类。


不过在具体的实现中,Spring不建议我们这样做,他建议将SpringSpringMvc分开,看个图

SpringMVC执行流程有哪些

他在Spring之上加了一层Web环境配置。相当于在Spring的外面包装了一层Servlet

看一下此时的代码

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
	
    //Spring配置文件
    @Override
    protected Class<!--?-->[] getRootConfigClasses() {
        return new Class<!--?-->[] { RootConfig.class };
    }

    //SpringMVC的配置文件
    @Override
    protected Class<!--?-->[] getServletConfigClasses() {
        return new Class<!--?-->[] { App1Config.class };
    }
	
    //指定DispatcherServlet可以拦截的路径
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/app1/*" };
    }
}

通过AbstractAnnotationConfigDispatcherServletInitializer

SpringMVC执行流程有哪些

可以看到他实现了WebApplicationInitializer接口,即在Servlet初始化的时候会加载这个类。

AbstractContextLoaderInitializer类,他初始化了Spring

AbstractDispatcherServletInitializer类,初始化了DispatcherServlet

AbstractAnnotationConfigDispatcherServletInitializer类,将两个类整合到一起

2. 实现原理

聊这个原理之前,先来聊聊他要干什么?

需求:请求分发;参数封装;结果返回

那如果我们自己来实现,该怎么办?(单说注解,先来看看我们怎么使用MVC)

@Controller
public class UserController {

    @GetMapping("/test")
    @ResponseBody
    public String test01(){
        return "success" ;

    }
}

接下来,我们通过我们已有的东西,看一下我们自己去处理请求的逻辑

先来想一下我们的请求过程:

2.1 Spring加载

在上面的怎么用中提到了,他通过AbstractContextLoaderInitializer来加载Spring配置文件的。

SpringMVC执行流程有哪些

此时关于Spring的东西已经加载好了,但并未进行初始化

2.2 MVC加载

同样也是通过AbstractDispatcherServletInitializer类实现

SpringMVC执行流程有哪些

2.2.1 DispatcherServlet

接下来我们具体看一下在这个期间,DispatcherServlet如何处理请求的

作用:分发所有的请求

类继承结构图

SpringMVC执行流程有哪些

可以看到他继承了HttpServlet类,属于一个Servlet,而在之前我们配置了这个Servlet的拦截路径。他会将所有的请求拦截,然后做一个分发。

下面这个图各位看官应该非常熟悉:

SpringMVC执行流程有哪些

其实DispatcherServlet处理所有请求的方式在这个图里完全都体现了。

接下来聊一下他的设计思路吧。

当一个请求来的时候,进入doDispatch方法中,然后处理这个请求,也是返回一个执行链

Spring提供了三种方式的处理器映射器来处理不同的请求。

@Component("/test02")
public class HttpController  implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("HttpController执行");
        return null;
    }
}
@Component("/test01")
public class HandlerController implements HttpRequestHandler {

    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("handlerRequest");
    }
}
@Controller
public class UserController {

    @GetMapping("/test")
    public String test01(){
        System.out.println("执行了");
        return "success" ;
    }
}
@Configuration
@ComponentScan("com.bywlstudio.controller")
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/pages/",".jsp");
    }

    @Bean
    public RouterFunction<!--?--> routerFunctionA() {
        return RouterFunctions.route()
                .GET("/person/{id}", request1 -&gt; ServerResponse.ok().body("Hello World"))
                .build();
    }

}

聊完了处理器映射器,再来聊一下处理器适配器

不同的请求方式,需要不同的处理方式,这也是Spring为什么要提供一个适配器的原因。

通过处理器适配器拿到适合的处理器,来处理对应的请求。

在处理器执行具体的请求的过程,实际上就是调用我们的方法的过程,于是就会出现返回值

通常对于返回值我们有两种方法:

对于返回值解析,MVC提供了一个接口用于处理所有的返回值,这里我们仅仅谈上面的两种

在我们拿到方法返回值以后,会调用this.returnValueHandlers.handleReturnValue返回值解析器的这个方法,用于对视图模型的返回和JSON数据的回显(直接回显到网页,此时返回的视图对象为null

对于视图对象,通过视图解析器直接解析,进行数据模型渲染,然后回显给前端。

2.2.2 MappingRegistry

这个类存放了method的映射信息。

class MappingRegistry {

   private final Map<t, mappingregistration<t>&gt; registry = new HashMap&lt;&gt;();

   private final Map<t, handlermethod> mappingLookup = new LinkedHashMap&lt;&gt;();

   private final MultiValueMap<string, t> urlLookup = new LinkedMultiValueMap&lt;&gt;();

   private final Map<string, list<handlermethod>&gt; nameLookup = new ConcurrentHashMap&lt;&gt;();

   private final Map<handlermethod, corsconfiguration> corsLookup = new ConcurrentHashMap&lt;&gt;();

   private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

MVC会从这个类中获取方法和URL的引用。相当于Spring MVC的容器。

3. 面试题

3.1 什么是MVC?什么是MVVM?

答:MVC是一个架构模式,它有三个核心

MVVM也是一种架构模式,它也是三个核心

它的核心思想是:通过ViewModel将数据和视图绑定,用数据操作视图,常见框架为Vue

3.2 Spring Mvc执行流程

关于SpringMVC执行流程有哪些问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

推荐阅读:
  1. SpringMVC常用注解有哪些
  2. SpringMVC的执行流程

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

springmvc

上一篇:prometheus 中怎么实现微服务指标监控

下一篇:如何解决某些HTML字符打不出来的问题

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》