一,Spring定义
Spring让Java程序更加快速,简单和安全。Spring对于速度、简单性和生产力的关注使其成为世界上最流行的Java框架
Spring的两个含义:
1)泛指Spring家族产业
2)Spring Framework/Spring Core
1.1 Maven
Maven是一个项目管理工具。基于POM的概念,Maven可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件
即Maven是一个项目管理工具,通过pom.xml文件的配置获取 jar包,而不用手动去添加 jar包
1.1.1 Maven的功能
maven简单,方便,可以提高我们的开发效率,减少开发bug
maven有两个主要的功能:项目构建和管理依赖
1)项目构建
maven提供了标准的,跨平台的自动化项目构建方式
当开发一个项目之后,代码需要经过编译,测试,打包,发布等流程,每次代码的修改,都需要经过这些流程,如果代码反复调试修改,这个流程就需要反复进行,就显得非常麻烦,而maven给我们提供了一套简单的命令来完成项目的构建
比如:maven命令中的package,可以完成项目的打包操作(打包就是把所有的class文件,全部放在一起,打成jar包或者war包)

jar包和war包都是⼀种压缩文件, jar包就是把开发人员已经写好的一些代码进行打包。 打好的jar包就可以引入到其他项目中,也可以直接使用这些jar包中的类和属性。另外也可以打成可执行jar包,这样的包就可以通过java-jar命令来执行war包可以理解为是⼀个web项⽬,里面是项目的所有东西,通常用于网站.
2)依赖管理
Maven是⼀个项目管理工具,通过pom.xml文件的配置获取jar包,而不用手动去添加jar包获取的jar包,其实就是依赖
pom.xml就是maven的配置文件,用以描述项目的各种信息
依赖配置
依赖:指当前项目运行所需要的jar包
例如在JDBC中,需要手动下载mysql-connector-java的包,并且添加到项目中
如果使用maven,则只需要在pom.xml中,引入mysql-connector-java的依赖就可以了
<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.5.0</version>
<!–排除依赖–>
<!– <exclusions>–>
<!– <exclusion>–>
<!– <artifactId>spring-jcl</artifactId>–>
<!– <groupId>org.springframework</groupId>–>
<!– </exclusion>–>
<!– </exclusions>–>
</dependency>
</dependencies>
依赖传递
没有使用maven时,向项目中添加依赖的jar包,需要把所有的jar包都复制到项目⼯程下,比如A依赖B,B依赖C, 那么A项目引⼊B的同时,也需要引⼊C,如果我们手动管理这个依赖,这个过程就会比较麻烦,我们需要知道每个库都依赖哪些库,以及这些依赖之间的版本是如何关联的
但使用maven的话,就可以避免管理所需依赖的关系。我们只需要在pom文件中,定义直接依赖就可以了,由于maven的依赖具有传递性,所以会自动把所依赖的其他jar包也⼀起导入
直接依赖:在当前项⽬中通过依赖配置建⽴的依赖关系
间接依赖:被依赖的资源如果依赖其他资源,当前项⽬间接依赖其他资源
依赖排除
随着项目越来越复杂,库之间的依赖关系会越来越复杂
排除依赖:主动断开依赖的资源(被排除的资源无需指定版本)
<exclusions>
<exclusion>
<artifactId>spring-jcl</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
1.1.2 maven仓库
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.5.0</version>
</dependency>
这个代码,我们称之为"坐标",也就是唯⼀的.
在Maven中,根据groupId、artifactId、version的配置,来唯⼀识别⼀个jar包,缺⼀不可.
当我们在pom⽂件中配置完依赖之后,点击刷新,Maven会根据坐标的配置,去仓库⾥寻找Jar包,并把他下载下来,添加到项⽬中.这个Jar包下载的地⽅就称为仓库.
仓库:⽤于存储资源,管理各种jar包
本地仓库
本地仓库:自己计算机上的⼀个目录(用来存储jar包) 当项目中引入对应依赖jar包后,首先会查找本地仓库中是否有对应的jar包
• 如果有,则在项目直接引用
• 如果没有,则去中央仓库中下载对应的jar包到本地仓库
中央仓库
中央仓库:maven软件中内置⼀个远程仓库地址,就是中央仓库,服务于整个互联⽹.由Maven团队 维护,全球唯⼀.
仓库地址:https://repo1.maven.org/maven2/
可以通过https://mvnrepository.com这个⽹站来查询并下载
我们可以把⾃⼰写好的Jar包上传到中央仓库(具备⼀定的要求), 也可以从中央仓库下载Jar包
查找Jar的坐标
1. 访问https://mvnrepository.com/
2. 进⾏查找,⽐如mysql
私服(私有服务器)
私服:⼀般由公司团队搭建的私有仓库. 私服属于某个公司,或者某个部⻔, 往往需要⼀定权限.
有了私服之后,Maven依赖下载的顺序⼜发⽣了变化
当Maven需要下载资源的时候
1. 先从本地仓库获取,本地仓库存在,则直接返回
2. 如果本地仓库没有,就从私服请求,私服存在该资源,就直接返回
3. 如果私服上不存在该资源,则从中央仓库下载,中央仓库不存在,就报错了…
4. 如果中央仓库中存在,就先缓存在私服上之后,再缓存到本地仓库⾥,再为Maven的下载请求提供服务
私服是很多⼈在使⽤的,所以只需要第⼀个使⽤者下载⼀次就可以了
1.4 SpringBoot
Spring Boot的诞生是为了简化Spring程序开发的

