1.MVC概述

MVC(Model View Controller)是一种软件设计的框架模式,它采用模型(Model)-视图(View)-控制器(controller)的方法把业务逻辑、数据与界面显示分离。把众多的业务逻辑聚集到一个部件里面。

通俗地讲:MVC的理念就是把数据处理、数据展示(界面)和程序/用户的交互三者分离开的一种编程模式。

MVC不是设计模式!MVC框架模式是一种复合模式。

1.1 MVC的三个核心部件分别是:

  1. Model(模型):所有的用户数据、状态以及程序逻辑,独立于视图和控制器
  2. View(视图):呈现模型,类似于Web程序中的界面,视图会从模型中拿到需要展现的状态以及数据,对于相同的数据可以有多种不同的显示形式(视图)
  3. Controller(控制器):负责获取用户的输入信息,进行解析并反馈给模型,通常情况下一个视图具有一个控制器

1.2 使用MVC的优点

程序通过将M(Model)和V(View)的代码分离,实现了前后端代码的分离,会带来几个好处

  1. 可以使同一个程序使用不同的表现形式,如果控制器反馈给模型的数据发生了变化,那么模型将及时通知有关的视图,视图会对应的刷新自己所展现的内容
  2. 因为模型是独立于视图的,所以模型可复用,模型可以独立的移植到别的地方继续使用
  3. 前后端的代码分离,使项目开发的分工更加明确,程序的测试更加简便,提高开发效率
    其实控制器的功能类似于一个中转站,会决定调用那个模型去处理用户请求以及调用哪个视图去呈现给用户

1.3 JavaWeb中MVC模式的应用

举个例子:

V:View视图,Web程序中指用户可以看到的并可以与之进行数据交互的界面,比如一个Html网页界面,或者某些客户端的界面,在前面讲过,MVC可以为程序处理很多不同的视图,用户在视图中进行输出数据以及一系列操作,注意:视图中不会发生数据的处理操作。
M:Model模型:进行所有数据的处理工作,模型返回的数据是中立的,和数据格式无关,一个模型可以为多个视图来提供数据,所以模型的代码重复性比较低
C:Controller控制器:负责接受用户的输入,并且调用模型和视图去完成用户的需求,控制器不会输出也不会做出任何处理,只会接受请求并调用模型构件去处理用户的请求,然后在确定用哪个视图去显示返回的数据

1.4 Web程序中MVC模式的优点

  1. 耦合性低:视图(页面)和业务层(数据处理)分离,一个应用的业务流程或者业务规则的改变只需要改动MVC中的模型即可,不会影响到控制器与视图
  2. 部署快,成本低:MVC使开发和维护用户接口的技术含量降低。使用MVC模式使开发时间得到相当大的缩减,它使程序员(Java开发人员)集中精力于业务逻辑,界面程序员(HTML和JSP开发人员)集中精力于表现形式上
  3. 可维护性高:分离视图层和业务逻辑层也使得WEB应用更易于维护和修改

1.5 Web程序中MVC模式的缺点

  1. 调试困难:因为模型和视图要严格的分离,这样也给调试应用程序带来了一定的困难,每个构件在使用之前都需要经过彻底的测试
  2. 不适合小型,中等规模的应用程序:在一个中小型的应用程序中,强制性的使用MVC进行开发,往往会花费大量时间,并且不能体现MVC的优势,同时会使开发变得繁琐
  3. 增加系统结构和实现的复杂性:对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率
  4. 视图与控制器间的过于紧密的连接并且降低了视图对模型数据的访问:视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能

2. Spring MVC框架

现在MVC框架已经有很多了,Struts、Webwork,新兴的MVC框架有Spring MVC、JSF等等

Struts1.0是基于webwork的MVC框架,里面有很多类的继承关系,耦合性太高,之后推出了struts2.0,但是这个MVC框架对于视图的解析还是存在一些小的不妥之处,所以产生了Spring MVC

