今天是学习ssm框架的第三天,学完今天预计在花两天就可以学完ssm,就可以接着学习redis这个重要部分了。

SpringMVC

📘简介

SpringMVC是一种基于Java实现MVC模型的轻量级Web框架

优点

  • 使用简单,开发便捷(相比于Servlet)
  • 灵活性强

📘步骤

  1. 使用SpringMVC技术需要先导入SpringMVC坐标与Servlet坐标
<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
	<version>3.1.0</version>
	<scope>provided</scope>
</dependency>
<dependency>
	<groupId>org. springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>5.2.10.RELEASE</version>
</dependency>
  1. 创建SpringMVC控制器类(等同于Servlet功能)
@Controller
public class UserController {
	@RequestMapping("/save")
	@ResponseBody
	public String save(){
		System.out.println("user save ... ");
		return "{'info':'springmvc'}";
	}
}
  1. 初始化SpringMVC环境(同Spring环境),设定SpringMVC加载对应的bean
@Configuration
@ComponentScan("com.itheima.controller")
public class SpringMvcConfig {
}
  1. 初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
	protected WebApplicationContext createServletApplicationContext() {
		AnnotationConfigWebApplicationContext ctx = new 		AnnotationConfigWebApplicationContext();
		ctx.register(SpringMvcConfig.class);
		return ctx;
	}	

	protected String[] getServletMappings() {
		return new String[]{"/"};
	}

	protected WebApplicationContext createRootApplicationContext() {
		return null;
	}
}

注解解释

  • 名称:@Controller
  • 作用:设定SpringMVC的核心控制器bean
    范例:
@Controller
public class UserController {
} 
  • 名称:@RequestMapping
  • 作用:设置当前控制器方法请求访问路径
    范例:
@RequestMapping("/save")//value:请求路径
public void save(){
	System.out.println("user save ... ");
}
  • 名称:@ResponseBody
  • 作用:设置当前控制器方法响应内容为当前返回值,无需解析
    范例:
@RequestMapping("/save")
@ResponseBody
public String save(){
	System.out.println("user save ... ");
	return "{'info': 'springmvc'}";
}

启动服务器初始化流程

  1. 服务器启动,执行ServletContainersInitConfig类,初始化web容器
  2. 执行createServletApplicationContext方法,创建了WebApplicationContext对象
  3. 加载SpringMvcConfig
  4. 执行@ComponentScan加载对应的bean
  5. 加载UserController,每个@RequestMapping的名称对应一个具体的方法
  6. 执行getServletMappings方法,定义所有的请求都通过SpringMVC

单次请求过程
7. 发送请求localhost/save
8. web容器发现所有请求都经过SpringMVC,将请求交给SpringMVC处理
9. 解析请求路径/save
10. 由/save匹配执行对应的方法save()
11. 执行save()
12. 检测到有@ResponseBody直接将save()方法的返回值作为响应求体返回给请求方

📘请求与响应

请求映射路径

  • 名称:@RequestMapping
  • 类型:方法注解,类注解
  • 位置:SpringMVC控制器方法定义上方
  • 作用:设置当前控制器方法请求访问路径,如果设置在类上统一设置当前控制器方法请求访问路径前缀
@Controller
@RequestMapping("/user")
public class UserController {
	@RequestMapping("/save")
	@ResponseBody
	public String save(){
		System.out.println("user save ... ");
		return "{'module': 'user save' }";
	}
}	
  • 属性:value(默认):请求访问路径,或访问路径前缀

Get请求传参
● 普通参数:ur1地址传参,地址参数名与形参变量名相同,定义形参即可接收参数
在这里插入图片描述

@RequestMapping("/commonParam")
@ResponseBody
public String commonParam(String name ,int age){
	System.out.println("普通参数传递 name == >"+name);
	System.out.println("普通参数传递 age == >"+age);
	return "{'module' : 'common param' }";
}

Post请求传参
● 普通参数:form表单post请求传参,表单参数名与形参变量名相同,定义形参即可接收参数
在这里插入图片描述

@RequestMapping("/commonParam")
@ResponseBody
public String commonParam(String name ,int age){
	System.out.println("普通参数传递 name == >"+name);
	System.out.println("普通参数传递 age == >"+age);
	return "{'module' : 'common param' }";
}

Post请求中文乱码处理
● 为web容器添加过滤器并指定字符集,Spring-web包中提供了专用的字符过滤器

public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer{
	// 配字符编码过滤器
	protected Filter[] getServletFilters() {
		CharacterEncodingFilter filter = new CharacterEncodingFilter();
		filter.setEncoding("utf-8");
		return new Filter[]{filter};
	}
}

不同类型参数传递

  • 📌核心注解