其中,SNAPSHOT是不稳定版本,可能会发生变化
RELEASE版本,是稳定版本,不能修改,只能升级版本
三,一个简单的项目创建
idea创建
四,Spring Web MVC
4.1 什么是Spring Web MVC
Spring WebMVC是基于ServletAPI构建的原始Web框架,从⼀开始就包含在Spring框架中。它的 正式名称“SpringWebMVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为"Spring MVC".
什么是Servlet呢?
Servlet 是⼀种实现动态⻚⾯的技术.准确来讲Servlet是⼀套JavaWeb开发的规范,或者说是⼀套 Java Web开发的技术标准.只有规范并不能做任何事情,必须要有⼈去实现它.所谓实现Servlet规 范,就是真正编写代码去实现Servlet规范提到的各种功能,包括类、⽅法、属性等. Servlet 规范是开放的,除了Sun公司,其它公司也可以实现Servlet规范,⽬前常⻅的实现了 Servlet 规范的产品包括Tomcat、Weblogic、Jetty、Jboss、WebSphere等,它们都被称 为"Servlet 容器".Servlet 容器⽤来管理程序员编写的Servlet类.
4.1.1 MVC定义
MVC是ModelViewController的缩写,它是软件工程中的⼀种软件架构设计模式,它把软件系统分 为模型、视图和控制器三个基本部分

• View(视图):指在应⽤程序中专⻔⽤来与浏览器进⾏交互,展⽰数据的资源.
• Model(模型):是应⽤程序的主体部分,⽤来处理程序中数据逻辑的部分.
• Controller(控制器):可以理解为⼀个分发器,⽤来决定对于视图发来的请求,需要⽤哪⼀个模型 来处理,以及处理完后需要跳回到哪⼀个视图。即⽤来连接视图和模型
4.1.2 什么是SpringMVC
MVC是⼀种架构设计模式,也是⼀种思想, ⽽SpringMVC是对MVC思想的具体实现.除此之外, Spring MVC还是⼀个Web框架.
总结来说,SpringMVC是⼀个实现了MVC模式的Web框架.
所以,SpringMVC主要关注有两个点:
1. MVC
2. Web框架
SpringMVC 全称是SpringWebMVC
4.1.3 应用
既然是Web框架,那么当用户在浏览器中输入了url之后,我们的Spring MVC项目就可以感知到用户的请求,并给予响应.
学习SpringMVC,重点也就是学习如何通过浏览器和⽤⼾程序进⾏交互
主要分以下三个⽅⾯:
1. 建⽴连接:将⽤⼾(浏览器)和Java程序连接起来,也就是访问⼀个地址能够调⽤到我们的 Spring 程序。
2. 请求:⽤⼾请求的时候会带⼀些参数,在程序中要想办法获取到参数,所以请求这块主要是获取参数的功能.
3. 响应:执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤⼾,也就是响应
项目准备
Spring MVC项⽬创建和SpringBoot创建项⽬相同,在创建的时候选择SpringWeb就相当于创建了 Spring MVC的项⽬.
建立连接
在SpringMVC中使用 @RequestMapping 来实现URL路由映射,也就是浏览器连接程序的作用
@RequestMapping("/getNum")
public Integer getNum(){
return 10;
}
接下来访问http://127.0.0.1:8080/getNum, 就可以看到程序返回的数据了
@RequestMapping 是SpringWebMVC应⽤程序中最常被⽤到的注解之⼀,它是⽤来注册接⼝的 路由映射的.
表⽰服务收到请求时,路径为 /getNum 的请求就会调⽤sayHi这个⽅法的代码
路由映射:当⽤⼾访问⼀个URL时,将⽤⼾的请求对应到程序中某个类的某个⽅法的过程就叫路由映射
@RequestMapping 注解介绍
注解,添加在类上,称之为“类注解”,添加在方法上,称之为“方法注解”
@RequestMapping既可以是类注解,也可以是方法注解
Q : 既然@RequestMapping可以达到目的,为什么还要加@RestController?
A:当把@RestController去掉的时候会报404,因为⼀个项⽬中,会有很多类,每个类可能有很多的⽅法,Spring程序怎么知道要执⾏哪个⽅法呢? Spring会对所有的类进⾏扫描,如果类加了注解@RestController,Spring才会去看这个类⾥⾯的⽅法 有没有加 @RequestMapping 这个注解
@RequestMapping使用
@RequestMapping 既可修饰类,也可以修饰⽅法,当修饰类和⽅法时,访问的地址是类路径+⽅ 法路径.
@RequestMapping标识⼀个类:设置映射请求的请求路径的初始信息
@RequestMapping标识⼀个⽅法:设置映射请求请求路径的具体信息
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping("/v2")
public Integer getNum(){
return 10;
}
}
访问地址为:http://127.0.0.1:8080/hello/v2