2.1 Spring MVC简介及特点

  • Spring MVC采用了松散耦合的可插拔组件结构,比其他的MVC框架更具有灵活性和扩展性,
  • Spring MVC通过使用一套注解,使一个Java类成为前端控制器(Controller),不需要实现任何接口
  • Spring MVC支持RES形式的URL请求
  • Spring MVC在在数据绑定、视图解析、本地化处理及静态资源处理上都有许多不俗的表现。
  • Spring MVC围绕DispatcherServlet(前端控制器)为中心展开,DispatcherServlet(前端控制器)是Spring MVC的中枢,和MVC的思想一样,它负责从视图获取用户请求并且分派给相应的处理器处理,并决定用哪个视图去把数据呈现给给用户

2.2 Spring MVC 请求响应

SpringMVC把视图渲染、请求处理、模型创建分离了,遵循了MVC框架模式的思想


SpringMVC的请求相应要经过七个阶段,蓝色的方框是Spring框架已经实现好的,第二阶段到第六阶段对应着Spring MVC中的一些核心理念,分别是前端控制器、处理映射器、控制器(处理器)、视图解析器、视图。

前端控制器和控制器的区别:

  • 前端控制器负责任务分发,
  • 控制器是模型的一部分,负责业务和数据的处理

2.3 SpringMVC核心控制类的请求流程


详解:


3. Spring MVC入门案例(一)

3.1 .配置环境

3.1.1 导包

(5+1)+2

Spring -context :5+1

Spring -web,spring-webmvc: 2

导入依赖的时候只用导入Spring-web一个就可以

但是编译的时候还需要servlet-api包,所以也需要导入

注意:还要在application.xml中添加war

3.1.2 web.xml配置前端控制器, 加载spring-web容器

  1. 配置前端控制器
  2. 配置url-pattern

3.1.3 Springmvc.xml 配置Springmvc依赖的bean

  1. 配置处理器映射器 handlerMapping
  2. 配置处理器适配器 HandlerAdater

3.2 Handler代码(Controller)

类需要继承Controller

注册组件:

4. 入门案例(二) MVC注解驱动

4.1 配置环境

配置映射器和适配器在为:

<mvc:annotation-driver/>

4.2 使 用

  1. 直接在类上添加@Controller注解.则该类为Handler类
  2. 通过@RequestMapping将请求url和应用中的方法建立映射关系


5. RequestMapping 详解

  • URl路径映射
  • 窄化请求映射
  • 请求方法限定

5.1 URl路径映射

5.2 窄化请求映射

在Handle类上添加 @RequsestMapping("") 进行请求的窄化

5.3 请求方法的限定(405)

通过@requestMapping中的method属性机型请求方法的限定

5.3.1RequestMapping延申出的注解--@GetMapping

5.4 请求参数的限定(400)

@ResquestMapping中Params属性

5.5 请求的Content-type 的限定(415)

@RequestMapping中consumes 属性

5.6 请求Accept的限定(406)

@RequestMapping 的produces 属性

6 .Controller对应方法的返回值(处理ModelAndView的时候)

6.1 Void

在形参中可以增加HttpServletRequest和HttpServletResponse


6.2 ModelAndView

ModelAndView 设置他的viewName(视图名)

6.3 String

返回字符串可以指视图名(viewName),通过视图解析器解析为物理视图地址。

处理的还是ModelAndView

  • 物理视图名
  • 逻辑视图名

6.3.1 物理视图名

把请求的最后一层删掉,然后将返回的字符串和请求拼接就是我们要访问的地址

6.3.2 逻辑视图名

做的是viewName的拼接

在页面注册其注入两个参数

注意的点:如果新增了逻辑视图的配置,原先物理视图的返回值和modelAndView中的viewName需要调整

6.3.3 返回字符串--转发/重定向

forward redirect

对应的是请求之间的转发和重定向,也就是RequestMapping所对应方法之间的跳转

7. 请求参数的封装

7.1 Requset(不推荐)

7.2 直接对参数进行封装

7.3 通过javabean进行封装


7.4 嵌套javabean

7.5 数组参数的接收

7.5.1 直接接收

7.5.2通过作为javabean的成员变量

7.6 List

7.7 字符编码(中文乱码)

7.8 日期类型转换---转换器

接收

配置过程

7.9 Fileupload 文件上传

7.9.1 导包

commons-io ,commons-fileUpload


7.9.2 请求

