MVC模型
1.MVC是一种表现层的设计模型。它的全名是Model(模型)-View(视图)-Control(控制器):
Model(模型):模型指的是数据模型,与封装数据相关的都是模型。比如pojo、vo
View(视图):视图指的是展示数据,与页面相关的都是视图。比如html、jsp
Control(控制器):控制器指的是用户交互,接收用户请求,响应用户。比如servlet

springmvc在三层架构中的位置
springmvc位于J2EE项目三层架构中的:表现层

springmvc优点

环境搭建
配置pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.heaven</groupId>
<artifactId>springmvc-day01-01helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<!--spring 版本-->
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<!--spring ioc依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!--spring webmvc依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
<build>
<finalName>springmvc-day01-01helloworld</finalName>
<!--配置插件-->
<plugins>
<!--maven tomcat插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<!-- tomcat 的端口号 -->
<port>8080</port>
<!-- 访问应用的路径 -->
<path>/hello</path>
<!-- URL按UTF-8进行编码,解决中文参数乱码 -->
<uriEncoding>UTF-8</uriEncoding>
<!-- tomcat名称 -->
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
</build>
</project>
编写springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--配置包扫描controller-->
<context:component-scan base-package="com.heaven.controller"></context:component-scan>
</beans>
编写web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
</web-app>
配置DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<!-- 配置前端控制器:DispatcherServlet -->
<servlet>
<servlet-name>springmvc-helloworld</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 加载springmvc主配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 配置什么时候加载前端控制器,说明:
1.配置大于等于0的整数,表示在tomcat启动的时候加载
2.配置小于0的整数,表示在第一次请求到达的时候加载
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc-helloworld</servlet-name>
<!-- 配置请求url规则,说明:
1.*.do,表示以.do结尾的请求进入前端控制器
2./,表示所有请求都进入前端控制器
-->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
代码开发
编写success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>springmvc入门案例页面</title>
</head>
<body>
你好,世界!${hello}
</body>
</html>
编写controller
/**
* 入门案例controller
*/
@Controller
public class HelloController {
/**
* 入门案例hello方法:
*
* ModelAndView:模型和视图。用于封装模型数据和视图页面
* @RequestMapping注解:用于配置请求的url
*/
@RequestMapping("/hello.do")
public ModelAndView hello(){
// 1.创建ModelAndView
ModelAndView mav = new ModelAndView();
// 2.响应模型数据
/**
* addObject方法:设置模型数据
* 参数一:模型名称
* 参数二:模型数据
*/
mav.addObject("hello","springmvc!");
// 3.响应视图
/**
* setViewName方法:设置视图页面的名称
*/
mav.setViewName("/WEB-INF/jsp/success.jsp");
return mav;
}
}
执行流程分析
1.启动初始化项目环境:
1.1.开发好项目,打成war包,部署到tomcat服务器
1.2.启动tomcat服务器,加载项目中的web.xml文件
1.3.初始化创建servlet对象(DispatcherServlet)
1.4.根据配置参数contextConfigLocation指定位置,加载springmvc.xml配置文件
1.5.初始化创建controller对象(HelloController)
1.6.到此,初始化项目环境工作完成
2.请求响应执行流程:
2.1.用户从浏览器发起请求:http://localhost:8080/hello/hello.do
2.2.请求统一到达前端控制器DispatcherServlet
2.3.前端控制器调用其它组件(处理器映射器),根据请求的url:hello.do,找到对应controller方法:hello()
2.4.前端控制器调用其它组件(处理器适配器),调用执行controller方法:hello()
2.5.controller方法执行完成,返回ModelAndView。包含响应的数据、和响应的页面
2.6.前端控制器调用其它组件(视图解析器),完成用户请求的响应
时序图