注意:@RequestMapping的URL路径最前面加不加 / (斜杠)都可以,Spring程序启动时,会进行判断,如果前面没有加 / ,Spring会拼接上⼀个 /
@RequestMapping 的URL路径也可以是多层路径, 最终访问时,依然是类路径+⽅法路径
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping("/v2/v3")
public Integer getNum(){
return 10;
}
}

注意:文件夹有不同的标签之分

@RequestMapping 是GET还是POST请求?
GET请求:
浏览器发送的请求类型都是get,通过以上案例,可以看出来 @RequestMapping ⽀持get请求.
POST请求:
通过form表单来构造请求:
创建test.html, html代码:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping("/v1")
public String hello(){
return "test 1";
}
@RequestMapping("v1/v3")
public Integer getNum(){
return 10;
}
}
前端代码放在static⽬录下,访问⽅式为:http://127.0.0.1:8080/test.html

从运⾏结果可以看出: @RequestMapping 既⽀持Get请求,⼜⽀持Post请求.同理,也⽀持其他的请 求⽅式.
指定GET/POST⽅法类型
@RequestMapping(value = "/getRequest",method= RequestMethod.POST)
注解里的数组

由此图可得,method为数组,这个数组和Java定义的数组不太一样。Java定义的数组有{},而注解中的数组如果里面只有一个元素的话,是可以省略{}的
4.2 Postman的使用
1 传递参数
Spring会解析收到的参数,整理成类Map的结构,即key-value,其中类型均为string,然后会根据后端的参数类型定义,转换参数类型
1. 普通传参,也就是通过查询字符串来传参

2. form-data(完整表⽰为:multipart/form-data)
表单提交的数据, 在form标签中加上enctyped="multipart/form-data"通常⽤于提交图⽚/⽂件,对应Content-Type: multipart/form-data

3. x-www-form-urlencoded
form表单,对应 Content-Type: application/x-www-from-urlencoded

4,raw
可以上传任意格式的⽂本,可以上传text、json、xml、html等

4.3 请求
访问不同的路径,就是发送不同的请求.在发送请求时,可能会带⼀些参数,所以学习Spring的请求,主要是学习如何传递参数到后端以及后端如何接收.
1,传递单个参数
接收单个参数,在Spring MVC中直接用方法中的参数就可以了
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/r1")
public String r1(String name){
return "接收到参数,name:" + name;
}
}
注意:
使用基本类型来接收参数时,参数必须传(除了Boolean类型),否则会报500错误
当类型不匹配时,会报400错误
@RequestMapping("/r2")
public String r2(int age){
return "接收到参数,name:" + age;
}



