Spring MVC 是 Spring 给我们提供的⼀个⽤于简化 Web 开发的框架
2.1 SpringMVC简介
2.1.1 MVC体系结构
三层架构
我们的开发架构⼀般都是基于两种形式,⼀种是 C/S 架构,也就是客户端/服务器;另⼀种是 B/S 架构
,也就是浏览器服务器。在 JavaEE 开发中,⼏乎全都是基于 B/S 架构的开发。那么在 B/S 架构中,系
统标准的三层架构包括:表现层、业务层、持久层。三层架构解释:
- 表现层:也就是我们常说的web 层。它负责接收客户端请求,向客户端响应结果,通常客户端使⽤http 协议请求web 层,web 需要接收 http 请求,完成 http 响应。
- 业务层:也就是我们常说的 service 层。它负责业务逻辑处理,和我们开发项⽬的需求息息相关。web 层依赖业务层,但是业务层不依赖 web 层。
- 持久层:也就是我们是常说的 dao 层。负责数据持久化,包括数据层即数据库和数据访问层,数据库是对数据进⾏持久化的载体,数据访问层是业务层和持久层交互的接⼝,业务层需要通过数据访问层将数据持久化到数据库中。通俗的讲,持久层就是和数据库交互,对数据库表进⾏增删改查的。
2.1.2 MVC是什么
- SpringMVC 全名叫 Spring Web MVC,是⼀种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级Web 框架,属于 SpringFrameWork 的后续产品。Spring MVC 本质可以认为是对servlet的封装,简化了我们serlvet的开发
- 作⽤:1)接收处理前端的http请求 2)返回响应,跳转⻚⾯
- MVC和原生Servlet的区别
-
2.2 MVC的主要工作流程
开发过程:
配置DispatcherServlet前端控制器
- 开发处理具体业务逻辑的Handler(@Controller、@RequestMapping)
- xml配置⽂件配置controller扫描,配置springmvc三⼤件
- 将xml⽂件路径告诉springmvc(DispatcherServlet)
流程说明:
- 第一步:⽤户发送请求⾄前端控制器DispatcherServlet
- 第⼆步:DispatcherServlet收到请求调⽤HandlerMapping处理器映射器
- 第三步:处理器映射器根据请求Url找到具体的Handler(后端控制器),⽣成处理器对象及处理器拦截器(如果 有则⽣成)⼀并返回DispatcherServlet
- 第四步:DispatcherServlet调⽤HandlerAdapter处理器适配器去调⽤Handler
- 第五步:处理器适配器执⾏Handler
- 第六步:Handler执⾏完成给处理器适配器返回ModelAndView
- 第七步:处理器适配器向前端控制器返回 ModelAndView,ModelAndView 是SpringMVC 框架的⼀个底层对 象,包括 Model 和 View
- 第⼋步:前端控制器请求视图解析器去进⾏视图解析,根据逻辑视图名来解析真正的视图。
- 第九步:视图解析器向前端控制器返回View
- 第⼗步:前端控制器进⾏视图渲染,就是将模型数据(在 ModelAndView 对象中)填充到 request 域
-
2.3 MVC的九大组件
HandlerMapping(处理器映射器):HandlerMapping 是⽤来查找 Handler 的,也就是处理器,具体的表现形式可以是类,也可以是⽅法。⽐如,标注了@RequestMapping的每个⽅法都可以看成是⼀个Handler。Handler负责具体实际的请求处理,在请求到达后,HandlerMapping 的作⽤便是找到请求相应的处理器Handler 和 Interceptor。存储了url和handler的映射关系。
- HandlerAdapter(处理器适配器):HandlerAdapter 是⼀个适配器。因为 Spring MVC 中 Handler 可以是任意形式的,只要能处理请求即可。但是把请求交给 Servlet 的时候,由于 Servlet 的⽅法结构都是doService(HttpServletRequest req,HttpServletResponse resp)形式的,要让固定的 Servlet 处理⽅法调⽤ Handler 来进⾏处理,便是 HandlerAdapter 的职责。
- ViewResolver(视图解析器):⽤于将String类型的视图名和Locale解析为View类型的视图,只有⼀个resolveViewName()⽅法。从⽅法的定义可以看出,Controller层返回的String类型视图名viewName 最终会在这⾥被解析成为View。View是⽤来渲染⻚⾯的,也就是说,它会将程序返回的参数和数据填⼊模板中,⽣成html⽂件。ViewResolver 在这个过程主要完成两件事情:ViewResolver 找到渲染所⽤的模板(第⼀件⼤事)和所⽤的技术(第⼆件⼤事,其实也就是找到视图的类型,如JSP)并填⼊参数。默认情况下,Spring MVC会⾃动为我们配置⼀个InternalResourceViewResolver,是针对 JSP 类型视图的。
- HandlerExceptionResolver:HandlerExceptionResolver ⽤于处理 Handler 产⽣的异常情况。它的作⽤是根据异常设置ModelAndView,之后交给渲染⽅法进⾏渲染,渲染⽅法会将 ModelAndView 渲染成⻚⾯。
- RequestToViewNameTranslator:RequestToViewNameTranslator 组件的作⽤是从请求中获取 ViewName.因为 ViewResolver 根据ViewName 查找 View,但有的 Handler 处理完成之后,没有设置 View,也没有设置 ViewName,便要通过这个组件从请求中查找 ViewName。
- LocaleResolver:ViewResolver 组件的 resolveViewName ⽅法需要两个参数,⼀个是视图名,⼀个是 Locale。LocaleResolver ⽤于从请求中解析出 Locale,⽐如中国 Locale 是 zh-CN,⽤来表示⼀个区域。这个组件也是 i18n 的基础。
- ThemeResolver:ThemeResolver 组件是⽤来解析主题的。主题是样式、图⽚及它们所形成的显示效果的集合。Spring MVC 中⼀套主题对应⼀个 properties⽂件,⾥⾯存放着与当前主题相关的所有资源,如图⽚、CSS样式等。创建主题⾮常简单,只需准备好资源,然后新建⼀个“主题名.properties”并将资源设置进去,放在classpath下,之后便可以在⻚⾯中使⽤了。SpringMVC中与主题相关的类有ThemeResolver、ThemeSource和Theme。ThemeResolver负责从请求中解析出主题名,ThemeSource根据主题名找到具体的主题,其抽象也就是Theme,可以通过Theme来获取主题和具体的资源。
- MultipartResolver:MultipartResolver ⽤于上传请求,通过将普通的请求包装成MultipartHttpServletRequest 来实现。MultipartHttpServletRequest 可以通过 getFile() ⽅法 直接获得⽂件。如果上传多个⽂件,还可以调⽤ getFileMap()⽅法得到Map
这样的结构,MultipartResolver 的作⽤就是封装普通的请求,使其拥有⽂件上传的功能。 FlashMapManager:FlashMap ⽤于重定向时的参数传递,⽐如在处理⽤户订单时候,为了避免重复提交,可以处理完post请求之后重定向到⼀个get请求,这个get请求可以⽤来显示订单详情之类的信息。这样做虽然可以规避⽤户重新提交订单的问题,但是在这个⻚⾯上要显示订单的信息,这些数据从哪⾥来获得呢?因为重定向时么有传递参数这⼀功能的,如果不想把参数写进URL(不推荐),那么就可以通过FlashMap来传递。只需要在重定向之前将要传递的数据写⼊请求(可以通过ServletRequestAttributes.getRequest()⽅法获得)的属性OUTPUT_FLASH_MAP_ATTRIBUTE中,这样在重定向之后的Handler中Spring就会⾃动将其设置到Model中,在显示订单信息的⻚⾯上就可以直接从Model中获取数据。FlashMapManager 就是⽤来管理 FalshMap 的。
2.4 MVC的数据输出机制
```java @Controller @RequestMapping(“test”) public class TestController{
public String test1(ModelMap modelMap) {
modelMap.addAttribute("test","1");
return "success";
}
public String test1(Modle model) {
model.addAttribute("test","1");
return "success";
}
public String test1(Map
map) { map.put("test","1");
return "success";
}
}
1. Spring MVC在handler的方法中传入ModelMap、Model、Map参数,并向这些参数中保存数据,实际是保存到了请求域当中,都可以在页面获取得到。
2. 这三个参数运行时的具体类型都是BindingAwareModelMap,相当于给BindingAwareModelMap中保存数据都会放在请求域中。
3. 三个参数的关系
- Map是jdk的接口,Model是Spring的接口
- ModelMap实现了Map接口
- BindingAwareModelMap继承了ExtendedMap,ExtendMap继承了ModelMap,实现了Model接口
- 所以这三个参数底层都是一样的
<a name="ShMUg"></a>
# 2.5 请求参数绑定
<a name="SSYNl"></a>
## 2.5.1 参数绑定介绍
1. 原生Servlet的参数传递:http请求传输一个整型参数,原生servlet来接收
- String ageStr = request.getParameter("age");
- int age = Integer.parseInt(ageStr);
2. Spring MVC是对Servlet的封装,所以简化了很多Servlet的操作,其中 也包括了接收参数。
3. Spring MVC接收一个整型参数直接在Hanlder的方法中声明形参即可。
```java
@RequestMapping("xxx")
public String handle(Integer age) {
System.out.println(age);
}
-
2.5.2 参数绑定详情
默认⽀持 Servlet API 作为⽅法参数:当需要使⽤HttpServletRequest、HttpServletResponse、HttpSession等原⽣servlet对象时,直接在handler⽅法中形参声明使⽤即可。
@RequestMapping("/handle01")
public ModelAndView handle01(HttpServletRequest request,
HttpServletResponse response,HttpSession session) {
String id = request.getParameter("id");
Date date = new Date();
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("date",date);
modelAndView.setViewName("success");
return modelAndView;
}
绑定简单数据类型参数(八种基本类型及其包装类型),只需要直接声明形参即可(形参参数名和传递的参数名要保持⼀致,建议 使⽤包装类型,当形参参数名和传递参数名不⼀致时可以使⽤@RequestParam注解进⾏⼿动映射)
@RequestMapping("/handle02")
public ModelAndView handle02(@RequestParam("ids") Integer id,Boolean
flag) {
Date date = new Date();
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("date",date);
modelAndView.setViewName("success");
return modelAndView;
}
绑定Pojo类型参数:接收pojo类型参数,直接形参声明即可,类型就是Pojo的类型,形参名⽆所谓。但是要求传递的参数名必须和Pojo的属性名保持⼀致。
2.6 Restful风格请求支持
什么是Restful:
- Restful 是⼀种 web 软件架构⻛格,它不是标准也不是协议,它倡导的是⼀个资源定位及资源操作的⻛格。
- 它本身并没有什么实⽤性,其核⼼价值在于如何设计出符合 REST ⻛格的⽹络接⼝。
- Restful 的优点:
- 它结构清晰、符合标准、易于理解、扩展⽅便,所以正得到越来越多⽹站的采⽤。
- RESTful 的示例:
- get 查询,获取资源
- post 增加,新建资源
- put 更新
- delete 删除资源
- rest⻛格带来的直观体现:就是传递参数⽅式的变化,参数可以在uri中了
示例:/account/1 HTTP GET :得到 id = 1 的 account
/account/1 HTTP DELETE:删除 id = 1 的 account
/account/1 HTTP PUT:更新 id = 1 的 account2.7 AJAX json交互
- 交互:
- 前端到后台:前端ajax发送json格式字符串,后台直接接收为pojo参数,使⽤注解@RequstBody
- 后台到前端:后台直接返回pojo对象,前端直接接收为json对象或者字符串,使⽤注解@ResponseBody
- 什么是 Json:
- Json是⼀种与语⾔⽆关的数据交互格式,就是⼀种字符串,只是⽤特殊符号{}内表示对象、[]内表示数
组、””内是属性或值、:表示后者是前者的值
- {“name”: “Michael”}可以理解为是⼀个包含name为Michael的对象
- [{“name”: “Michael”},{“name”: “Jerry”}]就表示包含两个对象的数组
- spring mvc和Json的交互
- 所需jar包
```xml
com.fasterxml.jackson.core jackson-core 2.9.0
- 示例代码:
- 前端jsp⻚⾯及js代码
```html
<div>
<h2>Ajax json交互</h2>
<fieldset>
<input type="button" id="ajaxBtn" value="ajax提交"/>
</fieldset>
</div>
$(function () {
$("#ajaxBtn").bind("click",function () {
// 发送ajax请求
$.ajax({
url: '/demo/handle07',
type: 'POST',
data: '{"id":"1","name":"李四"}',
contentType: 'application/json;charset=utf-8',
dataType: 'json',
success: function (data) {
alert(data.name);
}
})
})
})
- 后台Handler⽅法
@RequestMapping("/handle07")
@ResponseBody
// 添加@ResponseBody之后,不再⾛视图解析器那个流程,⽽是等同于response直接输出
// 数据
public User handle07(@RequestBody User user) {
// 业务逻辑处理,修改name为张三丰
user.setName("张三丰");
return user;
}