MultipartFile通过transferTo方法存储到我们的文件上

7.9.3 组件的注册


8. 其他常见注解

8.1 @PathVariable

将URI请求模板中的变量映射到处理方法参数上

eg: @RequestMapping(value = "/{id}", method = RequestMethod.GET)
      public String toUpdate(@PathVariable("id") Integer id, Model model) {
      
      }

8.2 @RequestParam

@RequestParam:将请求参数绑定到你控制器的方法参数上(是springmvc中接收普通参数的注解)
语法:@RequestParam(value=”参数名”,required=”true/false”,defaultValue=””)

  • value:参数名
  • required:是否包含该参数,默认为true,表示该请求路径中必须包含该参数,如果不包含就报错。
  • defaultValue:默认参数值,如果设置了该值,required=true将失效,自动为false,如果没有传该参数,就使用默认值

8.3 @ConfigurationProperties加载外部配置

@Configuration //配置类注解,被自动扫描发现

@PropertySource("classpath:application.yml") //指明配置源文件位置

@ConfigurationProperties("environment") //指明前缀

8.4 @Valid / @Validated区别及使用

限制

说明

@Null

限制只能为null

@NotNull

限制必须不为null

@AssertFalse

限制必须为false

@AssertTrue

限制必须为true

@DecimalMax(value)

限制必须为一个不大于指定值的数字

@DecimalMin(value)

限制必须为一个不小于指定值的数字

@Digits(integer,fraction)

限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction

@Future

限制必须是一个将来的日期

@Max(value)

限制必须为一个不大于指定值的数字,和Dcimal相比,Max只能限制long最大值以下的,DcimalMax可以验证bigDecimal

@Min(value)

限制必须为一个不小于指定值的数字

@Past

限制必须是一个过去的日期

@Pattern(value)

限制必须符合指定的正则表达式,例如:@Pattern(regexp = "[1]+\.mr$")

@Size(max,min)

限制字符长度必须在min到max之间,注意:限定的不是数字

@Past

验证注解的元素值(日期类型)比当前时间早

@NotEmpty

验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)

@NotBlank

验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格

@Email

验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

@NotNull、@NotEmpty、@NotBlank的区别:

  • @NotEmpty 用在集合上面(不能注释枚举):String类,Collection、Map、数组,是不能为null或者长度为0的(String、Collection、Map的isEmpth()方法)
  • @NotBlank用在String上面:纯空格的String也是不符合规则的
  • @NotNull用在所有类型上面

8.4.1 基本概念

@Valid是使用Hibernate validation的时候使用,需要导入hibernate-validator 依赖

@Validated是只用Spring Validator校验机制使用

8.4.2 注解位置:

@Validated:用在类型、方法和方法参数上。但不能用于成员属性(field)

@Valid:可以用在方法、构造函数、方法参数和成员属性(field)上

8.4.3 分组校验:

@Validated:提供分组功能,可以在参数验证时,根据不同的分组采用不同的验证机制(例如:id在新增的时候不需要传入,在修改和删除的时候必须传入,不可为空)

@Valid:没有分组功能

说明

  1. 不分 配groups,默认每次都要进行验证
  2. 对一个参数需要多种验证方式时,也可通过分配不同的组达到目的。

8.4.4 组序列:

一个组可定一切未其他组的序列,使用该组验证时,会按照序列规定的顺序验证,如果前面的验证失败后,后面的组无需在验证

举例:如果年龄验证失败,之后的验证都不会再进行

8.4.5 嵌套验证

一个pojo类中包含其他需要验证的对象(可以为类,也可以时嵌套类的集合),将该类加上注解@Valid即可

举例:

9. springmvc的工作流程

SpringMvc有两种处理模型数据的方式:

  1. 将方法的返回值设置为ModelAndView
  2. 方法的返回值还是String类型,在方法中的入参中传入Map,Model或者ModelMap

无论处理器方法的 返回值是什么SpringMVC都会转换成一个ModelAndView对象

  1. 中央控制器在web.xml中配置的dispatherServlet拦截情节,调用对应的处理器来处理
  2. 视图解析器是我们自己配置的视图解析器

  1. \S ↩︎