Spring MVC简介

Spring MVC简介

Java Web发展历程

Java Web应用程序的结构经历了Model IModel II两个时代,从Model I 发展到Model II 是技术发展的必然。

Model I

在早期的Java Web应用开发中,JSP文件即要负责处理业务逻辑和控制程序的运行流程,还要负责数据的显示,即用JSP文件来独立自主地完成系统功能的所有任务。传统的Model I模式,如图所示。
在这里插入图片描述 改进的Model I利用JSP页面与JavaBean组件共同协作来完成系统功能的所有任务,JSP文件负责程序的流程控制逻辑和数据显示逻辑任务,JavaBean负责处理业务逻辑任务。改进的Model I模式,如图所示。
在这里插入图片描述

Model II

Model II模式是基于MVC架构的设计模式。在Model II模式下,利用JSP页面、Servlet和JavaBean组件分工协作共同完成系统功能的所有任务。其中,JSP负责数据显示逻辑任务,Servlet负责程序流程控制逻辑任务,JavaBean负责处理业务逻辑任务。Model II模式,如图所示。
在这里插入图片描述

MVC模式

MVC思想不是哪个语言所特有的设计思想,也并不是Web应用所特有的思想,是一种规范。

MVC思想将一个应用分成三个基本部分:Model(模型)、View(视图)和Controller(控制器),这三个部分以最少的耦合协同工作,从而提高应用的可扩展性和可维护性。MVC设计模式中模型、视图和控制器三者之间的关系,如图所示。
在这里插入图片描述 概括起来,MVC模式具有如下特点

  1. 各司其职、互不干涉。在MVC模式中,3层各司其职,所有如果哪一层的需求发生了变化,就只需要更改相应层中的代码,而不会影响到其他层。

  2. 有利于开发中的分工。在MVC模式中,由于按层把系统分开,就能更好地实现开发中的分工。网页设计人员可以开发JSP页面,对业务熟悉的开发人员可以开发模型中相关业务处理的方法,而其他开发人员可开发控制器,以进行程序控制。

  3. 有利于组件的重用。分层后更有利于组件的重用,如控制层可独立成一个通用的组件,视图层也可做成通用的操作界面。MVC最重要的特点就是把显示和数据分离,这样就增加了各个模块的可重用性。

Spring MVC

Spring MVC是Spring框架中用于Web应用开发的一个模块,是Spring提供的一个基于MVC设计模式的轻量级Web框架。Spring框架提供了构建Web应用程序的全功能MVC模块。Spring MVC框架本质上相当于Servlet,提供了一个DispatcherServlet作为前端控制器来分派请求,同时提供灵活的配置处理程序映射、视图解析、语言环境和主题解析,并支持文件上传。

在MVC设计模式中,Spring MVC作为控制器(Controller)来建立模型与视图的数据交互, 是一个典型的MVC框架,是结构最清晰的MVC Model II实现,如图所示。

在这里插入图片描述
Spring MVC分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让他们更容易进行定制。Spring MVC框架无论是在框架设计还是扩展性、灵活性等方面都全面超越了Struts 2等MVC框架,而且它本身就是Spring框架的一部分,与Spring框架的整合可以说是无缝集成,性能方面具有天生的优越性,Spring MVC具有如下特点:

  1. Spring MVC拥有强大的灵活性、非侵入性和可配置型。
  2. Spring MVC提供了一个前端控制器DispatcherServlet,开发者无须额外开发控制器对象。
  3. Spring MVC分工明确,包括控制器、验证器、命令对象、模型对象、处理程序映射器和视图解析器等,每一个功能实现由一个专门的对象负责。
  4. Spring MVC可以自动绑定用户输入,并正确转换数据类型。
  5. Spring MVC使用一个名称/值的Map对象实现更加灵活的模型数据类型。
  6. Spring MVC内置了常见的校验器,可以检验用户输入,如果校验不同,则重定向回输入表单。输入校验是可选的,并且支持编程方式即声明方式。
  7. Spring MVC支持国际化,支持根据用户区域显式多国语言,并且国际化的配置非常简单。
  8. Spring MVC支持多种视图技术,最常见的有JSP技术以及其他技术,包括Velocity和FreeMarker。
  9. Spring MVC提供了一个简单而强大的JSP标签库,支持数据绑定功能,使得编写JSP页面更加容易。

Spring MVC环境搭建

    <!--junit包单元测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>

    <!-- Spring MVC 及 Spring系列包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.3.24.RELEASE</version>
    </dependency>

   <!--spring-jdbc-->
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>4.3.24.RELEASE</version>
    </dependency>

    <!--数据库驱动包-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>

    <!--SpringMVC需要的前端和Servlet包-->
    <!--servlet-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.0.1</version>
    </dependency>
    
    <!--jsp-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2</version>
    </dependency>
    
    <!--jstl-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

