框架 —— spring MVC

spring MVC

学习网址:
http://c.biancheng.net/spring_mvc/
https://www.w3cschool.cn/spring_mvc_documentation_linesh_translation/

       SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级Web框架(三层架构中web层的框架),属于 Spring FrameWork 的后续产品,已经融合在 Spring Web Flow 里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用 Spring 进行 WEB 开发时,可以选择使用 Spring 的 Spring MVC 框架或集成其他 MVC 开发框架,如 Struts1 (现在一般不用), Struts2 等。
       SpringMVC 已经成为目前最主流的 MVC 框架之一,并且随着 Spring3.0 的发布,全面超越 Struts2, 成为最优秀的 MVC 框架。
       它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时它还支持 RESTful 编程风格的请求。

MVC 是 Model、View 和 Controller 的缩写,分别代表 Web 应用程序(web层)中的 3 种职责。

  • 模型:用于存储数据以及处理用户请求的业务逻辑。
  • 视图:向控制器提交数据,显示模型中的数据。
  • 控制器:根据视图提出的请求判断将请求和数据交给哪个模型处理,将处理后的有关结果交给哪个视图更新显示。

基于 Servlet 的 MVC 模式的具体实现如下。

  • 模型:一个或多个 JavaBean 对象,用于存储数据(实体模型,由 JavaBean 类创建)和处理业务逻辑(业务模型,由一般的 Java 类创建)。
  • 视图:一个或多个 JSP 页面,向控制器提交数据和为模型提供数据显示,JSP 页面主要使用 HTML 标记和 JavaBean 标记来显示数据。
  • 控制器:一个或多个 Servlet 对象,根据视图提交的请求进行控制,即将请求转发给处理业务逻辑的 JavaBean,并将处理结果存放到实体模型 JavaBean 中,输出给视图显示。

MVC中最重要的核心就是控制器,控制器与视图和模型相对独立,它起到一个负责分发请求和返回处理结果的作用,对请求和数据模型的处理一般由JavaBean负责。
在这里插入图片描述
Spring MVC 框架中主要的角色划分:

  • 前端控制器(DispatcherServlet) (核心):接收请求,分发请求到相应的控制器(Controller)进行处理,响应结果。相当于转发器,中央处理器,降低了组件之间的耦合性。

      (1). 不需要进行开发。
      (2). 作用:接受请求,响应结果,相当于一个转发器。
      (3). 减少了其他组件的耦合度。
    
  • 处理器映射( HandlerMapping):根据请求的URL,找到对应的Handler,由 HandlerMapping 定位到控制器,帮助 DispatcherServlet 找到对应的 Controller 以便分发请求。

      (1). 不需要进行开发。
      (2). 作用:根据请求的URL查找Handler。
    
  • 处理器适配器( HandlerAdapter):将各种 Controller 适配成 DispatcherServlet 可以使用的Handler,通过特定规则(HandlerAdapter要求的规则)去执行 Handler。

      (1). 不需要进行开发。
      (2). 作用:按照特定的规则去执行Handler。
    
  • 处理器或页面控制器(Controller / Handler):后端控制器。编写Handler时需要HandlerAdapter的要求去做,这样HandlerAdapter才可以正确执行Handler
    Handler是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet控制下对用户请求进行处理,Handler涉及业务需求,所以需要工程师针对用户需求进行开发,最终返回业务数据

      (1). 需要进行开发。
      (2). 要求:必须要按照HandlerAdapter的要求去编写。
    
  • 视图解析器(ViewResolver):进行视图解析,根据逻辑视图名解析成真正的视图View。

      (1). 不需要进行开发。
      (2). 作用:进行视图解析,根据逻辑视图名解析成真正的视图(View)
    
  • 视图(View ):View是一个接口,实现类支持不同的类型(jsp、html、freemarker、pdf等)

      (1). 需要进行开发。
      (2). 说明:View是一个接口,实现类支持不同的View类型(jsp、freemaker、pdf.........)
    

  • HandlerInterceptor:Handler / Controller 执行前后拦截器。HandlerInterceptor是个接口,里面包含三个方法:preHandle、postHandle、afterCompletion 分别在 Handler 执行前、执行中、执行完成后执行的三个方法。
  • 验证器( Validator)
  • 命令对象(Command请求参数绑定到的对象就叫命令对象)
  • 表单对象(Form Object提供给表单展示和提交到的对象就叫表单对象)。

