【JavaEE】Spring MVC 程序开发要点总结
【JavaEE】Spring MVC 程序开发要点总结
1. 什么是 Spring MVC
官方文档:Spring Framework Documentation :: Spring Framework
Spring Web MVC 是基于 Servlet API 构建的原始Web 框架,从一开始就包含在Spring 框架中。它的正式名称“Spring Web MVC” 来自其源模块的名称(Spring-webmvc),但它通常被称为“Spring MVC”
两个关键信息:
- Spring MVC 是一个Web框架
- Spring MVC 是基于Servelet API 构建的
全称为“Spring Model View Controller”
- 它就是软件工程中的一种软件架构模式,它把软件系统分为模型Model、视图View、控制器Controller,三个基本部分
大概就是这个模式:
1.1 MVC的执行流程
- 用户的请求首先先给到Controller
- Controller将请求转发给Model
- Model处理业务并将结果给到Controller
- Controller再将“冷冰冰”的数据传给View
- View 转化数据生成最终的页面给用户
这个过程就是网站前后端工作的原理,也就是Web
- 在做项目实战之前,只需要知道,通过指定路由发送请求返回响应即可,现在是学习基础阶段
1.2 为什么要学Spring MVC
绝大多数Java项目都是基于Spring全家桶实现的,而Spring 的核心就是Spring MVC!
在学习Spring Boot的时候,我们不也可以通过路由访问吗?
- 那是因为我们在创建Spring Boot项目的时候,添加了Spring Web框架,也就是Spring MVC框架!
- 所以,这个项目相当于Spring MVC项目,而Spring Boot之前相关Web的优点,没有这个框架也无用武之地,Spring MVC框架的实现,也离不开Spring 的核心内容:IOC容器、AOP等等…
说到底SpringBoot就是Spring相关开发的脚手架👍,“大辅助”
- 方便Spring,例如提供默认配置和自动配置来减少开发者的工作量、约定大于配置的原则…
- 方便Spring MVC,例如内置了Web容器…
另外,Spring Boot还提供了丰富的插件和扩展机制,可以与其他技术(如数据库、消息队列、缓存等)无缝集成。开发者可以通过简单的配置,快速集成这些技术,并且可以轻松地通过命令行或配置文件进行管理和调整。
不过,我们作为开发者,不需要过多在意他们的关系和底层实现原理, 我们要专注于开发 ~
重点在于,Spring MVC的学习!
1.3 Spring MVC 的学习
Spring MVC重点就是,连接,处理请求,返回响应
就是说,前面Servelet开发的所有内容,在这里用Spring MVC框架去做一个大的升级!
- 注意,本文章不讲两者对比,冷热自知
- 连接的功能
- 处理请求 — 获取请求中的相关数据
- 返回响应 — 输出执行业务逻辑后的数据
2. Spring MVC 的创建和连接
2.1 创建
刚才说过了,就是Spring Boot 引入 Spring Web框架~
- 跟之前别无二致
2.2 连接
建立连接(三次挥手四次握手),其他不需要我们开发者管,我们要做的是:
- 确定个“终点”,也就是说给一段后端程序,加一个路由(url),让前端知道跟哪个程序建立连接
2.2.1 @RestController注解
这个注解很重要!
- 包含两个重要注解
-
@Controller,五大类注解之一,没有它,就无法扫描进行一些框架内部操作
- 框架也是有依靠Bean存储和注入的呀
-
@ResponseBody,没有它,那么后续方法的返回的字符串,默认代表“文件名”
- 因为早期没有前后端分离,后端工程师也编写html,所以返回的html文件,就是返回页面咯~
- 如果页面404,可能就是因为没有这个注释,或者没有这个文件
- 而有了它,返回的默认就是字符串数据(在后面讲返回数据的时候再说)
2.2.2 @RequestMapping注解
这个注解就是请求要连接的路由
-
加在类上,代表这个类的路由的上一级路径(可有可无)
- 这样不同类的方法中,就可以其同样的路由名了~
- 加在方法,代表这个方法的路由,其返回值作为响应的Body(这里只关注内容,不关注格式是什么)
理论上前面要加 /
符号的,但是一些版本已经优化掉了,也就是可加可不加,不影响访问(之前是不加就访问不了)
- 并且支持一次写多级的路由
2.2.3 请求的方法
我们之前有针对Get的,还有Post的,那么这个@RequestMapping注解代表可以接受什么方法呢
答:默认情况下是全都可以,如何请求都能访问这个url,但是可以改~
- 这里的重点就是 path / value(path和value一样) 和method三个,其他没咋用
path的值代表url,method代表允许的请求的方法
- method的值是对应的枚举类型的值,不是字符串
这样就只有POST请求可以访问了,浏览器只能构造GET请求:
- 报405,方法不允许~
注解的属性的值要设置多个,用类似这样数组的方式即可:
- 代表可连接的几种url
- 代表满足的几种方法
这样一个类就可以书写,多个处理GET请求和多个处理POST请求的程序了~
3. 处理请求
因为Spring MVC是基于Servlet写的,所以也可以这样操作
然后完全继承之前的处理操作
- 之后都是用Spring MVC框架的方式去写~
@RequestMapping注解的方法,它们的参数列表没有限制,什么都可以
你可以理解为,Spring框架内部有很多Bean
- 参数列表的取名/其他可以定位到对应的Bean,就可以完成注入
- 找不到的就是默认值
而HttpServletRequest request,就有一个对应的针对这个请求的Bean,请求过来的时候,就会诞生
- 具体底层实现和相关的复杂的原理,暂时不考虑
3.1 获取参数 Parameter
- query string的键值对
- form表单的键值对
3.1.1 一个个参数属性注入的方式
这里用到Postman这个软件!
可见:
- 自动设置了字符集为UTF-8,没有中文乱码的问题
- 将键值对注入到了参数中!
要求:
- 类型正常对应得上!(不要没事找事,正常点写)
- 框架已经支持很多对应了,比如字符串可对应为包装类,也可以对应为基本数据类型!
- 参数名跟key对应
多个同名的key
- 用数组接受
- 参数的值为,key1, key2
3.1.2 注入对象的方式
有时候,其实这些属性对应的就是一个实体类的属性,那么还不如注入到一个实体类里
要求:
- 实体类的属性名要对应得上,否则找不到对应的Bean
- 类型正确
注入规则就是:
- 参数列表中的任何对象的属性名和对应请求中的key名相同的属性,都会被注入
理论上,这些数据并不会共享不同的对象,而是针对一个类一个对象!
- 代码层面上,这些参数没规定是哪个对象的,逻辑实际层面上,这些参数是一个User对象的,开发者心知肚明
3.1.3 @RequestParam重命名
你有时候会觉得,前端传过来的键值对,key名好low!让我的代码变得low!
还是通过注解,你可以这么做:
- 代表的含义是:
- 前端 key 为 n 的值,注入到 name 里
- 前端必须有key 为 n的键值对
加了注解后就会强制要求这个键值对存在,而不是取默认值
当然,你也可以设置:
让required等于false,代表,这个键值对不需要必须存在
- 这个注解的位置只能在那,所以如果以对象注入的方式的话,无法重命名key为对应的属性名
3.2 获取请求中的JSON格式数据
json格式的数据,对应的是一个对象,不能像通过获取参数的方式去获取!
通过注解@RquestBody即可实现:
-
@ResponseBody,@RequestBody都是跟正文有关的,或者说是跟JSON有关的~
- 不要纠结这个注解名,记住他们的作用和用法!
- @ResponseBody等一下就讲~
- 含义就是把这个User对象,看做json对象
- 相较于json字符串,多出来的属性,忽略
- 相较于json字符串,缺少的属性,默认值
Spring MVC 这种动态注入的方式是不是很爽!😊
3.3 获取请求中url附带的变量
url本来就是我们规定的,所以不需要获取(要是想获取,用老方法req.getRequestURL即可获取)
我们在日常生活中,一些网站的格式好像不符合我们之前的【路径 + url + querystring】的格式
例如csdn:
这个数字明显不是路由,而是url附带的一个变量
实现方式:
3.3.1 注解@PathVariable
- 用到注解@PathVariable,也就是获取路径上的变量
一旦这么写了,url就是必须按照这个格式来了!
当然,也支持携带多个变量:
不支持注入对象:
3.3.2 重命名
- 其实很少见这么写,比较这个起名本来就完全由一个程序员规定的
- 唯一的特点就是,同时注入到两个不同的参数里,因为原本这个 i 固定了,就只能个一个参数
3.4 提交文件
3.4.1 注解@RequestPart
用到的注解就是 @RequestPart(name = “xxx”)
-
含义就是:在前端name属性值为fileName的文件按钮,化为对象MultipartFile对象注入到参数中,用此对象可进行相关文件操作
- 如transferTo方法代表,将文件保存到对应目录
Postman提交文件方法:
- 模拟了form表单提交文件,一个文件对应一个name(key)
点击发送后,查看对应目录:
- 表示不会自动建立不存在的目录,并且没有默认的文件名(并非原名)!
如果没有设置文件名,或者文件格式错误:
成功~
3.4.2 设置独一无二的适配的文件名
- 文件名可能会在目录下已存在,如果重了的话,就会导致原文件被覆盖!
- 所以我们要获取一个独一无二的文件名
- 并不是所有文件都是.png文件
- 所以我们还要获得其后缀才能成功保存任何文件!
- 文件保存路径
- 绝对路径/相对路径/项目目录
获取唯一id:
UUID的方式去获取一个全球唯一id:考虑到元素MAC + 随机种子 + 加密算法 …
- 由于考虑线程安全的问题,所以没有绝对的同时!让机器保存一个文件的时间的那极短的时间内生成的id都是不同的,那么这个id必然就是全球唯一的~
- 这里用到了UUID的一个工厂模式,生成方法
- UUID来自java标准库util
获取文件后缀
- 我们只需要知道这个文件的初始文件名,截取一下字符串即可
取最后一个点以及之后的字符串
- 相对路径
如果不加目录,相对路径放在了 “四海八荒之外”了🤣
- 绝对路径
就会保存到这儿~
- 项目目录
用这一套固定搭配就能获取项目目录了~
藏的还挺深
当然是有其他的方式,应该可以指定存储到项目的哪个目录,感兴趣的同学可以去了解一下~
但是,正式项目通常并不是在项目里去保存文件,而是在其他地方去统一的保存一些文件,即绝对路径的写法👍
3.5 获取Cookie
这个机制在初阶的时候已经讲解,不用细说~
- 传送门:【JavaEE】Cookie与Session的前后端交互-表白墙登录设计_s:103的博客-CSDN博客
3.5.1 老方法
通过注入这两个对象,这样跟之前的一模一样
- 如果key不唯一,要遍历多个Cookie,还得用这种
3.5.2 注解@CookieValue
跟之前的注解一样,通过注入的方式:
浏览器手动加Cookie:
- Cookie是浏览器的机制,所以浏览器中演示最佳最方便
3.5.3 重命名
通过key值直接注入,并设置不存在也无所谓:
现在不存在key为n的cookie,但不会报错,手动加入:
3.6 获取和存储Session
3.6.1 老方法
如果不存在session,不打算创造session,就得用老方法
3.6.2 存储Session
可以直接注入session对象( 系统根据Cookie中的SessionId,找到对应的Session然后注入到参数中 )
这个方式,默认自动创建session
3.6.3 获取Session - 注解@SessionAttribute
典型注入~
同样的,有value属性和require属性
- 重命名
- 是否强制要求存在
效果:
- 一样的不能注入对象,只有获取参数的时候才能用注入对象的方式
3.7 获取Header
同样可以用老方法
- 我们如果要遍历获取所有的Header,就用老方法:
Enumeration<String> headerNames = reqest.getHeaderNames();
StringBuilder result = new StringBuilder();
while(headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = req.getHeader(name);
result.append(name);
result.append(": ");
result.append(value);
result.append("<br>");
}
return result;
现在用注解@RequestHeader,一样的注入思想
- 这里最好加上,重命名,因为header的key一般都有
-
,而变量不能起这个名儿 - 同样有require属性=>是否强制要求存在
处理请求的内容就差不多这么多了,掌握这些基本够用了~
注意:并不是只有这些,可能实现的方式还有其他,注解还有更多,可以实现的也还有更多,我们之后需要用到的不会的东西就专门去查阅资料去学即可~
Java的很多东西都是学不完的,但是我们只要保证我们需要的会去学即可~
4. 返回响应
一样可以注入参数中的HttpServletResponse对象,这是老方法,就不提了~
其实**一般我们只注重响应body里面的数据**,其他都是信息自动生成的也就够用了
- 要是需要调整的,注入这个对象调整一下就好~
4.1 默认返回代表什么
代表的是文件,这个文件的内容就是响应的Body
test.html是在resources.static目录下扫描的:
如果找不到:
返回其他类型呢?
- 直接报错(包括void)
4.2 注解@ResponseBody
@RestController = @Controller + @ResponseBody
这个注解修饰这个类后,其中的所有方法的返回值就是响应的body,字符集默认为utf8!
4.2.1 String类型
格式为text/html
即使这个字符串就是json格式,格式仍然是text/html:
如果为html代码,则会显示出来:
即使你返回的是文件名,也会被认为是文本~
4.2.2 其他类型
其他类型,都会被转化为格式为application/json的字符串作为响应的body~
- 只有一条数据的json是这样的~
- fiddler中可见
特殊:
这样,就能很方便的返回json字符串给前端了!😀😀😀
4.3 补充:请求转发和请求重定向
forward VS redirect
不加@ResponseBody的情况下,通过返回值返回一个视图(一个文件),还可以实现转发和重定向!
- forward:请求转发
- redirect:请求重定向
4.3.1 现象对比
- 写法是这样的👆
对于index1:
对于index2:
4.3.2 现象分析
-
对于请求重定向的index1,现象属于直接跳转到一个页面,跟点击到一个链接一样
-
而对于请求转发,地址并没有改变为test.html,依旧保持index2,现象跟直接返回一个视图一样
也就是说:
- 请求重定向:直接让浏览器去访问另一个地址(让你自己去访问别的页面)
- 请求转发:服务器帮忙访问另一个地址,显示在原地址上(服务器转发了个页面给你)
知道一些网站为什么不是显示html文件了吧,原来是这样Σ(っ °Д °;)っ!
- 这也谈不上高级,倒是以后也可以这样试试 ~
4.3.3 具体区别
- redirect将请求重新定位到资源;forward则为服务器帮忙转发
- redirect地址发生改变;forward地址不会发生改变
-
redirect与直接访问效果一致,不存在原来的外部资源不能访问;forward服务器转发有可能造成原外部资源不能访问
- 例如forward如果资源和转发的页面不在一个目录下,会导致资源不可访问(失效),如果是css/js等等…失效了,页面会变得很丑
- 这里就不演示了,感兴趣的同学可以去试试,以后有机会做项目的时候搞一下
文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆!代码位置:spring_mvc_demo/src/main/java/com/example/demo · 游离态/马拉圈2023年8月 - 码云 - 开源中国 (gitee.com)
看到这里,Spring MVC算是掌握了!对于网站开发基本够用了~
还是那句话,我们学了这些之后,之后肯定会遇到不会的,因为本文章的内容之外的,能够实现的还有很多,注解也很多,方式也很多,我们之后项目开发需要用到的,我们就去学就完事了!b( ̄▽ ̄)d文章来源:https://www.toymoban.com/news/detail-639630.html
接下来就是MyBatis框架的学习✿✿ヽ(°▽°)ノ✿文章来源地址https://www.toymoban.com/news/detail-639630.html
到了这里,关于【JavaEE】让“单车变摩托”的神级框架—Spring MVC的深入讲解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!