常用组件
处理器映射器
在springmvc框架中,组件处理器映射器的作用:
根据请求的url路径:
http://localhost:8080/hello/hello.do
找到对应的处理器方法:
@RequestMapping("/hello.do")
public ModelAndView hello(){}
处理器适配器
在springmvc框架中,组件处理器适配器的作用:
调用执行处理器方法:hello()
显示配置处理器映射器和适配器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--配置包扫描controller-->
<context:component-scan base-package="com.heaven.controller"></context:component-scan>
<!--显示配置处理器映射器和处理器适配器,说明:
第一步:导入mvc名称空间和约束
第二步:通过注解驱动标签配置
-->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
视图解释器
在springmvc框架中,组件视图解析器的作用:
1.把逻辑视图(在处理器方法中设置的页面路径)解析成物理视图(在浏览器实际看到的页面)
2.整个处理过程有两件事情:
2.1.把数据放入HttpServletRequest域中
2.2.通过转发响应页面
显示视图解析器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--配置包扫描controller-->
<context:component-scan base-package="com.heaven.controller"></context:component-scan>
<!--显示配置处理器映射器和处理器适配器,说明:
第一步:导入mvc名称空间和约束
第二步:通过注解驱动标签配置
-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--配置视图的公共目录路径(前缀)-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--配置视图的扩展名称(后缀)-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
SpringMVC框架原理
请求响应执行流程
1.请求响应执行流程:
1.1.用户从浏览器发起请求:http://localhost:8080/hello/hello.do
1.2.请求统一到达前端控制器DispatcherServlet
1.3.前端控制器调用其它组件(处理器映射器),根据请求的url:hello.do,找到对应controller方法:hello()
1.4.前端控制器调用其它组件(处理器适配器),调用执行controller方法:hello()
1.5.controller方法执行完成,返回ModelAndView。包含响应的数据、和响应的页面
1.6.前端控制器调用其它组件(视图解析器),完成用户请求的响应
主要源码追踪:
DispatcherServlet
public class DispatcherServlet extends FrameworkServlet {
// 统一接收处理请求的入口方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
...........
// 处理器映射器:根据请求的url,找到对应的处理器方法
mappedHandler = this.getHandler(processedRequest);
...........
// 处理器适配器:调用执行处理器方法
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
...........
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
...........
// 视图解析器:把逻辑视图,解析成物理视图
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
...........
}
}
----------------------------------------------------------------------------------------
2.2.InternalResourceView
public class InternalResourceView extends AbstractUrlBasedView {
// 解析视图方法,把数据放入request域,通过转发实现页面响应
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 把数据放入request域
this.exposeModelAsRequestAttributes(model, request);
.............
// 转发响应页面
RequestDispatcher rd = this.getRequestDispatcher(request, dispatcherPath);
.............
rd.forward(request, response);
}
}

RequestMapping注解
RequestMapping直接是springMVC中的基础注解,作用有三:
1.配置请求的url
@Controller
public class RequestMappingController {
/**
* @RequestMapping注解:
* 作用一:配置请求的url
* 属性:
* value:是一个数组,可以配置多个url
* 细节:
* "/"和".do"可以省略
*
*/
//@RequestMapping(value = {"/requestMapping.do","/requestMappingAAA.do"})
@RequestMapping(value = {"requestMapping"})
public ModelAndView requestMapping(){
// 1.创建ModelAndView
ModelAndView mav = new ModelAndView();
// 2.响应模型数据
mav.addObject("hello","RequestMapping注解!");
// 3.响应视图
mav.setViewName("success");
return mav;
}
}
2.限制http请求方法
@RequestMapping(value = {"requestMapping"},method = {RequestMethod.POST,RequestMethod.GET})
public ModelAndView requestMapping(){
// 1.创建ModelAndView
ModelAndView mav = new ModelAndView();
// 2.响应模型数据
mav.addObject("hello","RequestMapping注解!");
// 3.响应视图
mav.setViewName("success");
return mav;
}
改造success.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>springmvc入门案例页面</title>
</head>
<body>
你好,世界!${hello}
<hr/>
<p>学习@RequestMapping注解:</p>
<form action="${pageContext.request.contextPath}/requestMapping.do" method="post">
<input type="submit" name="submit" value="POST请求"/>
</form>
</body>
</html>
3.分类管理url


SpringMVC参数绑定
定义——
1.我们在访问网站的时候,通常会提交一些请求参数给服务器。比如登录:用户名称和密码
2.在web阶段,通过HttpServletRequest对象获取请求参数:
request.getParameter("参数名称")
3.在springmvc框架中,参数绑定指的是通过处理器方法的形参,获取到请求的参数数据
参数绑定类型
1.HttpServletRequest:
作用:通过request,获取请求的参数数据
2.HttpServletResponse:
作用:通过response,执行响应
3.HttpSession:
作用:通过session,获取和保存会话域数据
4.Model/ModelMap:
4.1.Model是一个接口,是模型,用于封装响应的模型数据
4.2.ModelMap是实现类,使用Model和使用ModelMap,效果是一样的
4.3.使用Model封装响应的模型数据,就可以不使用ModelAndView,页面视图可以使用字符串响应
tips:
Model+String == ModelAndView
简单参数类型注意事项——
使用简单参数类型绑定参数,推荐使用简单类型的包装类型(Integer),不建议使用简单类型的基础类型(int)。原因是基础类型不能为null值,如果不传递会报异常
常用简单类型

