一.基础概念
1.什么是 MVC
- MVC 是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。
- 是将业务逻辑、数据、显示分离的方法来组织代码。
- MVC 主要作用是降低了视图与业务逻辑间的双向偶合。
- MVC 不是一种设计模式,MVC 是一种架构模式。当然不同的 MVC 存在差异。
Model(模型)
:数据模型,提供要展示的数据,因此包含数据和行为. 一个或多个 JavaBean 对象,用于存储数据(实体模型,由 JavaBean 类创建)和处理业务逻辑(业务模型,由一般的 Java 类创建)。
View(视图)
:负责进行模型的展示,一个或多个 JSP 页面,向控制器提交数据和为模型提供数据显示,JSP 页面主要使用 HTML 标记和 JavaBean 标记来显示数据
Controller(控制器)
:接收用户请求,委托给模型进行处理. 一个或多个 Servlet 对象,根据视图提交的请求进行控制,即将请求转发给处理业务逻辑的 JavaBean,并将处理结果存放到实体模型 JavaBean 中,输出给视图显示
最典型的 MVC 就是JSP + servlet + javabean
的模式。
2.Spring MVC 的特点
- 轻量级,简单易学
- 高效 , 基于请求响应的 MVC 框架
- 与 Spring 兼容性好,无缝结合
- 约定优于配置
- 功能强大:RESTful、数据验证、格式化、本地化、主题等
- 简洁灵活
Spring 的 web 框架围绕DispatcherServlet [ 调度 Servlet ] 设计。
DispatcherServlet 的作用是将请求分发到不同的处理器。从 Spring 2.5 开始,使用 Java 5 或者以上版本的用户可以采用基于注解形式进行开发,十分简洁;
正因为 SpringMVC 好 , 简单 , 便捷 , 易学 , 天生和 Spring 无缝集成(使用 SpringIoC 和 Aop) , 使用约定优于配置 .
能够进行简单的 junit 测试 . 支持 Restful 风格 .异常处理 , 本地化 , 国际化 , 数据验证 , 类型转换 , 拦截器 等等
3.SpringMVC 流程
从图可总结出 Spring MVC 的工作流程如下:
- 客户端请求提交到
DispatcherServlet
。 - 由
DispatcherServlet
控制器寻找一个或多个HandlerMapping
,找到处理请求的Controller
。 DispatcherServlet
将请求提交到Controller
。controller
调用模型,处理业务后返回一个ModelAndView
。DispatcherServlet
得到controller
的处理结果。DispatcherServlet
调用视图解析器(ViewResolver
) 来解析HandlerAdapter
传递的逻辑视图名。- 视图解析器将解析的逻辑视图名传回给
DispatcherServlet
DispatcherServlet
根据视图解析器的视图结果,调用具体的视图, 并最终结果返回给浏览器
4.SpringMVC 组件说明
在 springmvc 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 springmvc 的三大组件。
以下组件通常使用框架提供实现:
-
DispatcherServlet
:前端控制器 用户请求到达前端控制器,它就相当于 mvc 模式中的 c,dispatcherServlet
是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet
的存在降低了组件之间的耦合性。 -
Handler
:处理器 Handler 是继DispatcherServlet
前端控制器的后端控制器,在DispatcherServlet
的控制下Handler
对具体的用户请求进行处理。 由于Handler
涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler
。 -
HandlerMapping
:处理器映射器HandlerMapping
负责根据用户请求 url 找到 Handler 即处理器,springmvc 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。 -
HandlAdapter
:处理器适配器 通过HandlerAdapter
对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。 下图是许多不同的适配器,最终都可以使用 usb 接口连接
ViewResolver
:视图解析器 View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。View
:视图 springmvc 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView 等。我们最常用的视图就是 jsp。
5.HTTP 请求处理流程
不论在``SpringBoot还是
SpringMVC中,一个 HTTP 请求会被
DispatcherServlet类接收,它本质是一个
Servlet,因为它继承自
HttpServlet。在这里,Spring 负责解析请求,匹配到
Controller`类上的方法,解析参数并执行方法,最后处理返回值并渲染视图。
6.Model 和 ModelAndView
Model 与 ModelAndView 的最大区别
- Model 只是用来传输数据的,并不会进行业务的寻址。ModelAndView 则可以进行业务寻址,即可以设置对应的要请求的静态文件(jsp 等)。
- Model 是每次请求可以自动创建的,而 ModelAndView 是需要自行 new 的。
7.ModelMap
- ModelMap 对象主要用于传递控制方法处理数据到结果页面,也就是说我们把结果页面上需要的数据放到 ModelMap 对象中即可。通过以下方法向页面传递参数:
8.DispatcherServlet
- 可以看到它是继承了
HttpServlet
的,用来接收请求的。 - 也是实现了
ApplicationContextAware
接口的可以猜到它是用来获取需要的相关组件的。 - 它的父类
FrameworkServlet
会看到Servlet
在初始化的时候会给Spring
注册一个容器刷新的监听事件,在容器初始化完之后会进来刷新执行初始化操作。
二.注解
1.RequestParam
@RequestMapping("/test1")
@ResponseBody
public String test1(String t1, @RequestParam(name = "t2",required = false) String t2,HttpServletRequest request){
logger.info("参数:{},{}",t1,t2);
return "Java";
}
2.ModelAttribute
@PostMapping("/getUserLogin")
public String getUserLogin(@ModelAttribute UserLogin userLogin) {
String username = userLogin.getUsername;
String password = userLogin.getPassword;
selectByCond(username,password);
}
-
@ModelAttribute 可以注释在方法上,在用@RequestMapping 注解的控制器方法被调用之前调用@ModelAttribute 方法。
-
当作为方法的参数使用,指示的参数应该从模型中检索。如果不存在,它应该首先实例化,然后添加到模型中,一旦出现在模型中,参数字段应该从具有匹配名称的所有请求参数中填充。
3.RequestParam 和 ModelAttribute 区别
- @ModelAttribute:绑定整个 Java 对象(如 Employee)。支持多个请求参数
- @RequestParam:结合一个单一的请求参数(像的 firstName)
- @RequestParam 是最适合读出一小则 params 的。
- @ModelAttribute 用于具有大量字段的表单。
- @ModelAttribute 为您提供了额外的功能,如数据绑定,验证和形式预先填充。
- 当同时使用@RequestParam()和@RequestBody 时,@RequestParam()指定的参数可以是普通元素、数组、集合、对象等等
4.RequestBody
@RequestBody 主要用来接收前端传递给后端的 json 字符串中的数据的(请求体中的数据的);
@RequestBody 用于 post 请求,不能用于 get 请求。
注:一个请求,只有一个 RequestBody;一个请求,可以有多个 RequestParam。
RequestBody
接收的是请求体里面的数据;而RequestParam
接收的是 key-value 里面的参数
如果我们需要前端传输更多的参数内容,那么通过一个 POST 请求,将参数放在 Body 中传输是更好的方式。当然,比较友好的数据格式当属 JSON。
@ResponseBody
@RequestMapping("/test2")
public String test2(@RequestBody SysUser user){
logger.info("参数信息:{}",JSONObject.toJSONString(user));
return "Hello";
}
5.GET 请求参数转换 Bean
还有一种写法是这样的,在 Controller 方法上用 Java Bean 接收。
@RequestMapping("/test3")
@ResponseBody
public String test3(SysUser user){
logger.info("参数:{}",JSONObject.toJSONString(user));
return "Java";
}
然后用 GET 方法请求:
http://localhost:8080/test3?id=1001&name=Jack&password=1234&address=北京市海淀区
6.RestFul 风格
概念
REST 是REpresentational State Transfer的缩写(一般中文翻译为表述性状态转移),REST 是一种体系结构,而 HTTP 是一种包含了 REST 架构属性的协议,为了便于理解,我们把它的首字母拆分成不同的几个部分:
-
表述性(REpresentational): REST 资源实际上可以用各种形式来进行表述,包括 XML、JSON 甚至 HTML——最适合资源使用者的任意形式;
-
状态(State): 当使用 REST 的时候,我们更关注资源的状态而不是对资源采取的行为;
-
转义(Transfer): REST 涉及到转移资源数据,它以某种表述性形式从一个应用转移到另一个应用。
简单地说,REST 就是将资源的状态以适合客户端或服务端的形式从服务端转移到客户端(或者反过来)。
在 REST 中,资源通过 URL 进行识别和定位,然后通过**行为(即 HTTP 方法)**来定义 REST 来完成怎样的功能。
功能
资源:互联网所有的事物都可以被抽象为资源
资源操作:使用 POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、修改、查询。
CRUD 动作 | HTTP 方法 |
---|---|
Create | POST |
Read | GET |
Update | PUT 或 PATCH |
Delete | DELETE |
使用传统方式操作资源
通过不同的参数来实现不同的效果!方法单一,post 和 get
http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST
使用 RESTful 操作资源
可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE
7.重定向和转发
重定向是将用户从当前处理请求定向到另一个视图(例如 JSP)或处理请求,以前的请求(request)中存放的信息全部失效,并进入一个新的 request 作用域;
转发是将用户对当前处理的请求转发给另一个视图或处理请求,以前的 request 中存放的信息不会失效。
转发是服务器行为,重定向是客户端行为。
转发过程
客户浏览器发送 http 请求,Web 服务器接受此请求,调用内部的一个方法在容器内部完成请求处理和转发动作,
将目标资源发送给客户;在这里转发的路径必须是同一个 Web 容器下的 URL,其不能转向到其他的 Web 路径上,中间传递的是自己的容器内的 request。
在客户浏览器的地址栏中显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。
转发行为是浏览器只做了一次访问请求。
重定向过程
客户浏览器发送 http 请求,Web 服务器接受后发送 302 状态码响应及对应新的 location 给客户浏览器,
客户浏览器发现是 302 响应,则自动再发送一个新的 http 请求,请求 URL 是新的 location 地址,服务器根据此请求寻找资源并发送给客户。
在这里 location 可以重定向到任意 URL,既然是浏览器重新发出了请求,那么就没有什么 request 传递的概念了。在客户浏览器的地址栏中显示的是其重定向的路径,客户可以观察到地址的变化。重定向行为是浏览器做了至少两次的访问请求。
8.GET 和 POST 的区别
- GET 在浏览器回退时是无害的,而 POST 会再次提交请求。
- GET 产生的 URL 地址可以被 Bookmark,而 POST 不可以。
- GET 请求会被浏览器主动 cache,而 POST 不会,除非手动设置。
- GET 请求只能进行 url 编码,而 POST 支持多种编码方式。
- GET 请求参数会被完整保留在浏览器历史记录里,而 POST 中的参数不会被保留。
- GET 请求在 URL 中传送的参数是有长度限制的,而 POST 么有。
- 对参数的数据类型,GET 只接受 ASCII 字符,而 POST 没有限制。
- GET 比 POST 更不安全,因为参数直接暴露在 URL 上,所以不能用来传递敏感信息。
- GET 参数通过 URL 传递,POST 放在 Request body 中。