1、2依赖我们在《Spring中IOC思想(2)和依赖注入详解》中讲解IOC思想时导入

3、4依赖我们在讲解《Spring中数据库编程》中讲解Spring数据库编程时导入

如果需要使用AOP的话还需要导入4个依赖,可以在我的博客《Spring中AOP思想》中查阅

5、6、7依赖是使用过Spring MVC时需要导入的,因为Spring MVC框架本质上相当于Servlet,提供了一个DispatcherServlet作为前端控制器来分派请求,所以我们需要导入Servlet的依赖;我们有视图界面,所以需要导入jsp依赖;JSTL(JavaServer Pages Standard Tag Library,JSP标准标签库)是一个不断完善的开放源代码的JSP标签库,所以也需要导入

为了防止资源在导出时候出现问题,我们还需要在pom.xml中的<build>标签中写入

    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.xml</include>
          <include>**/*.properties</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>

至此,Spring MVC的配置完成

代码实现

我们在IDE中创建一个Maven的web项目

我们先需要在web.xml中配置Spring MVC的前端控制器DispatcherServlet,DispatcherServlet是整个Spring MVC框架的核心,他负责接收请求并将其分派给相应的处理器处理

但是在配置DispatcherServlet之前,我们还需要注意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"
         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">
</web-app>

因为约定大于配置的原则,我们可以直接将上面的模板也就是头文件复制到web.xml文件中,在<web-app>中进行DispatcherServlet的配置

  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--初始化参数,配置Spring MVC配置文件的位置及名称-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <!--表示容器在启动时,立即加载dispatcherServlet-->
    <load-on-startup>1</load-on-startup>
  </servlet>

我们配置完成DispatcherServlet后,需要将所有的URL请求拦截下来后映射到前端控制器DispatcherServlet中,只要这样DispatcherServlet才能在后续进行请求的分发,所以我们还需要

  <!--让Spring MVC的前端控制器拦截所有的请求-->
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

注意:上面的代码的位置是在<web-app>标签中

在配置前端控制器时我们使用到了springmvc.xml文件,所以我们还需要创建一个springmvc.xml文件

在这里插入图片描述
我们创建Maven的web项目后,自动生成的目录结构如上图所示,我们需要在webapp目录下分别创建java目录和resources目录,在java目录下创建我们的dao、service、pojo等包,在resources目录下创建配置文件

在resources目录下创建springmvc.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    

</beans>

直接粘贴配置文件的模板,在这个配置文件中,我们使用到了aop、context和mvc,所以要先引入这3样东西的命名空间,这里我将aop、context和mvc的命名空间进行罗列,使用时直接复制粘贴

aop命名空间

xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd

context命名空间

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd

mvc命名空间

xmlns:mvc="http://www.springframework.org/schema/mvc"
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/spring-mvc.xsd

配置文件的格式为

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.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/spring-mvc.xsd
        ">



</beans>

在该配置文件中,我们要做两件事

1.配置处理器映射:我们在将所有的请求拦截下来并映射到DispatcherServlet后,需要DispatcherServlet来将请求分配给处理器进行处理,但是要将请求交给哪个特定的Controller处理?它会咨询一个名为HandlerMapping(处理器映射)的Bean,之后把URL请求指定给一个Controller处理(就像web.xml文件使用<servlet_mapping>将URL映射到相应的Servlet上)

我们可以根据需求来选择处理器映射
Spring提供了多种处理器映射(HanderMapping)支持,例如:

  1. org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
  2. org.springframework.web.servlet.SimpleUrlHandlerMapping
  3. org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
  4. org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

这里我们选择BeanNameUrlHandlerMapping,若没有明确声明任何处理器映射,Spring会默认使用BeanNameUrlHandlerMapping,即在Spring容器中查找与请求URL同名的Bean,处理相应的Controller

2.配置视图解析器:在配置完成处理器映射后我们就需要配置视图解析器,因为处理请求的最后一件事就是解析输出,这个任务由JSP实现,需要确定由哪个视图进行进行请求结果的输出,DispatcherServlet会查找一个视图解析器,将控制器返回的逻辑视图名称转换成渲染结果的实际视图,Spring提供了多种视图解析器,例如:

  1. org.springframework.web.servlet.view.InternalResourceViewResolver
  2. org.springframework.web.servlet.view.ContentNegotiatingViewResolver

3.处理器适配器:在Spring MVC的使用中我们还会使用到处理器适配器,关于处理器适配器的功能,我们后面会讲到。在我们这片博客讲到的例子中,springmvc.xml并没有配置处理器映射和处理器适配器,Spring会使用默认的处理器映射和处理器适配器

在讲解完springmvc.xml中配置的内容后,我们就开始配置,处理器映射和处理器适配器不用配置

我们先需要配置一个和URL同名的Bean

<!--配置一个和URL同名的bean-->
<bean id="/hello" class="com.westos.controller.HelloController"></bean>

接下来配置视图解析器

<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean>

至此springmvc.xml文件完成

在配置和URL同名的bean时我们使用到了一个类HelloController,接下来我们开始创建这个类

这里要讲解遇到的一个问题,在我创建完成Maven的web项目后,我在webapp目录下创建了java目录,在java目录下创建了com目录,在com目录下创建了westos目录,在westos目录下创建了controller目录,在controller创建HelloController文件时出现了问题,我在controller目录上点击右键,在新建的东西中没有Java Class,如下图所示

在这里插入图片描述
通过上网查阅得知是没有对java目录进行标识,我们在java目录上点击右键
在这里插入图片描述在这里插入图片描述
可以看到java目录颜色发生变化
在这里插入图片描述
现在我们在controller目录上点击右键可以看到Java Class
在这里插入图片描述
我们在controller目录下创建类

package com.westos.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 HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        System.out.println("Hello Spring MVC");
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "第一个SpringMVC程序");
        mv.setViewName("/ch06/first.jsp");
        return mv;
    }
}

HelloController类是一个实现Controller接口的控制器,可以处理单一的请求的动作,handleRequest是接口必须实现的方法,该方法必须返回一个ModelAndView对象,这个对象包含视图名或视图名和模型,这样Spring MVC就可以使用视图解析器对模型数据进行解析

本利返回的模型包含一个名为msg的字符串对象,返回的视图路径为/ch06/first.jsp,因此,请求被转发到ch06路径下的first.jsp界面

所以我们需要创建一个first.jsp界面,在webapp目录下创建ch06目录,在ch06目录下一个叫first.jsp的JSP文件,内容为

<%--
  Created by IntelliJ IDEA.
  User: 87257
  Date: 2019/8/20
  Time: 9:41
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>

之后我们还需要进行项目的部署,需要在Tomcat中进行相关的配置
在这里插入图片描述配置完成后启动项目
在这里插入图片描述
可以看到项目正在启动,等待一会儿,自动弹出浏览器窗口

在这里插入图片描述为什么在自动弹出的窗口中显示的内容是Hello World!,因为URL后面还没有具体的请求,所以会默认跳转到index.jsp界面,我们可以查看以下index.jsp文件
在这里插入图片描述index.jsp文件中的内容和界面显示的一致

我们试着请求以下hello
在这里插入图片描述界面上显示的是HelloController类中ModelAndView类的对象mv所包含的字符串对象"第一个SpringMVC程序",我们跳转到first.jsp界面后将mv中的字符串对象进行打印

查看控制台
在这里插入图片描述
控制台输出我们之前定义好的语句

项目测试成功

Spring MVC请求流程

通过前面示例,简单总结Spring MVC的处理流程:

  1. 当用户发送URL请求http://localhost:8081/SpringMVC/hello时,根据web.xml中对于DispatcherServlet的配置,该请求被DispatcherServlet截获,并根据HandlerMapping找到处理相应请求的Controller控制器也就是HelloController
  2. Controller处理完成后,返回ModelAndView对象;
  3. 该ModelAndView对象告诉DispatcherServlet需要通过哪个视图来进行数据模型的展示,DispatcherServlet根据视图解析器把Controller返回的逻辑视图名渲染成真正的视图并输出,呈现给用户。

接下来深入了解Spring MVC框架的请求处理流程,如图所示。

在这里插入图片描述

  1. 用户通过客户端向服务器发起一个request请求,此请求会被前端控制器(DispatcherServlet)所拦截。
  2. 前端控制器请求处理器映射器(HandlerMapping)去查找Handler,可以依据XML配置或注解去查找。
  3. 处理器映射器根据请求URL找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成),并返回给前端控制器。
  4. 前端控制器请求处理器适配器(HandlerAdapter)去执行相应的Handler(常称为Controller)。
  5. 处理器适配器会调用并执行Handler处理器,这里的处理器指的是程序中编写Controller类,也被称之为后端控制器。在填充Handler的入参过程中,根据配置,Spring将帮助做一些额外的工作:1.消息转换、2.数据转换、3.数据格式化、4.数据验证
  6. Controller执行完毕后会返回给处理器适配器一个ModelAndView对象(Spring MVC底层对象),该对象中会包含View视图信息或包含Model数据模型和View视图信息。
  7. 处理器适配器接收到Controller返回的ModelAndView后,将其返回给前端控制器。
  8. 前端控制器接收到ModelAndView后,选择一个合适的视图解析器(ViewReslover)对视图进行解析。
  9. 视图解析器解析后,会根据View视图信息匹配到相应的视图结果,反馈给前端控制器。
  10. 前端控制器收到View具体视图后,进行视图渲染,将模型数据(在ModelAndView对象中)填充到request域。
  11. 前端控制器向用户响应结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值