pojo参数类型
一次接收多个参数
中文字符乱码解决
原因分析:
1.通过测试,使用商品pojo可以一次性接收到请求的多个商品属性参数。但是出现了乱码。
2.乱码的原因是,tomcat服务器默认的字符集编码是ISO-8859-1。它不支持中文。
3.解决办法:
sprnig框架提供了一个字符集编码过滤器:CharacterEncodingFilter。用于解决post请求的字符集编码
。
web.xml
<!-- 配置字符集编码过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 指定使用的编码:UTF-8 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<!-- 配置所有请求都经过字符集编码过滤器处理 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
pojo包装类型
谓pojo包装类型,就是在pojo中包含(嵌套)了其它pojo。
/**
* pojo包装类型
*/
public class QueryVO {
// 包装商品
/**
* 商品名称:<input type="text" name="item.name" value=""/>
*/
private Item item;
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
}
增加包装类参数:
*/
@RequestMapping("/queryItem.do")
public ModelAndView queryItem(QueryVO queryVO){
// 1.创建ModelAndView
ModelAndView mav = new ModelAndView();
// 2.设置响应的页面
mav.setViewName("item/list");
return mav;
}
自定义参数类型
日期
自定义装换器
/**
* 自定义日期类型转换器,需要实现接口:Converter<S,T>
*
* Converter<S, T>
* S,Source,源,转换之前的数据,这里是字符串String类型的商品生产日期
* T,Target,目标,转换之后的数据,这里是Date类型的商品生产日期
*/
public class DateConverter implements Converter<String,Date>{
/**
* 实现转换逻辑
*/
public Date convert(String s) {
// 1.日期格式化对象(2018-07-15 17:22:30)
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
// 转换成功,直接返回
return format.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
// 转换失败,返回null
return null;
}
}
配置自定义转换器(springmvc.xml)
<!--显示配置处理器映射器和处理器适配器,说明:
第一步:导入mvc名称空间和约束
第二步:通过注解驱动标签配置
-->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 配置自定义转换器 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.heaven.converter.DateConverter"/>
</set>
</property>
</bean>
高级参数绑定
List
【关于List参数类型绑定的注意事项】
springmvc框架的List参数绑定,List需要作为pojo的属性,不能直接在处理器方法的形参中,使用List,否则不能完成绑定。
/**
* 查询全部商品列表数据
* <form action="${pageContext.request.contextPath }/queryItem.do"
*
* 说明:
* 形参QueryVO,用于接收综合查询条件
* 形参数组ids,接收多个商品id参数数据:
* <td><input type="checkbox" name="ids" value="1"/></td>
*/
@RequestMapping("/queryItem.do")
public ModelAndView queryItem(QueryVO queryVO,Integer[] ids){
// 1.创建ModelAndView
ModelAndView mav = new ModelAndView();
// 2.设置响应的页面
mav.setViewName("item/list");
return mav;
}
List参数类型
修改商品列表页面(list.jsp)
<hr/>
批量修改商品页面功能:
<form action="${pageContext.request.contextPath }/queryItem.do"
method="post">
商品列表:<input type="submit" value="批量修改" />
<table width="100%" border=1>
<tr>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
</tr>
<%--
list绑定name属性分析:
itemList:要绑定的集合属性
itemList[0]:集合中的第一个商品对象
itemList[0].id:集合中第一个商品对象的id属性
其它以此类推......
--%>
<tr>
<input type="hidden" name="itemList[0].id" value="1"/>
<td><input type="text" name="itemList[0].name" value="笔记本"/></td>
<td><input type="text" name="itemList[0].price" value="8000"/></td>
<td><input type="text" name="itemList[0].createtime" value="2018-07-15 17:22:30"/></td>
<td><input type="text" name="itemList[0].detail" value="国产的质量越来越好了,放心使用"/></td>
</tr>
<tr>
<input type="hidden" name="itemList[1].id" value="2"/>
<td><input type="text" name="itemList[1].name" value="台式机"/></td>
<td><input type="text" name="itemList[1].price" value="5000"/></td>
<td><input type="text" name="itemList[1].createtime" value="2018-07-15 17:22:30"/></td>
<td><input type="text" name="itemList[1].detail" value="国产的质量越来越好了,放心使用"/></td>
</tr>
</table>
</form>
修改包装类
/**
* pojo包装类型
*/
public class QueryVO {
// 包装商品
/**
* 商品名称:<input type="text" name="item.name" value=""/>
*/
private Item item;
// 包装商品集合list
private List<Item> itemList;
public List<Item> getItemList() {
return itemList;
}
public void setItemList(List<Item> itemList) {
this.itemList = itemList;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
}
controller方法返回值(响应)
1.返回ModelAndView
ModelAndView:
用于封装响应的模型数据
用于封装响应的页面

2.返回void
/**
* 学习controller方法返回void:
* 1.request转发
* 2.response重定向
* 3.response响应数据
*/
@RequestMapping("/returnVoid.do")
public void controllerReturnVoid(HttpServletRequest request, HttpServletResponse response){
/**
* 1.request转发
* 转发特点:
* 1.转发是一次请求,可以获取到request中的数据
* 2.转发浏览器的地址栏不会发生改变
* 3.只能在项目内部实现转发
*/
try {
request.getRequestDispatcher("queryItem.do")
.forward(request,response);
}catch(Exception e) {
e.printStackTrace();
}
}
修改商品列表页面(list.jsp)
<%--说明:
param.itemId===>request.getParameter("itemId")
--%>
<p>我是转发过来,可以获取到request中的数据:${param.itemId}
<hr/>
response重定向
修改controllerReturnVoid方法
/**
* 学习controller方法返回void:
* 1.request转发
* 2.response重定向
* 3.response响应数据
*/
@RequestMapping("/returnVoid.do")
public void controllerReturnVoid(HttpServletRequest request, HttpServletResponse response){
/**
* 1.request转发
* 转发特点:
* 1.转发是一次请求,可以获取到request中的数据
* 2.转发浏览器的地址栏不会发生改变
* 3.只能在项目内部实现转发
*/
/* try {
request.getRequestDispatcher("queryItem.do")
.forward(request,response);
}catch(Exception e) {
e.printStackTrace();
}*/
/**
* 2.response重定向
* 重定向特点:
* 1.重定向是两次请求,不能获取旧的request中的数据
* 2.重定向浏览器的地址栏会改变成目标url
* 3.重定向可以在项目内部执行;也可以重定向到其它项目
*/
try {
// 1.项目内部执行重定向
//response.sendRedirect("queryItem.do");
// 2.重定向到外部项目:博客园
response.sendRedirect("https://www.cnblogs.com");
} catch (IOException e) {
e.printStackTrace();
}
}
修改商品列表页面(list.jsp)
<%--说明:
param.itemId===>request.getParameter("itemId")
--%>
<%--<p>我是转发过来,可以获取到request中的数据:${param.itemId}--%>
<p>我是重定向过来,【不】可以获取到request中的数据:${param.itemId}
<hr/>
response响应数据
修改controllerReturnVoid方法
/**
* 学习controller方法返回void:
* 1.request转发
* 2.response重定向
* 3.response响应数据
*/
@RequestMapping("/returnVoid.do")
public void controllerReturnVoid(HttpServletRequest request, HttpServletResponse response){
/**
* 1.request转发
* 转发特点:
* 1.转发是一次请求,可以获取到request中的数据
* 2.转发浏览器的地址栏不会发生改变
* 3.只能在项目内部实现转发
*/
/* try {
request.getRequestDispatcher("queryItem.do")
.forward(request,response);
}catch(Exception e) {
e.printStackTrace();
}*/
/**
* 2.response重定向
* 重定向特点:
* 1.重定向是两次请求,不能获取旧的request中的数据
* 2.重定向浏览器的地址栏会改变成目标url
* 3.重定向可以在项目内部执行;也可以重定向到其它项目
*/
/*try {
// 1.项目内部执行重定向
//response.sendRedirect("queryItem.do");
// 2.重定向到外部项目:博客园
response.sendRedirect("https://www.cnblogs.com");
} catch (IOException e) {
e.printStackTrace();
}*/
/**
* 3.response响应数据
*/
try {
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
// 模拟向浏览器输出的json字符串
String str = "{\"id\":1,\"name\":\"小明\"}";
response.getWriter().write(str);
} catch (IOException e) {
e.printStackTrace();
}
}
返回String
默认直接响应页面
[图片上传失败...(image-d6b93-1568508653099)]
forward转发
增加controllerReturnString方法
/**
* 学习controller方法返回String:
* 1.默认直接响应页面
* 2.forward转发
* 3.redirect重定向
*/
@RequestMapping("/returnString.do")
public String controllerReturnString(){
/**
* 1.forward转发
* 转发格式:
* forward+":"+目标url
*
* 细节:
* 请求的url,不能省略.do。
* 即return "forward:queryItem";
*/
return "forward:queryItem.do";
}
redirect重定向
修改controllerRequestString方法
@RequestMapping("/returnString.do")
public String controllerReturnString(){
/**
* 1.forward转发
* 转发格式:
* forward+":"+目标url
*
* 细节:
* 请求的url,不能省略.do。
* 即return "forward:queryItem";
*/
//return "forward:queryItem.do";
/**
* 2.redirect重定向
* 重定向格式:
* redirect+":"+目标url
*
* 细节:
* 请求的url,不能省略.do。
* 即return "redirect:queryItem";
*/
return "redirect:queryItem.do";
}
网友评论