SpringMVC
第一章 SpringMVC介绍
1.1 JavaEE经典三层架构
- 表现层(Web层)
整个表现层负责接收客户端请求并响应结果给客户端。(Http请求)
具体说来,表现层=View视图层+Controller控制层。Controller层负责接收请求、转发请求给Service层、跳转视图页面
servlet—>Struts(过滤器)—>SpringMVC
- 业务层(Service层)
负责业务逻辑处理,和项目需求息息相关(比如转账业务)。
Spring—>SpringBoot(全注解)
主要涉及逻辑 : 异常处理 参数处理 声明式事务AOP
- 持久层(Dao层)
和数据库交互,对数据表进行增删改查
JDBC—> JdbcTemplate —> DButils —>MyBatis—>Spring Data JPA
主流:SSM —> 潮流:SSS(Spring全家桶)
1.2 MVC模式
M即Model模型,V即View视图,C即Controller控制器。
Model的广义和狭义之说
广义:Model = Service层 +Dao层,由这两层来产生数据模型
狭义:Model 就是数据模型本身,就是Controller和View之间传递的数据,在这种说法下,MVC又可归为Web层。
MVC模式,是JavaEE经典三层中的Web层开发模式
1.3 SpringMVC概述
- SpringMVC是什么
- SpringMVC是一个轻量级的Web表现层框架,用来写Controller接收请求跳转页面的,它是Spring框架的一部分。
- SpringMVC是对Servlet的封装和增强,简化了servlet的操作。它已经超越了Struts,成为目前最优秀的表现层框架。
- SpringMVC能做什么
- 接收请求
- 跳转页面
- 会话控制
- 过滤拦截
- 异步交互
- 文件上传
- 文件下载
- 数据校验
- 类型转换
- 什么时候使用SpringMVC?
- 当你觉得servlet繁琐的时
1.4 SpringMVC的优势
SpringMVC 是 Spring 为表述层开发提供的一整套完备的解决方案。在表述层框架历经 Strust、WebWork、Strust2 等诸多产品的历代更迭之后,目前业界普遍选择了 SpringMVC 作为 Java EE 项目表述层开发的首选方案。之所以能做到这一点,是因为 SpringMVC 具备如下显著优势:
- Spring 家族原生产品,与 IOC 容器等基础设施无缝对接
- 表述层各细分领域需要解决的问题全方位覆盖,提供全面解决方案
- 内部组件化程度高,可插拔式组件即插即用,想要什么功能配置相应组件即可
- 性能卓著,尤其适合现代大型、超大型互联网项目要求
- 操作特简单,性能特别高,灵活性特别强
第二章 SpringMVC快速入门案例
1.1 SpringMVC的处理流程
之前:request请求到servlet,一个项目中有很多servlet,不同serlvet处理不同的事情,好比很多年前装修,业主需要直接把需求告知水工、电工、木工等。现在我们直接把需求告知包工头,包工头具体分发任务给下面的小弟(水工、电工、木工),我们不需要直接和其他人交涉。
前端控制器就类似于上面的包工头,不干具体的活,只负责接收请求,分发请求,反馈结果
SpringMVC全局只需要一个servlet。
1.2 案例需求
浏览器输入url发起请求,该url请求被SpringMVC框架拦截处理,把后台服务器的当前时间输出到jsp页面显示
入门案例实现分析
- jsp页面(显示当前系统时间)
- 前端控制器dispatcherServlet在web.xml中配置
- 写Handler获取当前系统时间(这里的Handler就是Controller)
- @Controller标识处理类,并配置扫描
springmvc.xml配置
<!--包扫描-->
<context:component-scan base-package="com.atguigu"/>
<!--自动注册最优最合适的处理器适配器和处理器映射器-->
<mvc:annotation-driven/>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
HelloController类
@Controller
public class HelloController {
//请求映射,浏览器的请求地址
@RequestMapping("sayHello")
//ModelAndWiew模型和视图对象
public ModelAndView sayHello(ModelAndView modelAndView){
//键值对存储request域对象
modelAndView.addObject("now",new Date());
//要转发的页面
modelAndView.setViewName("result");
return modelAndView;
}
}
web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1" metadata-complete="true">
<!--配置前端控制器,接收客户端的所有请求地址为do的-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--Servlet初始化参数,加载SpringMVC配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
1.3 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
HandlerMapping负责根据用户请求的Url找到Handler即处理器,SpringMVC提供了不同的映射器来实现不同的映射方式,例如:实现接口方式,注解方式等。
Handler:处理器
在SpringMVC当中有两层意思:Controller或者Controller当中的方法 Handler相对于前端控制器DispatcherServlet来说是后端控制器,执行具体业务处理的,它在 DispatcherServlet的控制下处理用户的具体请求。
HandlAdapter:处理器适配器
不同的接口类型转换成usb,体现了万物归一的思想
通过HandlerAdapter对Handler处理器进行执行,这是适配器模式的应用。
ViewResolver:视图解析器
ViewResolver进行视图解析,首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象。
View:视图
SpringMVC框架提供了很多的View视图类型的支持,包括:jsp、html等。
注意:在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器称为SpringMVC的三大组件。
需要我们开发的组件有handler、view
1.4配置 mvc:annotation-driven
处理器映射器、处理器适配器我们在入门程序没有配置,也可以用,因为SprigMVC默认会给我们加载对应器,但是默认加载的器的版本Spring3.x之后已经不推荐使用了,推荐使用更好的。
我们使用很简单配置一个标签即可,SpringMVC会自动注册最合适的处理器映射器、处理器适配器.
第三章 RequestMapping注解
从注解名称上我们可以看到,@RequestMapping注解的作用就是将请求的 URL 地址和处理请求的方式关联起来,建立映射关系。
SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的方法来处理这个请求。
@RequestMapping注解的属性 value,数据类型是String[],可以同时配置多个请求地址
1.1 精确匹配模式
在@RequestMapping注解指定 URL 地址时,不使用任何通配符,按照请求地方进行精确匹配。
<a href="sayHello">HelloWorld</a><br/>
@RequestMapping("/sayHello")
1.2 模糊匹配模式
在@RequestMapping注解指定 URL 地址时,通过使用通配符,匹配多个类似的地址。
<h3>测试@RequestMapping注解匹配方式</h3>
<a href="/fruit/apple">@RequestMapping模糊匹配[apple]</a><br/>
<a href="/fruit/orange">@RequestMapping模糊匹配[orange]</a><br/>
<a href="/fruit/banana}">@RequestMapping模糊匹配[banana]</a><br/>
@RequestMapping("/fruit/*")
1.3 注解作用域类上
添加到类上面(分类管理,限定类中方法访问的前缀)
<h3>测试@RequestMapping注解标记在类上</h3>
<a href="/user/login">用户登录</a><br/>
<a href="/user/register">用户注册</a><br/>
<a href="/user/logout">用户退出</a><br/>
@RequestMapping("useer")
public class User{
@RequestMapping("login")
public ModelAndWiew login(ModelAndWiew modelAndWiew){
return null;
}
@RequestMapping("register")
public ModelAndWiew register(ModelAndWiew modelAndWiew){
return null;
}
@RequestMapping("logout")
public ModelAndWiew logout(ModelAndWiew modelAndWiew){
return null;
}
}
1.4 注解的属性method
method的属性的数据类型是RequestMethod枚举类型的数组,该枚举中定义了8个静态常量。
HTTP 协议定义了八种请求方式,在 SpringMVC 中封装到了下面这个枚举类:
public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}
前面代码中,只要求请求地址匹配即可,现在附加了请求方式后,还要求请求方式也必须匹配才可以。
<h3>测试@RequestMapping注解限定请求方式</h3>
<a href="/emp}">同地址GET请求</a><br/>
<form action="/emp" method="post">
<button type="submit">同地址POST请求</button>
</form>
<br/>
- 处理 GET 请求:
@RequestMapping(value = "/emp", method = RequestMethod.GET)
public ModelAndWiew empGet(ModelAndWiew modelAndWiew) {
return modelAndWiew;
}
- 处理 POST 请求:
@RequestMapping(value = "/emp", method = RequestMethod.POST)
public ModelAndWiew empPost(ModelAndWiew modelAndWiew) {
return modelAndWiew;
}
@RequestMapper注解中,不写属性method的,那么可以接收任何请求方式!
原版 | 进阶版 |
---|---|
@RequestMapping(value = “/emp”, method = RequestMethod.GET) |
@GetMapping(“/emp”) |
@RequestMapping(value = “/emp”, method = RequestMethod.POST) |
@PostMapping(“/emp”) |
除了 @GetMapping、@PostMapping 还有下面几个类似的注解:
第四章 请求参数绑定
1.1 默认支持ServletAPI
可以将原生HttpServletRequest和HttpServetResponse接口作为参数,传递到handler的方法中
@RequestMapping("servlet")
public ModelAndView servletParam(HttpServletRequest request, HttpServletResponse response,ModelAndView modelAndView){
String name = request.getParameter("name");
System.out.println("name = " + name);
return modelAndView;
}
1.2 一键一值方式
绑定简单数据类型参数,只需要直接形参声明
注意:形参的参数名和传递的参数名保持一致,建议使用包装类型
<form method="post" action="/paramsName.do">
<input type="text" name="username">
<input type="text" name="password">
<input type="submit">
</form>
@RequestMapping("paramsName")
public ModelAndView paramsName(String username,String password,ModelAndView modelAndView){
System.out.println("username = " + username);
System.out.println("password = " + password);
return modelAndView;
}
- 请求参数乱码问题,需要配置过滤器
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.3 RequestParam注解
当形参和传递的参数名称不一致时使用RequestParam进行手动映射,类似于Mybatis当中国的resultMap的作用。
<form method="post" action="/paramsName.do">
<input type="text" name="user">
<input type="text" name="password">
<input type="submit">
</form>
@RequestMapping("paramsName")
public ModelAndView paramsName(@RequestParam("user") String username, String password, ModelAndView modelAndView){
System.out.println("username = " + username);
System.out.println("password = " + password);
return modelAndView;
}
1.4 一键多值参数
<form action="/paramsList.do" method="post">
请选择你最喜欢的球队:
<input type="checkbox" name="team" value="Brazil"/>巴西
<input type="checkbox" name="team" value="German"/>德国
<input type="checkbox" name="team" value="French"/>法国
<input type="checkbox" name="team" value="Holland"/>荷兰
<input type="checkbox" name="team" value="Italian"/>意大利
<input type="checkbox" name="team" value="China"/>中国
<br/>
<input type="submit" value="保存"/>
</form>
@RequestMapping("paramsList")
public ModelAndView paramsList( @RequestParam("team") List<String> teamList, ModelAndView modelAndView){
System.out.println(teamList);
return modelAndView;
}
1.5 请求参数绑定pojo对象
- 直接形参声明pojo即可接收
- 要求:传递的参数名必须和pojo属性名对应
<form method="post" action="/paramsPojo.do">
<input type="text" name="username">
<input type="text" name="password">
<input type="submit">
</form>
@RequestMapping("paramsPojo")
public ModelAndView paramsPojo(User user,ModelAndView modelAndView){
System.out.println(user);
return modelAndView;
}
1.6 请求参数绑定pojo对象的包装对象
- 重点在于传参参数的命名
- pojo包装对象首先就是一个普通的pojo,就应该按照上面绑定pojo的要求来,然后进一步处理,传参时参数名,首先应该定位到包装对象的属性名,如果不能确定数据,通过属性.的方式进一步锁定即可
<form method="post" action="/paramsPojoVo.do">
<input type="text" name="user.username">
<input type="text" name="user.password">
<input type="submit">
</form>
@RequestMapping("paramsPojoVo")
public ModelAndView paramsPojoVo(QueryVo queryVo, ModelAndView modelAndView){
System.out.println(queryVo);
return modelAndView;
}
1.7 绑定List集合包装pojo对象
<form action="/paramsPojoVoList.do" method="post">
<table>
<tr>
<td>用户名</td>
<td>密码</td>
</tr>
<tr>
<td>
<input type="text" name="userList[0].username">
</td>
<td>
<input type="text" name="userList[0].password">
</td>
</tr>
<tr>
<td>
<input type="text" name="userList[1].username">
</td>
<td>
<input type="text" name="userList[1].password">
</td>
</tr>
<tr>
<td>
<input type="text" name="userList[2].username">
</td>
<td>
<input type="text" name="userList[2].password">
</td>
</tr>
</table>
<input type="submit">
</form>
@RequestMapping("paramsPojoVoList")
public ModelAndView paramsPojoVoList(QueryVo queryVo,ModelAndView modelAndView){
System.out.println("queryVo = " + queryVo);
return modelAndView;
}
1.8 绑定Map集合包装pojo对象
<form action="/paramsPojoVoMap.do" method="post">
<table>
<tr>
<td>用户名</td>
<td>密码</td>
</tr>
<tr>
<td>
<input type="text" name="userMap['k1'].username">
</td>
<td>
<input type="text" name="userMap['k1'].password">
</td>
</tr>
<tr>
<td>
<input type="text" name="userMap['k2'].username">
</td>
<td>
<input type="text" name="userMap['k2'].password">
</td>
</tr>
<tr>
<td>
<input type="text" name="userMap['k3'].username">
</td>
<td>
<input type="text" name="userMap['k3'].password">
</td>
</tr>
</table>
<input type="submit">
</form>
@RequestMapping("paramsPojoVoMap")
public ModelAndView paramsPojoVoMap(QueryVo queryVo,ModelAndView modelAndView){
System.out.println("queryVo = " + queryVo);
return modelAndView;
}
1.9 RequestHeader注解
- 获取请求头信息
- 属性value,属性值为请求头的键名
@RequestMapping("sendParamsHeader")
public ModelAndView sendParamsHeader(@RequestHeader("user-Agent") String header, ModelAndView modelAndView){
System.out.println(header);
return modelAndView;
}
2.0 CookieValue注解
- 获取浏览器携带的Cookie
- 属性value,属性值是Cookie的键名
@RequestMapping("paramsCookie")
public ModelAndView sendParamsCookie(@CookieValue("JSESSIONID") String sessionId, ModelAndView modelAndView){
System.out.println(sessionId);
return modelAndView;
}