spring mvc原理深度解析(一)

回顾servlet 与jsp 执行过程

在这里插入图片描述
流程说明:
1.请求Servlet
2.处理业务逻辑
3.设置业务Model
4.forward jsp Servlet
5. jsp Servlet 解析封装html 返回

spring mvc请求处理流程

在这里插入图片描述

spring mvc功能特性

spring mvc本质上还是使用Servlet处理,并在其基础上进行了封装简化了开发流程,提高易用性、并使用程序逻辑结构变得更清晰
a.基于注解的URL映谢
b.表单参数映射
c.缓存处理
d.全局统一异常处理
e.拦截器的实现
f.下载处理

spring mvc案例

第一步:引入spring mvc依赖

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

第二步:创建web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         id="WebApp_ID" version="3.0">
  <display-name>springMVC</display-name>
  <!-- 部署 DispatcherServlet -->
  <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>
    <!-- 表示容器再启动时立即加载servlet -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!-- 处理所有URL -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

第三步:创建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">

    <bean name="/hello.do" class="com.yemuxia.mvc01.controller.SimpleController"/>

</beans>

第四步:创建SimpleController类

package com.yemuxia.mvc01.controller;



import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class SimpleController implements Controller {
    
    

    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    
        ModelAndView mv = new ModelAndView("/WEB-INF/page/userView.jsp");
        mv.addObject("name","hhh");
        return mv;
    }
}

第五步:创建userView.jsp文件

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
</head>
<body>
测试
${name}
</body>
</html>

在这里插入图片描述
在这里插入图片描述

spring mvc体系结构

spring mvc解决了什么问题

  • URL映射
  • 表单参数映射
  • 调用目标Controller
  • 数据模型映射
  • 视图解析
  • 异常处理

HandlerMapping url与控制器的映谢
HandlerAdapter 控制器执行适配器
ViewResolver 视图仓库
view 具体解析视图
HandlerExceptionResolver 异常捕捕捉器
HandlerInterceptor 拦截器

spring mvc各组件执行流程

在这里插入图片描述

HandlerMapping

HandlerMapping作用是通过url找到对应的Handler ,但其HandlerMapping.getHandler()方法并不会直接返回Handler 对像,而是返回 HandlerExecutionChain 对像再通过 HandlerExecutionChain.getHandler() 返回最终的handler
在这里插入图片描述

实现类

在这里插入图片描述
1.SimpleUrlHandlerMapping:基于手动配置 url 与control 映谢
2.BeanNameUrlHandlerMapping: 基于ioc name 中以 “/” 开头的Bean时行 注册至映射.
3.RequestMappingHandlerMapping:基于@RequestMapping注解配置对应映射

上述案例基于第二种。
在这里插入图片描述

基于SimpleUrlHandlerMapping配置映射

案例

在这里插入图片描述
在这里插入图片描述

SimpleUrlHandlerMapping体系结构

在这里插入图片描述

初始化(容器启动时调用)

在这里插入图片描述
在这里插入图片描述

org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#setUrlMap
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#initApplicationContext
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#registerHandlers
// /表示根路径 /* 表示默认路径
org.springframework.web.servlet.handler.AbstractUrlHandlerMapping#registerHandler()

获取 Handler流程关键源码

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

org.springframework.web.servlet.DispatcherServlet#doService
org.springframework.web.servlet.DispatcherServlet#doDispatch
org.springframework.web.servlet.DispatcherServlet#getHandler
org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
org.springframework.web.servlet.handler.AbstractUrlHandlerMapping#getHandlerInternal
// 获取URL路径
org.springframework.web.util.UrlPathHelper#getPathWithinApplication
// 查找handler
org.springframework.web.servlet.handler.AbstractUrlHandlerMapping#lookupHandler
// 封装执行链
org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandlerExecutionChain

BeanNameUrlHandlerMapping体系结构

在这里插入图片描述
BeanNameUrlHandlerMapping 实现上与 SimpleUrlHandlerMapping 一致,唯一区别在于继承自AbstractDetectingUrlHandlerMapping ,通过对应detectHandlers 可以在无配置的情况下发现url 与handler 映射。

RequestMappingHandlerMapping体系结构

最常用 基于注解。
在这里插入图片描述

Handler

对应的类型如下
在这里插入图片描述

  • Controller 接口:
  • HttpRequestHandler 接口:
  • HttpServlet 接口:
  • @RequestMapping方法注解

在这里插入图片描述

可以看出 Handler 没有统一的接口,当dispatchServlet获取当对应的Handler之后如何调用呢?调用其哪个方法?这里有两种解决办法,一是用instanceof 判断Handler 类型然后调用相关方法 。二是通过引入适配器实现,每个适配器实现对指定Handler的调用。spring 采用后者。

HandlerAdapter详解

这里spring mvc 采用适配器模式来适配调用指定Handler,根据Handler的不同种类采用不同的Adapter,其Handler与 HandlerAdapter 对应关系如下

Handler类别 对应适配器 描述
Controller SimpleControllerHandlerAdapter 标准控制器,返回ModelAndView
HttpRequestHandler HttpRequestHandlerAdapter 业务自行处理请求,不需要通过modelAndView 转到视图
Servlet SimpleServletHandlerAdapter 基于标准的servlet 处理
HandlerMethod RequestMappingHandlerAdapter 基于@requestMapping对应方法处理

在这里插入图片描述

基于Servlet 处理

案例

package com.yemuxia.mvc01.controller;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class SimpleServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        resp.getWriter().println("wo shi ge hao ren");
    }
}

在这里插入图片描述

在这里插入图片描述

ViewResolver 与View 详解

找到对应的Adapter 之后就会基于适配器调用业务处理,处理完之后业务方会返回一个ModelAndView ,在去查找对应的视图进行处理。其在org.springframework.web.servlet.DispatcherServlet#resolveViewName() 中遍历 viewResolvers 列表查找,如果找不到就会报一个 Could not resolve view with name 异常。
在这里插入图片描述

基于BeanNameViewResolver

案例

添加自定义视图

package com.yemuxia.mvc01.controller;

import org.springframework.web.servlet.View;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * 自定义的视图解析器
 */
public class MyView implements View {
    
    
    @Override
    public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    
        response.getWriter().println("hello dajia shi ge hao ren");
    }

    @Override
    public String getContentType() {
    
    
        return null;
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/yemuxiaweiliang/article/details/120258164