SpringMVC笔记
课前事项
[了解]今日课程内容
SpringMVC框架,帮我们写Controller(接收请求),及跳转页面的。(web表现层框架)
SpringMVC框架进行介绍【了解】
什么是SpringMVC?
SpringMVC作用于哪一层?
SpringMVC有什么优势
SpringMVC的入门案例【掌握】
SpringMVC的架构【了解】
SpringMVC的请求参数绑定【掌握】
简单参数绑定
pojo参数绑定
pojo包装对象绑定
集合参数的绑定
[了解]MVC模式
M即Model数据模型,V即View视图,C即Controller控制器。
Model的广义和狭义之说
广义:Model = Service层 +Dao层,由这两层来产生数据模型
狭义:Model就是数据模型本身,就是Controller和View之间传递的数据,在这种说法下,MVC又可归为Web层。
经典三层:web表现层(view+controller)、service业务层、dao持久层
[了解]SpringMVC概述
SpringMVC是什么
SpringMVC是什么
SpringMVC是一个轻量级的Web表现层框架,作用:用来写Controller接收请求跳转页面的,它是Spring框架的一部分。
说白了,用来替代servlet的。SpringMVC是对Servlet的封装和增强,简化了servlet的操作。它已经超越了Struts,成为目前最优秀的表现层框架。
原始Servlet中
第一步:取参
request.getParameter(“param”)
第二步:数据类型转换
Integer.valueOf()
http协议:超文本传输协议
在SpringMVC中,因为它是对servlet的封装,所以可以很方便的拿到整型数据
什么时候使用SpringMVC?
你觉得servlet繁琐的时候
在哪儿使用SpringMVC?
在经典三层的web表现层使用SpringMVC框架
SpringMVC的优势
操作特简单,性能特别高,灵活性特别强
与Struts框架相比
解决了struts的安全性低,操作难,执行性能低的问题
拓展认识
Spring + Spring jdbctemplate + SpringMVC --> Spring全家桶 1.0 主流
Spring cloud + Spring Boot + Spring Data JPA + SpringMVC --> Spring全家桶2.0 潮流
Spring Cloud(微服务框架,单体工程拆分成很多个小(微)工程,订单服务、用户服务等)
dubbo(阿里巴巴微服务框架、hsf框架)
[理解]SpringMVC的处理流程
原始Servlet方式
一个项目中有很多个servlet,每个servlet负责不同的业务或者功能,前台请求各个servlet。
好比自己去找水电工、木工等。
SpringMVC全局只有一个servlet,这个servlet就好比装修队的头儿
SpringMVC的入门案例
入门案例需求
浏览器输入url发起请求,该url请求被SpringMVC框架拦截处理,把后台服务器的当前时间输出到jsp页面显示
入门案例实现分析
jsp页面(显示当前系统时间)
前端控制器dispatcherServlet在web.xml中配置
写Handler获取当前系统时间(这里的Handler就是Controller)
@Controller标识处理类,并配置扫描
入门案例步骤
使用骨架创建web应用,配置pom.xml
4.0.0
com.itheima.springmvc
hm328_springmvc01_main
1.0-SNAPSHOT
war
hm328_springmvc01_main Maven Webapp
http://www.example.com
junit junit 4.12 test <!--引入spring框架-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--引入springmvc模块-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--引入web开发所需要的两个jar,往往一起引入即可,start-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0</version>
<!--使用范围provide,只在开发、编译阶段有效,打包之后是由服务器环境提供-->
<scope>provided</scope>
</dependency>
<!--引入web开发所需要的两个jar,往往一起引入即可,end-->
hm328_springmvc01_main
maven-clean-plugin 3.0.0
maven-resources-plugin 3.0.2 maven-compiler-plugin 3.7.0 maven-surefire-plugin 2.20.1 maven-war-plugin 3.2.0 maven-install-plugin 2.5.2 maven-deploy-plugin 2.8.2
result.jsp页面开发
<%@ page isELIgnored=“false” contentType=“text/html;charset=UTF-8” language=“java” %>
<!--自动注册最优最合适的处理器适配器和处理器映射器-->
<mvc:annotation-driven/>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
入门案例执行过程
tomcat启动加载读取web.xml
进一步读取到web.xml中配置的前端控制器DispatcherServlet
DispatcherServlet会读取到springmvc.xml,进一步去实例化DefaultController对象
当url请求到来时,首先被DispatcherServlet前端控制器拦截,然后前端控制器去找能够处理当前url的处理器Handler(根据@RequestMapping的配置)
jsp页面从request域当中获取到变量,进行显示
[理解]SpringMVC架构
框架结构
架构流程
第一步:用户发送请求至前端控制器DispatcherServlet
第二步:DispatcherServlet收到请求调用HandlerMapping处理器映射器
第三步:处理器映射器根据请求Url找到具体的Handler(后端控制器),生成处理器对象及处理器拦截器(如果有则生成)一并返回DispatcherServlet
第四步:DispatcherServlet调用HandlerAdapter处理器适配器去调用Handler
第五步:处理器适配器执行Handler
第六步:Handler执行完成给处理器适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回 ModelAndView,ModelAndView 是SpringMVC 框架的一个底层对象,包括 Model 和 View
第八步:前端控制器请求视图解析器去进行视图解析
根据逻辑视图名来解析真正的视图。
第九步:视图解析器向前端控制器返回View
第十步:前端控制器进行视图渲染
就是将模型数据(在 ModelAndView 对象中)填充到 request 域
第十一步:前端控制器向用户响应结果
组件说明
DispatcherServlet:前端控制器
接收用户请求,响应结果,相当于*处理器,DispatcherServlet是整个流程控制的中心,由它调用其它组件完成用户请求的处理。DispatcherServlet的存在降低了组件之间的耦合性。
HandlerMapping:处理器映射器
理解为一个Map<url,Hanlder>
HandlerMapping负责根据用户请求的Url找到Handler即处理器,SpringMVC提供了不同的映射器来实现不同的映射方式,例如:实现接口方式,注解方式等。
Handler:处理器
在SpringMVC当中有两层意思:Controller或者Controller当中的方法
Handler相对于前端控制器DispatcherServlet来说是后端控制器,执行具体业务处理的,它在DispatcherServlet的控制下处理用户的具体请求。
HandlAdapter:处理器适配器
不同的接口类型转换成usb,体现了万物归一的思想
通过HandlerAdapter对Handler处理器进行执行,这是适配器模式的应用。
ViewResolver:视图解析器
ViewResolver进行视图解析,首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象。
View:视图
SpringMVC框架提供了很多的View视图类型的支持,包括:jsp、freemarkerView等。我们最常用的视图就是jsp
注意:在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器称为SpringMVC的三大组件。
需要我们开发的组件有handler(后台的处理逻辑)、view(前端的显示页面)
配置mvc:annotation-driven
SpringMVC对于三大件默认在底层已经进行了注册和使用(三大件已经存在于SpringMVC的运行机制中),默认使用的三大件已经过时了(虽然过时,但是依然能够保证程序运行的),建议我们使用更好更合适的三大件,只需要在SpringMVC的配置文件中添加一个标签mvc:annotation-driven,配置完成后会自动注册最合适的三大件
[掌握]RequestMapping使用
多个URL路径映射到同一个Handler(同一个方法)
添加到类上面(分类管理,限定类中方法访问的前缀),一看到url,就知道这个url所处理的业务领域
属性限定请求方法,请求的url相同,请求方式(get/post)不同进入不同方法处理
访问的url是一样的(Handler名字是一样的),但是我根据你不同的请求方式(get/post)进入不同的方法处理
请求的url一样,但是请求方式不一样(get/post)
/*
- 用例:url相同,根据请求方式(get/post)不同进入不同方法处理
- */
@RequestMapping(value = “gotoResultSameUrl”,method = {RequestMethod.GET})
public ModelAndView gotoResultSameUrlGet(ModelAndView modelAndView) {
Date date = new Date();
modelAndView.addObject(“nowDate”,date + “—>>>gotoResultSameUrlGet”);
modelAndView.setViewName(“result”);
return modelAndView;
}
/*
- 用例:url相同,根据请求方式(get/post)不同进入不同方法处理
- */
@RequestMapping(value = “gotoResultSameUrl”,method = {RequestMethod.POST})
public ModelAndView gotoResultSameUrlPost(ModelAndView modelAndView) {
Date date = new Date();
modelAndView.addObject(“nowDate”,date + “—>>>gotoResultSameUrlPost”);
modelAndView.setViewName(“result”);
return modelAndView;
}
属性限定请求参数,支持简单的表达式语法
url一样,根据携带参数的不同进入不同的方法处理
url相同,请求方式相同,请求参数不同进入不同hanlder方法处理
param1:表示请求必须包含名为 param1 的请求参数
!param1:表示请求不能包含名为 param1 的请求参数
param1 != value1:表示请求包含名为 param1 的请求参数,但其值不能为 value1
{“param1=value1”, “param2”}:请求必须包含名为 param1 和param2 的两个请求参数,且 param1 参数的值必须为 value1
[掌握]请求参数绑定(接收)
默认支持Servlet API作为方法参数
绑定简单类型参数
参数类型推荐使用包装数据类型,因为基础数据类型不可以为null
整型:Integer、int
字符串:String
单精度:Float、float
双精度:Double、double
布尔型:Boolean、boolean
说明:对于布尔类型的参数,请求的参数值为true或false。或者1或0
绑定简单数据类型参数,只需要直接形参声明
注意:形参的参数名和传递的参数名保持一致
建议使用包装类型
参数绑定两步骤:1、从request中getParameter;2、根据形参定义的参数类型进行类型转换和赋值
@RequestParam使用
当形参和传递的参数名称不一致时使用RequestParam进行手动映射,类似于Mybatis当中国的resultMap的作用
/**
- @RequestParam:从请求中把某一个参数取出赋值给当前形参
- value属性:指定从请求中获取哪个参数赋值给当前形参
- defaultValue:默认值,如果获取的参数值为空,则取该默认值(场景:分页的第一页)
- @param modelAndView
- @param id
- @return
*/
@RequestMapping(value = “sendSimpleParams2”)
public ModelAndView sendSimpleParams2(ModelAndView modelAndView,@RequestParam(value = “ids”,defaultValue = “3”) Integer id) {
Date date = new Date();
modelAndView.addObject(“nowDate”, date + " id==>>" + id);
modelAndView.setViewName(“result”);
return modelAndView;
}
绑定pojo类型参数
直接形参声明pojo即可接收
要求:传递的参数名必须和pojo属性名对应
/**
- 绑定pojo类型参数,只需要直接在形参中声明pojo即可
- 要求:请求参数名和pojo属性名保持一致
- @param modelAndView
- @param user
- @return
*/
@RequestMapping(“sendPojo”)
public ModelAndView sendPojo(ModelAndView modelAndView,User user) {
Date date = new Date();
modelAndView.addObject(“nowDate”, date + " user==>>" + user);
modelAndView.setViewName(“result”);
return modelAndView;
}
重点在于传参参数的命名(和pojo属性名保持一致)
绑定pojo包装对象参数
重点在于传参参数的命名
pojo包装对象首先就是一个普通的pojo,就应该按照上面绑定pojo的要求来,然后进一步处理
传参时参数名,首先应该定位到包装对象的属性名,如果不能确定数据,通过属性.的方式进一步锁定即可
前台传参
传递(绑定)pojo包装类型参数
测试后台接收
/**
- 绑定pojo包装类型参数,只需要直接在形参中声明pojo包装对象即可
- 注意:绑定pojo包装类型参数,重点在于前台参数参数名的取法,首先定位到pojo的属性,然后通过.的方式进一步确定
- @param modelAndView
- @return
*/
@RequestMapping(“sendPojoPackage”)
public ModelAndView sendPojoPackage(ModelAndView modelAndView, QueryVo queryVo) {
Date date = new Date();
modelAndView.addObject(“nowDate”, date + " queryVo==>>" + queryVo);
modelAndView.setViewName(“result”);
return modelAndView;
}
绑定pojo包含集合类型参数
传递绑定集合类型(List/Map),作为POJO的一个属性来传递
前端页面
测试用例USE_CASE10:SpringMVC接收集合(List)类型参数
</table>
<input type="submit" value="批量修改提交">
</form>
主键 | 用户名 | 性别 |
测试用例USE_CASE11:SpringMVC接收集合(Map)类型参数
</table>
<input type="submit" value="批量修改提交">
</form>
主键 | 用户名 | 性别 |
pojo
后端handler
/**
- 用例:springmvc绑定list集合
- 重点在于前端参数的取值方式
- @param modelAndView
- @return
*/
@RequestMapping(“sendList”)
public ModelAndView sendList(QueryVo queryVo, ModelAndView modelAndView) {
Date date = new Date();
modelAndView.addObject(“nowDate”,date + “—>>>queryVo:” + queryVo);
modelAndView.setViewName(“result”);
return modelAndView;
}
/**
- 用例:springmvc绑定map集合
- 重点在于前端参数的取值方式
- @param modelAndView
- @return
*/
@RequestMapping(“sendMap”)
public ModelAndView sendMap(QueryVo queryVo, ModelAndView modelAndView) {
Date date = new Date();
modelAndView.addObject(“nowDate”,date + “—>>>queryVo:” + queryVo);
modelAndView.setViewName(“result”);
return modelAndView;
}
自定义类型转换器
自定义类型转换器
package com.itheima.springmvc.utils;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
- 自定义类型转换器实现改接口,Converter<S,T>
- S:source,转换前的数据类型
- T:target,转换后的数据类型
*/
public class DateConverter implements Converter<String,Date> {
@Override
public Date convert(String source) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(“yyyy-MM-dd”);
try {
return simpleDateFormat.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
注册自定义类型转换器
[了解]消息头相关的两个注解
@RequestHeader
@CookieValue
作业
笔记过一遍
练习要求“掌握”的部分
附录
附录一:乱码问题处理
Post请求乱码,web.xml中加入过滤器