在这里插入图片描述
从上图可总结出 Spring MVC 的工作流程如下:

  1. 客户端请求提交到 DispatcherServlet。
  2. 由 DispatcherServlet 控制器寻找一个或多个 HandlerMapping,通过 HandlerMapping 找到处理请求的 Controller。
  3. DispatcherServlet 将请求提交到 Controller。
  4. Controller 调用业务逻辑处理后返回 ModelAndView。
  5. DispatcherServlet 寻找一个或多个 ViewResolver 视图解析器,找到 ModelAndView 指定的视图。
  6. 视图负责将结果显示到客户端。

Spring MVC接口:

在上图中包含 4 个 Spring MVC 接口,即 DispatcherServlet、HandlerMapping、Controller 和 ViewResolver。

  • Spring MVC 所有的请求都经过 DispatcherServlet 来统一分发,在 DispatcherServlet 将请求分发给 Controller 之前需要借助 Spring MVC 提供的 HandlerMapping 定位到具体的 Controller。

  • HandlerMapping 接口负责完成客户请求到 Controller 映射。

  • Controller 接口将处理用户请求,这和 Java Servlet 扮演的角色是一致的。一旦 Controller 处理完用户请求,将返回 ModelAndView 对象给 DispatcherServlet 前端控制器,ModelAndView 中包含了模型(Model)和视图(View)。

    从宏观角度考虑,DispatcherServlet 是整个 Web 应用的控制器;从微观考虑,Controller 是单个 Http 请求处理过程中的控制器,而 ModelAndView 是 Http 请求过程中返回的模型(Model)和视图(View)。

  • ViewResolver 接口(视图解析器)在 Web 应用中负责查找 View 对象,从而将相应结果渲染给客户。


导包

Spring MVC 程序所需要的 JAR 包,包括 Spring 的 4 个核心 JAR 包、commons-logging 的 JAR 包;
两个与 Web 相关的 JAR 包(spring-web-3.2.13.RELEASE.jar 和 spring-webmvc-3.2.13. RELEASE.jar);
在 Spring MVC 应用中使用注解时添加 spring-aop-3.2.13.RELEASE.jar 包。
在这里插入图片描述


前端控制器(DispatcherServlet)

DispatcherServlet 其实就是个 Servlet(它继承自HttpServlet基类),需要 web 应用的 web.xml 配置文件下声明。
在这里插入图片描述

前端控制器配置:web.xml

前端控制器在 web.xml 文件中配置

<web-app>
	<!-- 部署 DispatcherServlet -->
    <servlet>
        <servlet-name>example</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 表示容器再启动时立即加载servlet -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>example</servlet-name>
        <!-- 处理所有URL -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

上述 DispatcherServlet 的 servlet 对象 springmvc 初始化时将在应用程序的 WEB-INF 目录下查找一个配置文件,该配置文件的命名规则是“servletName-servlet.xml”,例如 springmvc-servlet.xml。

也可以将 Spring MVC 配置文件存放在应用程序目录中的任何地方,但需要使用 servlet 的 init-param 元素加载配置文件。示例代码如下:

<!-- 部署 DispatcherServlet -->
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <!-- 声明 spring MVC 的配置文件,方便前端控制器访问 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
    <!-- 表示容器再启动时立即加载servlet -->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
后端控制器配置:如 springmvc-servlet.xml

spring MVC 的配置文件(需要在 web.xml 核心配置文件中声明):可以在 WEB-INF 目录下,如上述第一种web.xml配置;也可以是其他任意位置,如上述第二种web.xml配置。

创建名为 springmvc-servlet.xml 的配置文件(spring MVC 自己的配置文件):

<?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">
        
    <!-- 自动扫描的包名 -->  
    <context:component-scan base-package="com.qgl, com.test" ></context:component-scan>  
       
    <!-- 默认开启 spring MVC 注解的支持 -->  
    <mvc:annotation-driven></mvc:annotation-driven>
    
    <!-- 若不使用注解映射(没有上述片段代码的声明),就需要在这里个配置文件中配置控制器类(需要在配置文件中部署映射),如下: -->
    <!-- 控制器类 --> 
    <!-- LoginController控制器类,映射到"/login" -->   
    <bean name="/login" class="controller.LoginController"/>   
    <!-- LoginController控制器类,映射到"/register" -->
    <bean name="/register" class="controller.RegisterController"/>
       
    <!-- 视图解释类 
    	 作用:1、捕获后端控制器的返回值,如"index" 
    	 	  2、解析:在返回值的前后拼接,如"/index.jsp" -->  
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
    	<!-- 前缀 -->
        <property name="prefix" value="/"></property>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"></property><!--可为空,方便实现自已的依据扩展名来选择视图解释类的逻辑  -->  
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>  
    </bean>  
