一、SpringMvc 概述
1.什么是SpringMVC?
( •̀ ω •́ )✧: SpringMVC是基于MVC开发模式的框架,具备IOC和AOP
MyBatis用来优化持久层, SpringMVC优化控制器。
spring是用来整合这两个框架 的框架
2.
2.入门案例
看尚硅谷了。。。。
一、SpringMVC入门(尚硅谷)
1.原来不用时的缺点
直接访问controller
自定义HttpServletRequest和HttpServletResponse
用springMvc后
简化了 前端的参数接收
简化了 后端数据相应
相当于对 servelet进行了封装。
2.springMVC执行流程
来过一遍流程:首先用户请求到达DipacherServlet ,DS去HandlerMapping中查看是否有用户访问的路径,如果有,那么将handler返回,接着调用HandlerAdapter, HandlerAdapter简化参数,并 调用 handler,将响应的数据进行包装。
其实HandlerAdapter是为 我们程序员写的 handler服务的,我们在写handler的参数时,不用再写一长串的HttpServletRequest........., 而是直接写上对应的参数。包括返回数据,在原来的servlet中,我们并没有进行返回,在使用springmvc后,适配器HandlerAdapter对我们的handler的返回值进行包装。
3.第一次写springMVC
<properties>
<spring.version>6.0.6</spring.version>
<servlet.api>9.1.0</servlet.api>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- springioc相关依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- web相关依赖 -->
<!-- 在 pom.xml 中引入 Jakarta EE Web API 的依赖 -->
<!--
在 Spring Web MVC 6 中,Servlet API 迁移到了 Jakarta EE API,因此在配置 DispatcherServlet 时需要使用
Jakarta EE 提供的相应类库和命名空间。错误信息 “‘org.springframework.web.servlet.DispatcherServlet’
is not assignable to ‘javax.servlet.Servlet,jakarta.servlet.Servlet’” 表明你使用了旧版本的
Servlet API,没有更新到 Jakarta EE 规范。
-->
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-web-api</artifactId>
<version>${servlet.api}</version>
<scope>provided</scope>
</dependency>
<!-- springwebmvc相关依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
一、springMVC入门((写不出来了,看黑马)
1.入门案列
问题:
maven的provided是什么意思?
最终:还是看尚硅谷
原来的错误是因为 必须要用Tomcat 10
一、
1.
二、SpringMVC接收数据
1.访问路径设置。
闲想:模糊匹配,可以设置请求的方式(get,post)默认所有请求方式
1.1 精确路径匹配
在@RequestMapping注解指定 URL 地址时,不使用任何通配符,按照请求地址进行精确匹配
@Controller
public class UserController {
/**
* 精准设置访问地址 /user/login
*/
@RequestMapping(value = {"/user/login"})
@ResponseBody
public String login(){
System.out.println("UserController.login");
return "login success!!";
}
/**
* 精准设置访问地址 /user/register
*/
@RequestMapping(value = {"/user/register"})
@ResponseBody
public String register(){
System.out.println("UserController.register");
return "register success!!";
}
}
1.2 模糊路径匹配
@Controller
public class ProductController {
/**
* 路径设置为 /product/*
* /* 为单层任意字符串 /product/a /product/aaa 可以访问此handler
* /product/a/a 不可以
* 路径设置为 /product/**
* /** 为任意层任意字符串 /product/a /product/aaa 可以访问此handler
* /product/a/a 也可以访问
*/
@RequestMapping("/product/*")
@ResponseBody
public String show(){
System.out.println("ProductController.show");
return "product show!";
}
}
现在来测试:
经过测试,/*/* 会严格匹配两层,请求时只写一层是不行的。
匹配 param/d1 ,失败
匹配param/d1/1 ,失败
匹配 param/d1/1/2 成功
1.3 类和方法级区别
1.4 附带请求参数限制
默认情况下,这八种请求方式都可以访问。
1.5 进阶注解
1.6 常见配置问题
2. 接收参数(重点)
2.1 param和json参数比较
2.2 param参数接收
①直接赋值。
②使用@RequestParam注解
why?
当前端传递的param参数与形参名不同时。
当需要指定形参的值是必须传递的。
当需要指定形参的值不是必须要传递的,并且可以设置默认值。
可能出现的问题!
我认为使用包装类是一个很好的习惯,当不传参时,会变为null,服务器不会报错。
使用@RequestParam时,必须要传参,即使是Integer这样的包装类。
③一名多指(两种方式)
数组的方式,只要参数与形参名保持一致就行,当然也可以使用@RequestParam
集合的方式,由于默认跟数组绑定到一块,因此必须使用@RequestParam 来进行绑定。
我踩坑了: 记得让 前端传过来的参数名与形参名保持一致。但是此时仍然可以使用@RequestParam注解 来解决名字不一样的问题。
④实体对象接收
遇到的问题,无法返回 User类型,只能返回字符串类型。这个后面会提到,需要引入一个跟json格式转换相关的依赖。
2.3 路径 参数接收
2.4 JSON参数接收(@RequestBody)
有个@ResponceBody ,也有一个@RequestBody
原来记得笔记没了。。。。。,现在来简述一下。
①接收json参数必须要用@RequestBody
②引入json格式转换相关的依赖。
③在springmvc配置类上加上 @EnableWebMvc 注解,会为handlerAdapter加上json转换器,也会去加载handlerMapping和handlerAdapter
@EnableWebMvc注解的用处
2.5 接收Cookie数据
2.6 接收请求头数据
2.7 原生Api对象操作
2.8 共享域对象操作
感觉共享域 很像 vuex, 有一个公共仓库来存储数据。
2.8.1 属性(共享)域作用回顾
2.8.2 Request级别属性域
①使用 Model 类型的形参
@RequestMapping("/attr/request/model")
@ResponseBody
// 在形参位置声明Model类型变量,用于存储模型数据
public String testAttrRequestModel(Model model) {
// 我们将数据存入模型,SpringMVC 会帮我们把模型数据存入请求域
// 存入请求域这个动作也被称为暴露到请求域
model.addAttribute("requestScopeMessageModel","i am very happy[model]");
return "target";
}
②使用 ModelMap 类型的形参
@RequestMapping("/attr/request/model/map")
@ResponseBody
// 在形参位置声明ModelMap类型变量,用于存储模型数据
public String testAttrRequestModelMap( ModelMap modelMap) {
// 我们将数据存入模型,SpringMVC 会帮我们把模型数据存入请求域
// 存入请求域这个动作也被称为暴露到请求域
modelMap.addAttribute("requestScopeMessageModelMap","i am very happy[model map]");
return "target";
}
③使用 Map 类型的形参
@RequestMapping("/attr/request/map")
@ResponseBody
public String testAttrRequestMap(
// 在形参位置声明Map类型变量,用于存储模型数据
Map<String, Object> map) {
// 我们将数据存入模型,SpringMVC 会帮我们把模型数据存入请求域
// 存入请求域这个动作也被称为暴露到请求域
map.put("requestScopeMessageMap", "i am very happy[map]");
return "target";
}
④使用原生request对象
@RequestMapping("/attr/request/original")
@ResponseBody
// 拿到原生对象,就可以调用原生方法执行各种操作
public String testAttrOriginalRequest(HttpServletRequest request) {
request.setAttribute("requestScopeMessageOriginal", "i am very happy[original]");
return "target";
}
⑤使用 ModelAndView 对象
@RequestMapping("/attr/request/mav")
public ModelAndView testAttrByModelAndView() {
// 1.创建ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
// 2.存入模型数据
modelAndView.addObject("requestScopeMessageMAV", "i am very happy[mav]");
// 3.设置视图名称
modelAndView.setViewName("target");
return modelAndView;
}
2.8.3 Session级别属性(共享)域
2.8.4 Application级别属性(共享)域
2.9 日期参数接收
两种方式:
1.@DateTimeFormat注解 应用于一个类的一个方法
2.@InitBinder注解 应用于类的所有方法
要求:前端传过来的字符串类型要满足后端的pattern
@InitBinder
public void initBinder(WebDataBinder dataBinder) {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
dataBinder.registerCustomEditor(Date.class, new CustomDateEditor(sf, true));
}
遇到的问题:@DateTimeFormat能解析Date类型,也能解析LocalDate类型,但在返回LocalDate时,会报错。
三、SpringMVC 响应数据
1.handler方法解析
2.返回JSON数据(重点)
①引入json处理器相关依赖
②给配置类加上@EnableWebMvc
③加上@ResponseBody注解
有个比较新奇的注解,@RestController
param和json get和post
@RequestBody注解和@RequestResponce
@ResponceBody注解可以加在类和方法上
3.页面跳转控制
3.1 快速返回模板视图(动力节点讲过)
不加@ResponseBody注解,返回字符串。字符串即为jsp的位置,前缀和后缀被处理过。
3.2 转发和重定向
不仅仅是转发到 jsp上,还有转发到 自己写的controller的路径下,如下图,可转发到 /demo 中。
3.3 返回静态资源
这个自己找相关知识吧,感觉用的不多。
四、RESTFul风格设计和实战
关于接收参数的三个注解
五、全局异常处理机制
实践如下:
六、拦截器使用
1.简单介绍
拦截器的位置
2.实践:
定义拦截器,实现HandlerInterceptor接口
并实现其中的preHandle() postHandle() afterCompletion()方法
还是有些困惑,对于postHandle() 和afterCompletion()
最后在配置类里面进行注册,配置类需要先实现 WebMvcConfigurer 接口
3. 自定义多个拦截器的执行顺序
当自定义了多个 拦截器时,执行顺序是怎样的。
4.细化拦截器所拦截的路径
七、参数校验(没见过)
八、番外篇
1.利用拦截器统计handle方法执行的时间。
- 创建一个实现
HandlerInterceptor
接口的拦截器类,例如ExecutionTimeInterceptor
。
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ExecutionTimeInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 在方法执行前记录当前时间
request.setAttribute("startTime", System.currentTimeMillis());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 在方法执行后计算执行时间并打印
long startTime = (long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
long executionTime = endTime - startTime;
System.out.println("Method execution time: " + executionTime + "ms");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 方法完成后清理资源
}
}
2. 配置拦截器,在 Spring MVC 的配置文件(例如 springmvc-servlet.xml
)中添加以下内容:
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 设置要拦截的路径 -->
<mvc:mapping path="/**"/>
<!-- 指定拦截器类 -->
<bean class="com.example.ExecutionTimeInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
JSON参数接收:
put delete post 能用json参数吗
request共享域是什么?
全局域
request.setArttribute() 跟共享域有关,原来好像没见过。
转发和重定向有什么区别?forward和redirect
表现在地址栏上:forward的地址栏不会变,但是redirect的地址栏会发生改变,变为重定向的地址。
经理handlerAdapter
v
v
通过两个秘书进行静态资源处理
机器人回答转发:
全局异常处理 @ControllerAdvice和@RestControllerAdvice
拦截器,比起filter粒度更细
面经:
1.springmvc的处理流程
2.springboot和springmvc区别
3、说一下对SpringMVC的理解
4、Spring和SpringMVC的关系
5、Spring中的事务
6.Springboot相比于Spring,SpringMVC流程,拦截器和过滤器的区别
7.前端发请求到后端返回在整个SpringMVC 中的执行流程
8.SpringBoot 相比于传统Spring项目的优点
9.springmvc的内部逻辑