目录
- url
- mvc框架
- mvc框架的设计
- mvc流程
- 实验目的
- 实验内容
- 实验过程
- 创建项目
- 创建项目结构
- 编写代码
- 简单测试一下
url
和 Hypertext 以及 HTTP 一样,URL 是 Web 中的一个核心概念。它是浏览器用来检索 web 上公布的任何资源的机制
URL 代表着是统一资源定位符(Uniform Resource Locator)。URL 无非就是一个给定的独特资源在 Web 上的地址。理论上说,每个有效的 URL 都指向一个唯一的资源。这个资源可以是一个 HTML 页面,一个 CSS 文档,一幅图像,等等。而在实际中,也有一些例外,最常见的情况就是一个 URL 指向了不存在的或是被移动过的资源。由于通过 URL 呈现的资源和 URL 本身由 Web 服务器处理,因此 web 服务器的拥有者需要认真地维护资源以及与它关联的 URL
mvc框架
MVC是三个单词的首字母缩写,它们是Model(模型)、View(视图)和Controller(控制)。
1、视图
视图(View)代表用户交互界面,对于Web应用来说,可以概括为HTML界面,但有可能为XHTML、XML和Applet。随着应用的复杂性和规模性,界面的处理也变得具有挑战性。一个应用可能有很多不同的视图,MVC设计模式对于视图的处理仅限于视图上数据的采集和处理,以及用户的请求,而不包括在视图上的业务流程的处理。业务流程的处理交予模型(Model)处理。比如一个订单的视图只接受来自模型的数据并显示给用户,以及将用户界面的输入数据和请求传递给控制和模型。
2、模型
模型(Model):就是业务流程/状态的处理以及业务规则的制定。业务流程的处理过程对其它层来说是黑箱操作,模型接受视图请求的数据,并返回最终的处理结果。业务模型的设计可以说是MVC最主要的核心。目前流行的EJB模型就是一个典型的应用例子,它从应用技术实现的角度对模型做了进一步的划分,以便充分利用现有的组件,但它不能作为应用设计模型的框架。它仅仅告诉你按这种模型设计就可以利用某些技术组件,从而减少了技术上的困难。对一个开发者来说,就可以专注于业务模型的设计。MVC设计模式告诉我们,把应用的模型按一定的规则抽取出来,抽取的层次很重要,这也是判断开发人员是否优秀的设计依据。抽象与具体不能隔得太远,也不能太近。MVC并没有提供模型的设计方法,而只告诉你应该组织管理这些模型,以便于模型的重构和提高重用性。我们可以用对象编程来做比喻,MVC定义了一个顶级类,告诉它的子类你只能做这些,但没法限制你能做这些。这点对编程的开发人员非常重要。
业务模型还有一个很重要的模型那就是数据模型。数据模型主要指实体对象的数据 保存(持续化)。比如将一张订单保存到数据库,从数据库获取订单。我们可以将这个模型单独列出,所有有关数据库的操作只限制在该模型中。
3、控制
控制(Controller)可以理解为从用户接收请求, 将模型与视图匹配在一起,共同完成用户的请求。划分控制层的作用也很明显,它清楚地告诉你,它就是一个分发器,选择什么样的模型,选择什么样的视图,可以完成什么样的用户请求。控制层并不做任何的数据处理。例如,用户点击一个连接,控制层接受请求后, 并不处理业务信息,它只把用户的信息传递给模型,告诉模型做什么,选择符合要求的视图返回给用户。因此,一个模型可能对应多个视图,一个视图可能对应多个模型。
模型、视图与控制器的分离,使得一个模型可以具有多个显示视图。如果用户通过某个视图的控制器改变了模型的数据,所有其它依赖于这些数据的视图都应反映到这些变化。因此,无论何时发生了何种数据变化,控制器都会将变化通知所有的视图,导致显示的更新。这实际上是一种模型的变化-传播机制。模型、视图、控制器三者之间的关系和各自的主要功能
1)最上面的一层,是直接面向最终用户的"视图层"(View)。它是提供给用户的操作界面,是程序的外壳
2)最底下的一层,是核心的"数据层"(Model),也就是程序需要操作的数据或信息
3)中间的一层,就是"控制层"(Controller),它负责根据用户从"视图层"输入的指令,选取"数据层"中的数据,然后对其进行相应的操作,产生最终结果
这三层是紧密联系在一起的,但又是互相独立的,每一层内部的变化不影响其他层。每一层都对外提供接口(Interface),供上面一层调用。这样一来,软件就可以实现模块化,修改外观或者变更数据都不用修改其他层,大大方便了维护和升级
mvc框架的设计
mvc框架运行的流程图
处理请求先到达控制器(Controller)、控制器的作用是进行请求分发,这样它会根据请
求的内容去访问模型层(Model);在现今互联网系统中,数据主要从数据库和 NoSQL 中来,
而且对于数据库而言往往还存在事务的机制,为了适应这样的变化,设计者会把模型层再细
分为两层,即服务层(Service)和数据访问层(DAO);当控制器获取到由模型层返回的数
据后,就将数据渲染到视图中,这样就能够展现给用户
mvc流程
Spring MVC 的流程是围绕 DispatcherServlet 而工作的。在 DispatcherServlet 的基础上,
还存在其他的组件
Spring MVC 运行全流程图。严格说,Spring MVC 处理请求并非一定要经过全流程,有时
候一些流程并不存在。例如,我们加入@ResponseBody 时,是没有经过视图解析器和视图渲染的
spring mvc全流程
1)在 Web 服务器启动的过程中,如果在 Spring Boot 机制下启用 Spring MVC,它就开
始初始 化 一 些 重 要 的 组 件 , 如 DispatcherServlet 、 HanderAdapter 的 实 现 类
RequestMappingHanderAdapter 等组件对象。注解@Controller 表明是一个控制器,然后
@RequestMapping 代表请求路径和控制器(或其方法)的映射关系,它就会在 Web 服务器
启动 Spring MVC 时,自动被扫描到 HanderMapping 的机制中存储。
2)在用户发起请求被 DispatcherServlet 拦截后,通过 URL 和其他的条件,通过
HanderMapping 就能找到对应的控制器(或者方法)进行响应。通过 HanderMapping 返回的
是一个 HanderExecutationChain 对象,HanderExecutationChain 对象包含了一个处理器
(Hander),处理器包含了控制器方法的逻辑,此外还有处理器的拦截器,通过拦截器进一
步增强处理器的功能。
3)得到了处理器,还要去运行。要处理的请求有多种:HTTP 请求,也有按 BeanName
的请求,所以需要一个适配器去运行 HanderExecutationChain 对象包含的处理器,这就是
HanderAdapter 接口定义的实现类 HttpRequestHanderAdapter 。通过请求的类型,
DispatcherServlet 就会找到它来执行 Web 请求的 HanderExecutationChain 对象包含的内容,
这样就能够执行我们的处理器(handler)了。
4)在处理器调用控制器时,它首先通过模型层得到数据,再放入数据模型中,最后将
返回模型和视图(ModelAndView)对象。下面代码控制器返回的视图名称为“user/details”,
这样就走到了视图解析器(ViewResolver),去解析视图逻辑名称了。
@Controller
@RequestMapping("/user")
public class MyController {
// 注入用户服务类
@Autowired
private IUserService userService;
// 按id查询显示结果, 展示用户详情,展示结果 jsp视图
// URL地址: http://localhost:8080/user/details?id=3
@RequestMapping("/details")
public ModelAndView details(Integer id) {
3
// 访问模型层得到数据
User user = userService.getUser(id);
// 模型和视图
ModelAndView mv = new ModelAndView();
// 定义模型视图
// 视图路径:application.property文件中设置
spring.mvc.view.prefix=/WEB-INF/jsp/
// 视图名称: user/details.jsp
mv.setViewName("user/details");
// 加入数据模型
mv.addObject("user", user);
// 返回模型和视图
return mv;
}
}
为了定制 InternalResourceViewResolver 初始化,可以在配置文件 application.properties
中进行配置。通过 application.properties 定制 InternalResourceViewResolver 初始化:
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
通过修改这样的配置,就能在 Spring Boot 的机制下定制 InternalResourceViewResolver
这个视图解析器的初始化,也就是在返回视图名称之后,它会以前缀(prefix)和后缀(suffix)
以及视图名称组成全路径定位视图。例如,控制器中返回的是“user/details”,那么它
就会找到/WEB-INF/jsp/user/details.jsp 作为视图 。严格地说,这一步也是必须的,因为有些
视图并不需要返回逻辑名称。在不需要的时候,就不再需要视图解析器工作了。
5)视图解析器定位到视图后,视图的作用是将数据模型(Model)渲染,这样就能够
相应用户的请求。这一步就是视图将数据模型渲染(View)出来,用来展示给用户看。
程序清单:/WEB-INF/jsp/user/details.jsp
<%@ page pageEncoding=“UTF-8”%>
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core”%>
<html>
<head>
<title>用户详情</title>
</head>
<body>
<div align="center">
<table border="1">
<tr>
<td>标签</td>
<td>值</td>
</tr>
<tr>
<td>用户编号</td>
<td><c:out value="${user.id}"></c:out></td>
4
</tr>
<tr>
<td>用户名称</td>
<td><c:out value="${user.userName}"></c:out></td>
</tr>
<tr>
<td>用户备注</td>
<td><c:out value="${user.note}"></c:out></td>
</tr>
</table>
</div>
</body>
</html>
注意:控制器里绑定数据模型的时候,属性名称为 user,而属性为 User 对象,所以就
有了${user.id}代表 User 对象的 id 属性。。。,这样就能够将数据模型的数据渲染到 JSP 视图上
来展示用户详情给请求。
Spring Boot 启动后,运行得到如下日志:
Mapped “{[/user/details]}” onto public
org.springframework.web.servlet.ModelAndView
com.springmvc.chapter03.controller.MyController.details(java.lang.Integ
er)
这说明我们配置的@RequestMapping 的请求映射已经在服务器启动时被扫描到了
Spring 上下文中,所以当请求来到时就可以匹配到对应的控制器去提供服务
通过请求 http://localhost:8080/user/details?id=3 以及 HanderMapping 的匹
配机制就可以找到处理器提供服务。而这个处理器则包含我们开发的控制器,那么进入控制
器后,它就执行控制器的逻辑,通过模型和视图(ModelAndView)绑定了数据模型,而且
把视图名称修改为“user/details”,随后返回。
有时候,我们需要的只是 JSON 数据集,因为目前前后台分离,使用 JSON 已经是主流方
式,使用@ResponseBody 标注。也可以用 MappingJackson2sonView 转换出 JSON。代码
清单。
// 按id查询显示结果, 展示用户详情 ,展示结果 Json格式
// URL地址: http://localhost:8080/user/detailsForJson?id=3
@RequestMapping(“/detailsForJson”)
public ModelAndView detailsForJson(Integer id) {
// 访问模型层得到数据
User user = userService.getUser(id);
5
// 模型和视图
ModelAndView mv = new ModelAndView();
// 生成JSON视图
MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
mv.setView(jsonView);
// 加入模型
mv.addObject(“user”, user);
return mv;
}
在 控 制 器 的 方 法 中 模 型 和 视 图 ( ModelAndView ) 中 捆 绑 了 JSON 视 图
(MappingJackson2JsonView)和数据模型(User)对象,然后返回,其结果也会转变为 JSON。
执行流程:JSON 视图是没有视图解析器的定位视图的,因为它不是一个逻辑视图,只
是需要将数据模型(这里是 User 对象)转换为 JSON 而已
在spring mvc流程中使用JSON视图
实验目的
(1) 掌握 Spring MVC 框架运行流程
(2) 掌握 Spring MVC 项目开发流程
(3) 掌握 URL 映射及方法参数的使用方法
实验内容
(1) 学会在 Spring Boot 中开发 Spring MVC 项目——Spring Boot 对 JSP 的支持
(2) 掌握 URL 映射及其方法参数的使用方法
实验过程
创建项目
打开idea,建立一个新项目
使用spring向导,选择合适的java版本
点击下一步
选择spring web和thymeleaf这两个坐标
点击创建
检查pom中是否引入了项目
可以通过查看idea右侧的meaven是否有勾选的内容
或者自动生成的主程序中的注解没有报错就可以说明坐标起了效果,没有问题
创建项目结构
编写代码
UserController
import com.example.springmvctest.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
public class UserController {
@RequestMapping(value = "/insert",method = RequestMethod.GET)
public String insertUser(Model model){
User user = new User();
user.setId("1");
user.setName("insert");
model.addAttribute("user",user);
return "index"; //返回视图的名称-
}
@RequestMapping(value = "/update",method = RequestMethod.GET)
public String updateUser(Model model){
User user = new User();
user.setId("1");
user.setName("update");
model.addAttribute("user",user);
return "index"; //返回视图的名称-
}
@RequestMapping(value = "/delete",method = RequestMethod.GET)
public String deleteUser(Model model){
User user = new User();
user.setId("1");
user.setName("delete");
model.addAttribute("user",user);
return "index"; //返回视图的名称-
}
@RequestMapping(value = "/find", method = RequestMethod.GET)
public String findUser(Model model){
User user = new User();
user.setId("1");
user.setName("find");
model.addAttribute("user",user);
return "index"; //返回视图的名称-
}
}
User
import lombok.Data;
@Data
public class User {
private String id;
private String name;
}
SpringMvcTestApplication
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringMvcTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringMvcTestApplication.class, args);
}
}
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">//命名空间
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>首页</h1>
<h1 th:text="${user.getName()}">测试</h1>
</body>
<!--<!DOCTYPE html>-->
<!--<html lang="zh">-->
<!--<head>-->
<!-- <meta charset="UTF-8">-->
<!-- <title>用户管理</title>-->
<!--</head>-->
<!--<body>-->
<!--<h1>用户管理</h1>-->
<!--<form action="/insert" method="post">-->
<!-- <p>添加用户</p>-->
<!-- <label for="id">ID:</label>-->
<!-- <input type="text" id="id" name="id" required>-->
<!-- <label for="name">姓名:</label>-->
<!-- <input type="text" id="name" name="name" required>-->
<!-- <input type="submit" value="添加">-->
<!--</form>-->
<!--<form action="/update" method="post">-->
<!-- <p>更新用户</p>-->
<!-- <label for="id">ID:</label>-->
<!-- <input type="text" id="id" name="id" required>-->
<!-- <label for="name">姓名:</label>-->
<!-- <input type="text" id="name" name="name" required>-->
<!-- <input type="hidden" name="_method" value="put">-->
<!-- <input type="submit" value="更新">-->
<!--</form>-->
<!--<form action="/delete" method="post">-->
<!-- <p>删除用户</p>-->
<!-- <label for="id">ID:</label>-->
<!-- <input type="text" id="id" name="id" required>-->
<!-- <input type="hidden" name="_method" value="delete">-->
<!-- <input type="submit" value="删除">-->
<!--</form>-->
<!--<form action="/find" method="get">-->
<!-- <p>查找用户</p>-->
<!-- <label for="id">ID:</label>-->
<!-- <input type="text" id="id" name="id" required>-->
<!-- <input type="submit" value="查找">-->
<!--</form>-->
<!--<div id="result">-->
<!-- <p>用户信息</p>-->
<!-- <h1 th:text="${user.getName()}">测试</h1>-->
<!--</div>-->
<!--</body>-->
<!--</html>-->
简单测试一下
以上。