</beans>

在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器称为SpringMVC的三大组件。使用<mvc: annotation-driven>自动加载RequestMappingHandlerMapping (处理映射器)和RequestMappingHandlerAdapter (处理适配器),可用在SpringMVC.xml配置文件中使用<mvc: annotation-driven>替代注解处理器和适配器的配置。


注解

传统风格的控制器不仅需要在配置文件中部署映射,而且只能编写一个处理方法,不够灵活。使用基于注解的控制器具有以下两个优点:

  • 在基于注解的控制器类中可以编写多个处理方法,进而可以处理多个请求(动作),这就允许将相关的操作编写在同一个控制器类中,从而减少控制器类的数量,方便以后的维护。
  • 基于注解的控制器不需要在配置文件中部署映射,仅需要使用 RequestMapping 注释类型注解一个方法进行请求处理。

在 Spring MVC 中最重要的两个注解类型是 Controller 和 RequestMapping。

Controller 注解类型:

@Controller注解表明了一个类是作为控制器的角色而存在的。Spring不要求你去继承任何控制器基类,也不要求你去实现Servlet的那套API。

在 Spring MVC 中使用 org.springframework.stereotype.Controller 注解类型声明某类的实例是一个控制器。

package controller;
import org.springframework.stereotype.Controller;
/**
* “@Controller”表示 IndexController 的实例是一个控制器
*
* @Controller相当于@Controller(@Controller) 或@Controller(value="@Controller")
*/
@Controller
public class IndexController {
    // 处理请求的方法
}

在 Spring MVC 中使用扫描机制找到应用中所有基于注解的控制器类,所以,为了让控制器类被 Spring MVC 框架扫描到,需要在配置文件中声明 spring-context,并使用 <context:component-scan/> 元素指定控制器类的基本包(请确保所有控制器类都在基本包及其子包下)。

 <!-- 使用扫描机制扫描控制器类,控制器类都在controller包及其子包下 -->
    <context:component-scan base-package="controller" />
RequestMapping 注解类型:

在基于注解的控制器类中可以为每个请求编写对应的处理方法。需要使用 org.springframework.web.bind.annotation.RequestMapping 注解类型将请求与处理方法一一对应。

1)方法级别注解:

package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* “@Controller”表示 IndexController 的实例是一个控制器
*
* @Controller相当于@Controller(@Controller) 或@Controller(value="@Controller")
*/
@Controller
public class IndexController {
    @RequestMapping(value = "/index/login")
    // 或 @RequestMapping(path = "/index/login"),path与value一样。
    public String login() {
        /**
         * login代表逻辑视图名称,需要根据Spring MVC配置
         * 文件中internalResourceViewResolver的前缀和后缀找到对应的物理视图
         */
        return "login";
    }
    @RequestMapping(value = "/index/register")
    // 或 @RequestMapping(value = "/index/register"),path与value一样。
    public String register() {
        return "register";
    }
}

上述示例中有两个 RequestMapping 注解语句,它们都作用在处理方法上。注解的 value 属性将请求 URI 映射到方法,value 属性是 RequestMapping 注解的默认属性,如果只有一个 value 属性,则可以省略该属性。

用户可以使用如下 URL 访问 login 方法(请求处理方法),在访问 login 方法之前需要事先在 /WEB-INF/jsp/ 目录下创建 login.jsp。

访问形式:http://localhost:8080/springMVCDemo02/index/login

2)类级别注解:

package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/index")
public class IndexController {
    @RequestMapping("/login")
    public String login() {
        return "login";
    }
    @RequestMapping("/register")
    public String register() {
        return "register";
    }
}

在类级别注解的情况下,控制器类中的所有方法都将映射为类级别的请求。用户可以使用如下 URL 访问 login 方法。

访问形式:http://localhost:8080/springMVCDemo02/index/login

为了方便维护程序,建议开发者采用类级别注解,将相关处理放在同一个控制器类中。例如,对商品的增、删、改、查处理方法都可以放在 GoodsOperate 控制类中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值