名称:@RequestParam
类型:形参注解
位置:SpringMVC控制器方法形参定义前面
作用:绑定请求参数与处理器方法形参间的关系

@RequestMapping("/commonParamDifferentName")
@ResponseBody
public String commonParamDifferentName(@RequestParam("name")String userName , int age){
	System.out.println("普通参数传递 userName == >"+userName);
	System.out.println("普通参数传递 age == >"+age);
	return "{'module' : 'common param different name'}";
}

参数:
■ required:是否为必传参数
■ defaultValue: 参数默认值

  1. POJO参数:请求参数名与形参对象属性名相同,定义POJO类型形参即可接收参数
    在这里插入图片描述
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
   System.out.println("pojo参数传递 user == >"+user);
   return "{'module': 'pojo param' }";
}
  1. 嵌套POJO参数:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
    在这里插入图片描述
@RequestMapping("/pojoContainPojoParam")
@ResponseBody
public String pojoContainPojoParam(User user){
	System.out.println("pojo嵌套pojo参数传递 user == >"+user);
	return "{'module' : 'pojo contain pojo param'}";
}
  1. 数组参数:请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型形参即可接收参数
    在这里插入图片描述
@RequestMapping("/arrayParam")
@ResponseBody
public String arrayParam(String[] likes){
	System.out.println("数组参数传递 likes == >"+Arrays.toString(likes));
	return "{'module': 'array param' }";
}
  1. 集合保存普通参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系
    在这里插入图片描述
@RequestMapping("/listParam")
@ResponseBody
public String listParam(@RequestParam List<String> likes){
	System.out.println("集合参数传递 likes == >"+ likes);
	return "{'module': 'list param' }";
}

Json数据传递

  1. 添加json数据转换相关坐标
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<vrsion>2.9.0</version>
</dependency>
  1. 设置发送json数据(请求bady中添加数据)
    在这里插入图片描述
  2. 开启自动转换json数据支持
@Configuration
@ComponentScan("com.itheima.controller")
@EnableWebMvc
public class SpringMvcConfig {
}

💡注意事项:@EnableWebMvc注解功能强大,该注解整合了多个功能,此处仅使用其中一部分功能,即json数据进行自动类型转换

  1. 设置接收json数据
@RequestMapping("/listParamForJson")
@ResponseBody
public String listParamForJson(@RequestBody List<String> likes){
   System.out.println("list common(json)参数传递 list == >"+likes);
   return "{'module' :'list common for json param'}";
}

📘 @RequestBody 与 @RequestParam 区别

🔑 区别 📦 说明
@RequestParam 用于接收 URL 地址传参,表单参数【application/x-www-form-urlencoded
@RequestBody 用于接收 JSON 数据【application/json
  • 🎯 应用
  • 后期开发中,发送 JSON 格式数据为主,@RequestBody 应用较广。
  • 如果发送非 JSON 格式数据,选择用 @RequestParam 接收请求参数。

日期型参数传递
日期类型数据基于系统不同格式也不尽相同

  • 2088-08-18
  • 2088/08/18
  • 08/18/2088

接收形参时,根据不同的日期格式设置不同的接收方式

@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,
						@DateTimeFormat(pattern = "yyyy-MM-dd") Date date1,
						@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss")Date date2){
	System.out.println("参数传递 date == >"+date);
	System.out.println("参数传递 date(yyyy-MM-dd) == >"+date1);
	System.out.println("参数传递 date(yyyy/MM/dd HH:mm:ss) == >"+date2);
	return "{'module' : 'data param' }";
}

💡使用DateTimeFormat注解,通过pattern属性规定日期格式,其底层通过Converter接口来实现的


响应

  • 名称:@ResponseBody
  • 类型:方法注解
  • 位置:SpringMVC控制器方法定义上方
  • 作用:设置当前控制器返回值作为响应体,将返回数据转为json格式,底层通过HttpMessageConverter实现
@RequestMapping("/save")
@ResponseBody
public String save(){
	System.out.println("save ... ");
	return "{'info': 'springmvc' }";
}
  • HttpMessageConverter接口
public interface HttpMessageConverter<T> {
	boolean canRead(Class <? > clazz, @Nullable MediaType mediaType);
	boolean canWrite(Class <? > clazz, @Nullable MediaType mediaType);
	List<MediaType> getSupportedMediaTypes();
	T read(Class <? extends T> clazz, HttpInputMessage inputMessage)
		throws IOException, HttpMessageNotReadableException;
	void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
		throws IOException, HttpMessageNotWritableException;
}

📘 REST风格

简历
REST(Representational State Transfer),表现形式状态转换

传统风格资源描述形式

  • http://localhost/user/getById?id=1
  • http://localhost/user/saveUser

REST风格描述形式

  • http://localhost/user/1
  • http://localhost/user