通过这个错误日志可知,int类型的参数‘age’,虽然为可选的,但是由于被声明为基本类型而不能转换为空值,考虑将其声明为对应基本类型的包装类型
对于包装类型,如果不传对应参数,spring接收到的数据则为null
所以,对于参数可能为空的数据,建议使用包装类型
2,传递多个参数
直接使用方法的参数接收即可
@RequestMapping("/r3")
public String r3(String name,int age){
return "接收到参数,age:" + age+"接收到参数,name:" + name;
}
当有多个参数的时候,前后端进行参数匹配时,是以参数的名称进行匹配的,因此参数的位置不影响后端获取参数的结果
3,传递对象
如果参数比较多,方法声明就需要很多形参,并且后续每次新增一个参数,也需要修改方法声明
Spring MVC也可以自动实现对象参数的赋值,比如Person对象
package com.luoyaoyun.springbootdemo;
public class Person {
private Integer id;
private String name;
private int age;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\\'' +
", age=" + age +
", address='" + address + '\\'' +
'}';
}
}
@RequestMapping("/m1")
public Object method1(Person p){
return p.toString();
}

Spring 会根据参数名称⾃动绑定到对象的各个属性上,如果某个属性未传递,则赋值为null(基本类型则赋值为默认初识值,⽐如int类型的属性,会被赋值为0)
4,后端参数重命名(后端参数映射)
某些特殊的情况下,前端传递的参数key和我们后端接收的key可以不一样,比如前端传递了一个time给后端,而后端是使用createtime字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使用@RequestParam来重命名前后端的参数值
@RequestMapping("/m2")
public Object method4(@RequestParam("time") String createtime){
return "接收到参数createtime" + createtime;
}

可以看到,Spring可以正确的把浏览器传递的参数time绑定到后端参数createtime参数上
此时,如果浏览器使用createtime来进行参数传递就会打印错误信息

可以得出结论:
1. 使⽤ @RequestParam 进⾏参数重命名时, 请求参数只能和@RequestParam声明的参数一致,才能进⾏参数绑定和赋值.
2. 使用@RequestParam 进⾏参数重命名时,参数就变成了必传参数.
非必传参数设置

查看 实现如下: @RequestParam 注解的实现细节就可以发现required 的默认值为true,表⽰含义就是该注解修饰的参数默认为必传
既然如此,我们可以通过设置 @RequestParam 中的required=false 来避免不传递时报错
@RequestMapping("/r6")
public String r6(@RequestParam(value = "wd", required = false) String keyword){
return "接收到参数, keyword:" + keyword;
}
可以看到,添加required=false之后, time前⾯也加了key,变成了 value = "time"
注解属性赋值时,没有指明key的话,默认为value属性.
如果需要有多个属性进⾏赋值时,需要写上key
5,传递数组
@RequestMapping("/r4")
public String r4(String[] arr){
return Arrays.toString(arr);
}

也有第二种方式:

6,传递集合
集合参数:和数组类似,同⼀个请求参数名有为多个,且需要使用 @RequestParam 绑定参数关系
默认情况下,请求中参数名相同的多个值,是封装到数组.如果要封装到集合,要使⽤ @RequestParam 绑定参数关系
@RequestMapping("/r5")
public String r5(List<String> list){
return list.toString();
}
如果直接传会报错


