志合者,不以山海为远;道乖者,不以咫尺为近
1. MVC简介
1.1 定义
MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范,MVC不是一种设计模式,MVC是一种架构模式
1.2 背景
- Model1时代:主要分为两层,视图层和模型层。逻辑基本在jsp上。jsp本质是一个Servlet
- Model2时代:MVC:模型(dao、service) 视图(jsp) 控制器(Servlet),最典型的MVC就是JSP + servlet + javabean的模式。
1.3 功能
- 将url映射到java类或java类的方法
- 封装用户提交的数据
- 处理请求–调用相关的业务处理–封装响应数据
- 将响应的数据进行渲染 . jsp / html 等表示层数据
1.4 常见框架
- 常见的服务器端MVC框架有:Struts、Spring MVC、ASP.NET MVC、Zend Framework、JSF
- 常见前端MVC框架:vue、angularjs、react、backbone;
- MVC演化出了另外一些模式如:MVP、MVVM【前后端分离核心】 等
2. Spring MVC概述
2.1 定义
Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。
2.2 特点
- 与Spring无缝结合,可以将mvc的bean注册到Spring,使用人多
- 约定优于配置
- 功能多:RESTful、数据验证、格式化、本地化、主题等
- Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计,DispatcherServlet是一个实际的Servlet (它继承自HttpServlet 基类)
1 | 1. public class DispatcherServlet extends FrameworkServlet |
2.3 Spring MVC原理和流程
当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者
- DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
- web.xml
1 |
|
HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
- springmvc-servlet.xml【接口版】
缺点:一个控制器中只有一个方法handleRequest,不方便
1 |
|
1 |
|
- springmvc-servlet.xml【注解版】
1 |
|
- HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello
- HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
- HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
- Handler让具体的Controller执行。
- HelloController【接口版】
1 | package cn.xxy.controller; |
- HelloController【注解版】
1 | package cn.xxy.controller; |
- Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
- HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
- DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名
- 视图解析器将解析的逻辑视图名传给DispatcherServlet。
- DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
- 最终视图呈现给用户
2.4 RestFul 风格【不是标准】
Restful就是一个资源定位及资源操作的风格。请求地址一样,但是功能可以不同!不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作,分别对应 添加、 删除、修改、查询。
注解有:
1 | //路经变量,放参数旁边 |
2.5 页面跳转方式
- ModelAndView: {视图解析器前缀} + viewName +{视图解析器后缀}
没有解耦
1 | <!-- 视图解析器 --> |
1 | public class ControllerTest1 implements Controller { |
- ServletAPI
不需要视图解析器 ,不建议使用,通过HttpServletResponse进行输出,通过HttpServletResponse实现重定向,通过HttpServletResponse实现转发
1 |
|
- SpringMVC
- 无视图解析器
1 |
|
- 有视图解析器
1 |
|
- 对比Model ,ModelMap ,ModelAndView
序号 | 名称 | 功能 |
---|---|---|
1 | Model | 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解; |
2 | ModelMap | 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性 |
3 | ModelAndView | 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转,但没有解耦 |
2.6 接收参数并绑定
- 注解
通过如HttpServletRequest等API得到请求数据,但推荐使用注解方式
序号 | 注解 | 功能 |
---|---|---|
1 | @RequestParam | 绑定单个请求参数值 |
2 | @PathVariable | 绑定URI模板变量值 |
3 | @CookieValue | 绑定Cookie数据值 |
4 | @RequestHeader | 绑定请求头数据 |
5 | @ModelValue | 绑定参数到命令对象 |
6 | @SessionAttributes | 绑定命令对象到session |
7 | @RequestBody | 绑定请求的内容区数据并能进行自动类型转换等,例如JSON和RESTful风格 |
8 | @RequestPart | 绑定“multipart/data”数据,一般上传和下载 |
- 单个请求参数值
@RequestParam(value=”user_id”)
1 |
|
- 对象实体
直接对象放入参数User user,前端传递的参数名和对象名必须一致
1 |
|
2.7 乱码
- 前端乱码【过滤器】
1 | <filter> |
- Tomcat乱码【修改配置文件】
1 | <Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1" |
- json乱码
1 | <mvc:annotation-driven> |
- 自定义编码
1 | package cn.xxy.filter; |
2.8 JSON
- 定义
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式,独立于编程语言的文本格式来存储和表示数据
- 格式
1 | var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的 |
- 注解
序号 | 名称 | 功能 |
---|---|---|
1 | @ResponseBody | 直接返回json对象,用于method |
2 | @RequestBody | 用于请求的数据绑定到方法的形参中,用于形参上 |
3 | @RestController | 里面所有的方法都只会返回 json 字符串,不用再每一个方法都添加@ResponseBody |
- 开发测试
- 导包【jackson\fastjson】
1 | <dependency> |
- 实体类
1 | package cn.xxy.pojo; |
- Controller类
1 | package cn.xxy.controller; |
- json乱码
- 第一种解决
1 | //produces:指定响应体返回类型和编码 |
- 第二种解决
1 | <mvc:annotation-driven> |
- 日期优化(getjson作为一个工具类)
1 | package cn.xxy.utils; |
- fastjson
- 导包
1 | <dependency> |
- 测试
1 | package cn.xxy.controller; |
2.9 Ajax【 Asynchronous JavaScript and XML】
- 概述
使用ajax技术的网页,通过在后台服务器进行少量的数据交换,就可以实现异步局部更新,框架一般用AXIOS库来使用ajax
- jQuery库的ajax
jQuery Ajax本质就是 XMLHttpRequest,对他进行了封装,
1 | jQuery.ajax(...) |
- 测试
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
1 |
|
2.10 拦截器
必须实现 HandlerInterceptor 接口
- 概述
拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理
2.过滤器与拦截器的区别
拦截器是AOP思想的具体应用
过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截,任何java web工程都可以使用
拦截器只会拦截访问的控制器方法, 如果访问的是jsp/html/css/image/js是不会进行拦截的,只有使用了SpringMVC框架才能使用
- 测试
1 | public class MyInterceptor implements HandlerInterceptor { |
1 | <!--拦截器配置--> |
2.11 文件上传下载
Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。
- 概述
前端表单设置enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。在2003年,Apache Software Foundation发布了开源的Commons FileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。
- 测试上传
- pom.xml
1 | <!--文件上传--> |
- index.jsp
1 | <form action="/upload" enctype="multipart/form-data" method="post"> |
- springmvc-servlet.xml
id不能变,必须是multipartResolver
1 | <!--文件上传配置--> |
序号 | CommonsMultipartResolver类的方法 | 功能 |
---|---|---|
1 | String getOriginalFilename() | 获取上传文件的原名 |
2 | InputStream getInputStream() | 获取文件流 |
3 | void transferTo(File dest) | 将上传文件保存到一个目录文件中 |
- FileController
1 | package cn.xxy.controller; |
- 测试下载
1 |
|
1 | <a href="${pageContext.request.contextPath}/static/1.png">图片下载</a> |
3. 总结
本次完成Spring MVC的复习,重点在原理和流程的掌握,三部分:映射器+适配器+前端显示