文章目录
1. SpringMVC概述
1.1 MVC思想
MVC是一种软件架构的思想, 将软件按照模型、视图、控制链来划分
- M: model,模型层,指工程中的JavaBean,作用是处理数据
- V: View,视图层,指工程中的jsp或html页面,作用是与用户进行交互,展示数据
- C:Controller,控制层,指工程中的Servlet,作用是接收请求和响应浏览器
JavaBean分为两类
- 一类是实体bean, 专门存储业务数据
- 一类为业务处理bean, 指Service或dao对象, 专门助理业务逻辑和数据访问
MVC的工作流程
用户通过视图层发送请求到服务器, 在服务器中请求被Controller接收, Controller调用相应的Model层处理请求, 处理完毕后将结果返回到Controller, Controller再根据请求处理的结果找到相应的View视图, 渲染数据后最后响应给浏览器。
1.2 SpringMVC简述
- Spring的后续产品, 是Spring的一个子项目
- 是Spring为表述层(前台页面和后台Servlet)提供的一套完备的解决方案。
1.3 SpringMVC特点
- 基于原生Servlet, 通过了功能强大的前端控制器DispatcherServlet, 对请求和响应进行统一处理
- Spring家族原生产品, 与IOC容器等基础设备无缝对接
- 性能卓越, 代码简洁
1.4 SpringMVC开发环境搭建
-
创建一个web工程
-
在Maven中引入依赖环境
-
配置web.xml
默认配置方式: 这种配置作用下, SpringMVC的配置文件位于WEB-INF下,默认名称为< serlvet-name >-servlet.xml, 例如下图: SpringMVC-servlet.xml
扩展配置方式(最优):使用这种方式可以将配置文件移动至想要的路径下
-
创建请求控制器
-
配置SpringMVC文件(注意引入名称空间)
Thymeleaf的写法
普通写法
-
编写请求匹配
当我访问资源路径为"/"时, 浏览器请求会和这个方法匹配返回字符串index到Spring配置文件中进行解析,
经过解析, 结果为 "/WEB-INF/templates/index.html"并自动跳转。
访问资源路径为target.html的文件
2. @RequestMapping
2.1 RequestMapping的基本介绍
RequestMapping(请求映射), 将请求和处理请求的控制器方法关联起来, 建立映射关系, SpringMVC接受到请求, 来映射关系中找到对应的方法来处理
2.2 RequestMapping的基本位置
-
当映射地址有多个控制方法会报错
-
标识一个类, 设置映射请求的请求路径的初始信息
-
标识一个方法, 设置映射请求的请求路径的具体信息
2.3 RequestMapping的属性
-
value
- 该值必须设置, 至少通过请求地址匹配请求映射。
- String[]类型数组, 表示可以有多个请求地址来匹配这个映射。
-
method: 可选项, 不设置的话任何形式的请求都能匹配
-
method属性是一个RequestMapping类型的数组, 表示这个请求映射可以有多个请求方式。
-
如果请求地址满足value, 但是请求方式不满足method, 则浏览器报405错误。
-
对于指定请求方式的控制器方法, SpringMVC提供了@RequestMapping的派生注解。
(1) @GetMapping
(2) @PostMapping
(3) @PutMapping
(4) @DeleteMapping
注意: 目前浏览器只能处理get和post请求, 表单提交时如果设置了其他请求方式的字符串则默认为get请求, 处理put和delete看后面的restful部分的笔记。
-
-
params(了解)
-
通过请求参数匹配映射。
-
params属性是一个String[] 数组, 可以通过四种表达式设置请求参数和请求映射的匹配关系
(1) param
(2) !param
(3) param=“value”
(4) param!=“value”当username = admin password = 123456时, 匹配成功
-
-
headers(了解)
-
根据请求头匹配映射。
-
是一个String[] 数组, 可以通过类似params的四种表达式来进行设置请求头和请求映射关系的匹配关系。
-
当满足value和method, 但是不满足headers, 浏览器报404。
-
2.5 ant风格的路径设置
? : 表示任意的单个字符
* : 表示任意的0个或多个字符
** : 表示任意的一层或多层目录
注意: 使用**时, 只能使用/**/xxx的方式。
演示
演示**
2.6 SpringMVC支持路径中的占位符(重要)
SpringMVC路径中的占位符常用于restful风格中, 当请求路径中将某些数据通过路径的方式传输到服务器中, 就可以在相应的@RequestMapping注解的value属性中通过占位符{xxx}表示传输的数据, 再通过@PathVariable注解,将占位符所表示的数据赋值给控制器方法的形参。
3. Spring获取请求参数
3.1 通过Servlet方式
SpringMVC可以使用原生Servlet方式来获取请求参数
3.2 通过控制器的形参
当有多个同名参数的情况, 可以通过使用字符串形参或字符串数组形参来获取, 若使用的是字符串形参, 多值之间通过,拼接起来
也可以通过原生Servlet的getParams()特定方法返回一个数组, 该数组就是参数数组
3.3 @RequestParam
@RequestParam是将请求参数和控制器方法的形参创建映射关系
@RequestParam有三个属性
- value :指定为形参赋值的请求参数的参数名
- required :是否包含该参数,默认为true,表示该请求路径中必须包含该参数,如果不包含就报错。
- defaultValue:默认参数值,如果设置了该值,required=true将失效,
自动为false,如果没有传该参数,就使用默认值
注意: 当设置required为true时, 没有传输该请求参数, 也没有设置默认值, 页面报错400, 对于默认值来说, 不管required怎么设置, 有请求参数就用请求参数, 没有就用默认值为形参赋值。
3.4 @RequestHeader、@CookieValue
- @RequestHeader是将请求头信息和控制器方法的形参创建映射关系
- @CookieValue是将Cookie数据和控制器方法的形参创建映射关系
- 有三个属性基本同@RequestParam
3.5 通过POJO获取请求参数
3.6 解决获取请求参数的乱码问题
SpringMVC已经提供好了字符编码的过滤器
4. 域对象共享数据
4.1 通过Servlet向request域对象共享数据
4.2 通过ModelAndView向request域对象共享数据
4.3 使用Model向request域对象共享数据
4.4使用Map向request域对象共享数据
4.5 使用ModeMap向request域对象共享数据
4.6 向Session域中共享数据
直接使用Servlet原生方式
4.7 向Application域共享数据
直接使用Servlet原生方式
4.8 Model、ModelMap、Map的关系
model、modelMap、map类型的参数其实本质都是BindingAwareModelMap类型的
5. SpringMVC视图
- SpringMVC的视图是View接口, 视图的作用渲染数据, 将模型model中的数据展示用户
- SpringMVC视图的种类很多, 默认有转发视图和重定向视图, 当工程引入jstl的依赖, 转发视图会自动转换为jstlView
- 若使用的视图技术为thymeleaf, 在SpringMVC的配置文件中配置了thymeleaf的视图解析器, 由此视图解析器解析之后得到的是ThymeleafView
5.1 ThymeleafView
当控制器方法中所设置的视图名称没有任何前缀时, 此时的视图名称会被springMVC配置文件中所配置的视图解析器解析, 视图名称拼接视图前缀好后缀所得到的最终路径, 会通过转发的方式实现跳转
5.2 转发视图
SpringMVC中默认的转发视图是InternalResourceView
SpringMVC中创建转发视图的情况
当控制器方法中所设置的视图名称以“forward”为前缀时, 创建InternalResourceView视图,
此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析, 而是会将前缀"forward"去掉,
剩余部分作为最终路径通过转发的方式实现跳转。
转发, 地址栏无变动
5.3 重定向视图
SpringMVC中默认的重定向视图是RedirectView
当控制器方法中所设置的视图名称以"redirect"为前缀时, 创建RedirectView视图,
此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析, 而是会将前缀"redirect"去掉, 剩余部分作为最终路径通过重定向的方式实现跳转
重定向, 地址栏变化
5.4 视图控制器View - Controller
当控制器方法中, 只实现页面跳转功能, 即只需要设置视图名称时, 可以将处理器方法使用view-controller标签进行表示
注意引入mvc名称空间
注意: 当使用mvc:view-controller标签在springMVC文件中配置时, 控制器中所有的请求映射全部失效, 需要在springMVC文件中加入一个配置来避免这种情况
开启mvc的注解驱动, 开启后便可同时使用两种方式来配置请求映射
6. RESTFul
6.1 RESTFul简介
Representational State Transfer 表现层资源状态转移
6.2 RESTFul的实现
具体来说, 就是HTTP协议里面, 4个表示操作方式的动词: GET、POST、PUT、DELETE
分别对应4种操作, GET用来获取资源, POST用来新建资源, PUT用来更新资源, DELETE用来删除资源
REST风格提倡URL地址使用统一的风格设计, 从前到后各个单词之间用\分开, 不使用问号键值对方式携带请求参数, 而是将要发送给服务器的数据作为URL地址的一部分, 以保证整体风格的一致性
模拟RESTFul模拟用户资源的增删改查
路径 | 方式 | 作用 |
---|---|---|
/user | GET | 查询所有用户信息 |
/user/1 | GET | 根据用户id查询用户信息 |
/user | POST | 添加用户信息 |
/user/1 | DELETE | 删除用户信息 |
/user | PUT | 修改用户信息 |
模拟GET和POST请求做查询、添加操作
HiddenHttpMetHodFilter处理PUT和DELETE做修改、删除操作
这一段看后面的RESTFul对员工信息的修改和删除操作, 这里只是一个简单介绍
- 首先配置HiddenHttpMetHodFilter过滤器
- 前端通过隐藏域来设置PUT和DELETE请求
注意: 在配置web.xml时hiddenHttpMethodFilter应该在CharactorEncodingFilter之后写好, 否则是无效的, 因为在进行编码过滤前不能获取任何请求方式参数。
6.3 RESTFul案例
6.3.1 资源准备
- 准备dao测试数据(未使用数据库)
package com.atguigu.mvc.dao;
import com.atguigu.mvc.bean.Employee;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Repository
public class EmployeeDao {
/*
* 准备了一些模拟数据用于RESTFul资源操作
* */
private static Map<Integer, Employee> employees = null;
private static Integer initId = 1006;
static{
employees = new HashMap<>();
employees.put(1001,new Employee(1001,"E-AA","aa@qq.com",1));
employees.put(1002,new Employee(1002,"E-BB","bb@qq.com",2));
employees.put(1003,new Employee(1003,"E-CC","cc@qq.com",1));
employees.put(1004,new Employee(1004,"E-DD","dd@qq.com",2));
employees.put(1005,new Employee(1005,"E-EE","ee@qq.com",1));
employees.put(1006,new Employee(1006,"E-FF","ff@qq.com",2));
employees.put(1007,new Employee(1007,"E-JJ","jj@qq.com",1));
employees.put(1008,new Employee(1008,"E-HH","hh@qq.com",2));
employees.put(1009,new Employee(1009,"E-II","ii@qq.com",1));
employees.put(1010,new Employee(1010,"E-GG","gg@qq.com",2));
}
// 修改和增加数据
public void save(Employee employee) {
if (employee.getId() == null) {
employee.setId(initId++);
}
employees.put(employee.getId(), employee);
}
// 获取所有数据
public Collection<Employee> getAll(){
return employees.values();
}
// 根据id查询数据
public Employee get(Integer id){
return employees.get(id);
}
// 根据id删除数据
public void delete(Integer id){
employees.remove(id);
}
}
- 准备bean
package com.atguigu.mvc.bean;
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender;
public Employee(){}
public Employee(Integer id, String lastName, String email, Integer gender) {
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", gender=" + gender +
'}';
}
}
- 写控制层
package com.atguigu.mvc.controller;
import com.atguigu.mvc.dao.EmployeeDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class EmployeeController {
@Autowired
private EmployeeDao employeeDao;
}
6.3.2 功能清单
注: 这里发现个问题, 如果使用原始方式InternalResourceViewResolver加前后缀的话, html不太好使, jsp则没有问题
需要对代码做一些改进
功能 | URL地址 | 请求方式 |
---|---|---|
访问首页 | / | GET |
查询全部数据 | /employee | GET |
删除 | /employee/1 | DELETE |
跳转到添加数据页面 | /toAdd | GET |
执行保存 | /employee | POST |
跳转到更新数据页面 | /employee/1 | GET |
执行更新 | /employee | PUT |
访问首页演示
访问首页只涉及到页面的跳转, 所以设置view-controller即可
-
写首页
-
配置view-controller
-
开启注解驱动
查询全部数据列表演示
控制层通过自动装配@AutoWired来装配Dao对象
前端
删除功能演示
删除是以超链接提交给表单的方式来发送请求, 而超链接的默认请求方式是GET, 我们需要把它转化成POST, 通过表单传过去DELETE属性才能完成删除功能
-
首先要在web.xml中配置HiddenHttpMethodFilter过滤器, 注意要在编码过滤器的下面写。
-
在spring配置文件中配置对静态资源的访问, 注意:这个标签要配合mvc:annotion-driven一起使用。
-
写控制层内容, 删除后重定向到员工列表页面
-
通过Jquery来将超链接的GET方式修改为POST, 设置点击时提交表单, 注意这里表单中的隐藏域的name属性必须是_method, 否则HiddenHttpMethodFilter会无效
超链接
表单
Jq
注意前端代码的书写顺序, 脚本内容写在后面。
修改功能演示
- 首先要获取修改的员工的ID
- 控制层进行处理
- 在empUpdate页面中进行修改操作
- 提交表单后再次进行控制层操作, 最后重定向回员工列表
- 修改完成
添加功能演示
- 首先是从员工列表页面跳转到添加页面, 这个过程除了跳转不涉及别的操作, 所以直接在spring配置文件中通过mvc:view-controller的方式实现跳转
- 添加员工信息的前端
- 控制层内容, 当表单提交后执行并重定向回员工列表
7. HttpMessageConverter
- HttpMessageConverter, 报文信息转换器, 将请求报文转换为Java对象, 或将Java对象转换为响应报文
- HttpMessageConverter提供了两个注解和两个类型: @RequestBody @ResponseBody RequestEntity ResponseEntity
7.1 @RequestBody注解
@RequestBody可以获取请求体, 需要在控制器方法设置一个形参, 使用@RequestBody进行标识, 当前请求体就会为当前注解所标注的形参赋值
7.2 RequestEntity
RequestEntity封装请求报文的一种类型, 需要在控制器方法的形参中设置该类型的形参, 当前请求的请求报文就会赋值给该形参, 可以通过getHeader()获取请求头信息, 通过getBody()获取请求头信息
7.3 @ResponseBody注解
用于标识一个控制器方法, 可以将该方法的返回值直接作为响应报文的响应体响应到浏览器
ResponseBody处理Json数据
实体类Employee
-
首先要导入Jackson的依赖
-
在SpringMVC的核心配置文件中开启MVC的注解驱动, 此时在HandlerAdaptor中会自动装配一个消息转换器, MappingJackson2HttpMessageConverter, 可以将响应到浏览器的java对象转换为json格式的字符串
-
在处理器方法上使用@ResponseBody注解作为标识
-
将java对象直接作为控制器方法的返回值返回, 就会自动转换为json格式的字符串
-
浏览器中的效果
7.4 ResponseEntity
ResponseEntity用于控制器方法的返回值类型, 该控制器方法的返回值就是响应到浏览器的响应报文
示例: 使用ResponseEntity实现文件下载功能
@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession httpSession) throws IOException {
// 获取ServletContext对象
ServletContext servletContext = httpSession.getServletContext();
// 获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/WEB-INF/static/img/1.jpg");
// 创建输入流
FileInputStream is = new FileInputStream(realPath);
byte[] bytes = new byte[is.available()];
// 将流读到字节数组中
is.read(bytes);
// 创建HttpHeaders对象设置响应头信息
MultiValueMap<String,String> headers = new HttpHeaders();
// 设置下载方以及下载文件的名字
headers.add("Content-Disposition","attachment;filename=1.jpg");
// 设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
// 创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes,headers,statusCode);
// 关闭输入流
is.close();
return responseEntity;
}
效果
7.5 @RestController注解
@RestController注解是springMVC提供的一个符合注解, 标识在控制器的类上, 就相当于为类添加了@Controller注解, 并且为其中的每个方法添加了@ResponseBody注解
8. 文件的上传和下载
下载功能演示参考ResponseEntity
上传功能演示
需要先引入依赖
SpringMVC配置文件中的配置
前端
控制器方法
@RequestMapping(value = "/textUp")
public String textUp(MultipartFile photo,HttpSession httpSession) throws IOException {
String fileName = photo.getOriginalFilename();
// 上传的文件名
ServletContext servletContext = httpSession.getServletContext();
// 获取上下文对象
String photoPath = servletContext.getRealPath("photo");
// 上传的文件的文件路径
File file = new File(photoPath);
// 判断photoPath路径是否真实存在
if(!file.exists()){
file.mkdirs();
// 不存在创建目录
}
String finalPath = photoPath + File.separator+ fileName;
photo.transferTo(new File(finalPath));
return "login";
// 上传完成后跳转到登录页面
}
文件上传成功后会存储在这里
解决文件的重名问题
String fileName = photo.getOriginalFilename();
// 上传的文件名
String suffixName = fileName.substring(fileName.lastIndexOf("."));
// 获取文件的后缀名
String uuid = UUID.randomUUID().toString();
// 获取UUID来作为上传后的文件名前缀 UUID是一堆混乱的字母数字来防止重名
fileName = uuid + suffixName;
System.out.println(fileName);
上传的都是2.jpg, 使用这串代码前和使用后进行对比
9. 拦截器
9.1 拦截器的配置
- SpringMVC中的拦截用于拦截控制器方法的执行, 不会拦截JS、JSP、Html、CSS、Image等等
- SpringMVC中的拦截器需要实现HandlerInterceptor或者继承HandlerInterceptorAdapter类
- SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置
9.2 创建拦截器
写自定义类实现实现HandlerInterceptor或者继承HandlerInterceptorAdapter
- 实现HandlerInterceptor
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 控制器方法执行前执行
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 控制器方法执行后执行
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 渲染视图后执行
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
- 继承HandlerInterceptorAdapter
public class TestInterceptor2 extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
super.afterCompletion(request, response, handler, ex);
}
}
9.3 配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<!--<bean class="com.ma.interceptor.CustomeInterceptor" />-->
<!--拦截器1-->
<!--<ref bean="customInterceptor">-->
<!--拦截器2-->
<mvc:interceptor>
<!--配置拦截器的作用路径-->
<mvc:mapping path="/**"/>
<!--配置不需要拦截的请求路径-->
<mvc:exclude-mapping path=""/>
<!--定义在<mvc:interceptor>下面的表示匹配指定路径的请求才进行拦截-->
<bean class="com.ma.interceptor.Intercptor1"/>
</mvc:interceptor>
<!--拦截器2-->
<mvc:interceptor>
<mvc:mapping path="/hello"/>
<bean class="com.ma.interceptor.Interceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
- mvc:interceptors元素用于配置一组拦截器,基子元素中定义的是全局拦截器,它会拦截所有的请求;而mvc:interceptor元素中定义的是指定路径的拦截器,它会对指定路径下的请求生效。
- mvc:interceptor元素的子元素mvc:mapping用于配置拦截器作用的路径,该路径在其属性path
中定义。如上述代码中 path 的属性值“/**” 表示拦截所有路径,“/hello” 表示拦截所有以 “/hello”
结尾的路径。如果在请求路径中包含不需要拦截的内容,还可以通过mvc:exclude-mapping元素进行配置。 - 注意:mvc:interceptor中的子元素必须按照上述代码中的配置顺序进行编写,即mvc:mapping
mvc:exclude-mapping ,否则文件会报错。
9.4 拦截器的三个抽象方法和多个拦截器之间的执行顺序
- preHandle() 方法:该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;
当其返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等)。 - postHandle()方法:该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。
- afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。
配置多个拦截器
执行代码, 拦截结果如下
可以看到对于preHandle, 拦截器方法的执行顺序是正向的, 而对于postHandle和afterCompletion来说, 是反向的
- 如果每个拦截器的preHandler()都返回true, 此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关, preHandler()会按照配置的顺序执行, 而postHandler()和afterComplation()会按照配置的反序执行
- 若某个拦截器的preHandler()返回了false, preHandler()返回false和它之前的拦截器的preHandler()都会执行, postHandler()都不执行, 返回false的拦截器之前的拦截器的afterComplation()会执行
10. 异常处理器
10.1 基于配置的异常处理
SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口: HandlerExceptionResolver
HandlerExceptionResolver接口的实现类有: DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver
SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver
演示
<!--配置异常处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--配置可能会出现的异常-->
<property name="exceptionMappings">
<props>
<!--
当出现了异常, 跳转到error这个视图
可以配置多个
-->
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
<property name="exceptionAttribute" value="ex">
</property>
<!--将异常信息存到请求域中 通过value取出-->
</bean>
取出效果
10.2 基于注解的异常处理器
使用 @ControllerAdvice 实现全局异常处理, 该注解除了异常处理, 还可以实现全局数据绑定等功能
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class})
// 设置处理的异常
public String testExcetion(Exception ex, Model model){
// Exception ex 异常对象信息
// Model model 请求域
model.addAttribute("ex",ex);
return "error";
}
}
出现异常时页面效果
11. 使用注解配置SpringMVC
使用配置类和注解来代替Web.xml和SpringMVC配置文件的作用
Spring3.2开始引入了一个便利的WebapplicationInitializer基础实现, 名为abstractAnnotationConfigDispatcherServletInitializer, 当我们的类扩展了这个基础实现并部署到Servlet3中, 容器会自动发现它, 并用它来配置Servlet的上下文
Web工程的初始化类WebInit
package com.atguigu.mvc.config;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import javax.servlet.Filter;
// Web工程的初始化类, 用来代替Web.xml
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
// 方法较多, 注意重写以下的方法
// 获取Spring配置类
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
// 获取SpringMVC配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
// 获取DispatcherServlet的映射路径
// 同Web.xml中的ServletMapping中的url-pattern
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
// 注册过滤器
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
// 设置过滤器的初始化参数
characterEncodingFilter.setEncoding("utf-8");
characterEncodingFilter.setForceResponseEncoding(true);
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[]{characterEncodingFilter,hiddenHttpMethodFilter};
}
}
SpringMVC配置类(这里是使用的Thymela)
12. SpringMVC执行流程
12.1 SpringMVC的常用组件
-
DispatcherServlet:前端控制器,不需要工程师开发,由框架提供
作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求 -
HandlerMapping:处理器映射器,不需要工程师开发,由框架提供
作用:根据请求的url、method等信息查找Handler,即控制器方法 -
Handler:处理器,需要工程师开发
作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理 -
HandlerAdapter:处理器适配器,不需要工程师开发,由框架提供
作用:通过HandlerAdapter对处理器(控制器方法)进行执行 -
ViewResolver:视图解析器,不需要工程师开发,由框架提供
作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、
RedirectView -
View:视图
作用:将模型数据通过页面展示给用户
12.2 DispacherServlet的初始化过程
DispatcherServlet 本质上是一个 Servlet,所以天然的遵循 Servlet 的生命周期。所以宏观上是 Servlet
生命周期来进行调度