加上@RequestParam,就可以正常传参
@RequestMapping("/r5")
public String r5(@RequestParam List<String> list){
return list.toString();
}
但是如果list中是类对象,或者别的都不好传参,这时候可以传递json数据
7,传递JSON数据
JSON:JavaScript Object Notation 【JavaScript 对象表示法】
JSON是⼀种轻量级的数据交互格式,它基于ECMAScript(欧洲计算机协会制定的js规范)的⼀个子集, 采用完全独立于编程语言的文本格式来存储和表示数据
简单来说:JSON就是⼀种数据格式,有自己的格式和语法,使用文本表示⼀个对象或数组的信息,因此 JSON本质是字符串. 主要负责在不同的语⾔中数据传递和交换.
JSON与Javascript的关系:没有关系,只是语法相似,js开发者能更快的上⼿⽽已,但是他的语法本⾝⽐较简单,所以也很好学
JSON语法
JSON是⼀个字符串,其格式非常类似于JavaScript对象字面量的格式
{
"squadName": "Super hero squad",
"homeTown": "Metro City",
"formed": 2016,
"secretBase": "Super tower",
"active": true,
"members": [
{
"name": "Molecule Man",
"age": 29,
"secretIdentity": "Dan Jukes",
"powers": [
"Radiation resistance",
"Turning tiny",
"Radiation \\nblast"
]
},
{
"name": "Madame Uppercut",
"age": 39,
"secretIdentity": "Jane Wilson",
"powers": [
"Million tonne punch",
"Damage resistance",
"Superhuman \\nreflexes"
]
},
{
"name": "Eternal Flame",
"age": 1000000,
"secretIdentity": "Unknown",
"powers": [
"Immortality",
"Heat Immunity",
"Inferno",
"Teleportation",
"Interdimensional travel"
]
}
]
}
JSON的语法
1,数据在键值对(key/value)中
2,数据由逗号,分隔
3,对象用{}表示
4,数组用 [] 表示
5,值可以为对象,也可以为数组,数组中可以包含多个对象
JSON的两种结构
1,对象:大括号{} 保存的对象是一个无序的键值对集合,一个对象以左括号{ 开始,右括号 } 结束。每个“键”后面跟一个冒号:,键值对之间使用逗号,分隔
2,数组:中括号[] 保存的数组是值(value)的有序集合,一个数组以左中括号 [ 开始,右中括号 ] 结束,值与值之间使用逗号,分隔
{"name":"admin","age":18},
["hello", 3.1415, "json"],
[{"name":"admin","age":18},{"name":"root","age":16},{"name":"\\n张三\\n","age":20}]
JSON字符串和Java对象互转
JSON本质上是⼀个字符串,通过文本来存储和描述数据
Spring MVC框架也集成了JSON的转换⼯具,我们可以直接使⽤,来完成JSON字符串和Java对象的互转
public class JacksonTest {
public static void main(String[] args) {
ObjectMapper objectMapper = new ObjectMapper();
Person person = new Person();
person.setId(12);
person.setAge(18);
person.setName("zhangsan");
person.setAddress("beijing");
//对象转为json字符串
String s = objectMapper.writeValueAsString(person);
System.out.println(s);
//json字符串转为对象
String jsonStr = "{\\"address\\":\\"beijing\\",\\"age\\":18,\\"id\\":12,\\"name\\":\\"zhangsan\\"}";
Person person1 = objectMapper.readValue(jsonStr, Person.class);
System.out.println(person1);
}
}
JSON优点
1. 简单易用:语法简单,易于理解和编写,可以快速地进⾏数据交换
2. 跨平台⽀持: JSON可以被多种编程语⾔解析和⽣成,可以在不同的平台和语⾔之间进⾏数据交换和 传输
3. 轻量级:相较于XML格式,JSON数据格式更加轻量级,传输数据时占⽤带宽较⼩,可以提⾼数据传输 速度
4. 易于扩展: JSON的数据结构灵活,⽀持嵌套对象和数组等复杂的数据结构,便于扩展和使⽤
5. 安全性:JSON数据格式是⼀种纯⽂本格式,不包含可执⾏代码,不会执⾏恶意代码,因此具有较高的安全性
传递JSON对象
接收JSON对象,需要使用@RequestBody 注解
RequestBody: 请求正文,意思是这个注解作用在请求正文的数据绑定,请求参数必须在写在请求正文中
@RequestMapping("/r6")
public String r6(@RequestBody Person person){
return person.toString();
}
8,获取URL中参数@PathVariable
path variable :路径变量
和字⾯表达的意思⼀样,这个注解主要作⽤在请求URL路径上的数据绑定
默认传递参数写在URL上,SpringMVC就可以获取到
@RequestMapping("/r7/{id}")
public String r7(@PathVariable Integer id){
return "从url中获取id:"+id;
}

如果⽅法参数名称和需要绑定的URL中的变量名称⼀致时,可以简写,不⽤给@PathVariable的属性赋值,如上述例⼦中的id变量
@RequestMapping("/r8/{id}/{name}")
public String r8(@PathVariable("id") Integer userId, @PathVariable("name") String
userName){
return "从url中获取id:"+userId +",type: "+ userName;
}
如果⽅法参数名称和需要绑定的URL中的变量名称不⼀致时,需要@PathVariable的属性value赋值, 如上述例⼦中的userName变量.
9,上传文件@RequestPart
@RequestMapping("/r11")
public String r11(@RequestPart("file") MultipartFile multipartFile) throws IOException {
System.out.println(multipartFile.getOriginalFilename());
//文件上传
File file = new File("D:/test/"+multipartFile.getOriginalFilename());
multipartFile.transferTo(file);
return "文件上传成功";
}