优点:

  • 隐藏资源的访问行为,无法通过地址得知对资源是何种操作
  • 书写简化

按照REST风格访问资源时使用行为动作区分对资源进行了何种操作

URL 描述 HTTP 方法
http://localhost/users 查询所有用户信息 GET (查询)
http://localhost/users/1 查询指定用户信息 GET (查询)
http://localhost/users 添加用户信息 POST (新增/保存)
http://localhost/users/1 修改用户信息 PUT (修改/更新)
http://localhost/users/1 删除用户信息 DELETE (删除)
  • 根据REST风格对资源进行访问称为RESTful
    💡注意事项:
    1.上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范
    2.描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、account.s …

步骤

  1. 设定HTTP请求动作(动词)
@RequestMapping(value ="/users", method = RequestMethod.POST)
@ResponseBody
public String save(@RequestBody User user){
	System.out.println("user save ... " + user);
	return "{'module' : 'user save' }";
}

@RequestMapping(value ="/users" ,method = RequestMethod.PUT)
@ResponseBody
	public String update(@RequestBody User user){
	System.out.println("user update ... "+user);
	return "{'module': 'user update' }";
}
  1. 设计请求参数(路径变量)
@RequestMapping(value ="/users/{id}" ,method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id){
	System.out.println("user delete ... " + id);
	return "{'module': 'user delete' }";
}

📌注解解释

  1. 名称:@RequestMapping
  • 类型:方法注解
  • 位置:SpringMVC控制器方法定义上方
  • 作用:设置当前控制器方法请求访问路径
@RequestMapping(value ="/users", method = RequestMethod.POST)
@ResponseBody
public String save(@RequestBody User user){
	System.out.println("user save ... " + user);
	return "{'module' : 'user save' }";
}
  • 属性
    ■ value(默认):请求访问路径
    ■ method:http请求动作,标准动作(GET/POST/PUT/DELETE)
  1. 名称:@PathVariable
  • 类型:形参注解
  • 位置:SpringMVC控制器方法形参定义前面
  • 作用:绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应
@RequestMapping(value ="/users/{id}" ,method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id){
	System.out.println("user delete ... " + id);
	return "{'module' : 'user delete' }";
}

RESTful

  • 名称:@RestController
  • 类型:类注解
  • 位置:基于SpringMVC的RESTful开发控制器类定义上方
  • 作用:设置当前控制器类为RESTful风格,等同于@Controller与@ResponseBody两个注解组合功能
@RestController
public class BookController {
}
  • 名称:@GetMapping @PostMapping @PutMapping @DeleteMapping
  • 类型:方法注解
  • 位置:基于SpringMVC的RESTful开发控制器方法定义上方
  • 作用:设置当前控制器方法请求访问路径与请求动作,每种对应个请求动作,例如@GetMapping对应GET请求
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
	System.out.println("book getById ... "+id);
	return "{'module': 'book getById' }";
}
  • 属性
    ●value(默认):请求访问路径

📘拦截器

概念

  • 拦截器(Interceptor)是一种动态拦截方法调用的机制

  • 作用:

    ■ 在指定的方法调用前后执行预先设定后的的代码

    ■阻止原始方法的执行

拦截器与过滤器区别

  • 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术

  • 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强


📌步骤

  1. 声明拦截器bean,并实现HandlerInterceptor接口(注意:扫描加载bean)
@Component
public class ProjectInterceptor implements HandlerInterceptor {
	public boolean preHandle( .. ) throws Exception {
		System.out.println("preHandle ... ");
		return true;
	}
	public void postHandle( .. ) throws Exception {
		System.out.println("postHandle ... ");
	}

	public void afterCompletion( .. ) throws Exception {
		System.out.println("afterCompletion ... ");
	}
}
  1. 定义配置类,实现WebMvcConfigurationSupport,实现addIntercreptor方法(注意:扫描加载配置)
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		...
	}
}
  1. 添加拦截器并设定拦截的访问路径,路径可以通过可变参数设置多个
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
	@Autowired
	private ProjectInterceptor projectInterceptor;

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(projectInterceptor).addPathPatterns("/books");
	}
}
  • 也可以使用标准化接口WebMvConfigurer简化开发(注意:侵入式较强)
@Configuration
@ComponentScan("com.itheima.controller")
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer{
	@Autowired
	private ProjectInterceptor projectInterceptor;

	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*");
	}

}

💡执行流程
在这里插入图片描述


多拦截器执行执行顺序
在这里插入图片描述
类型于栈的执行操作,先入后出先运行的拦截器的pre方法其post和after方法后运行


🧾总结:今天的课程主要学完了SpringMvc,个人认为就是对以前使用过的注解进行了底层如何实现进行了讲解,因为这些注解都使用过所以理解起来不会太难。明天继续学习,加油!🔥🔥🔥

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