目录
一、什么是 Spring Web MVC
1、MVC 定义
二、学习Spring MVC
1、项目准备
2、建立连接
2.1 @RequestMapping 注解的学习
2.2 @RequestMapping 使用
3、请求
3.1 传递单个参数
3.2 传递多个参数
3.3 传递对象
3.4 后端参数重命名(后端参数映射)
3.5 传递数组
3.6 传递集合
3.7 传递JSON数据
1、JSON语法
2、JSON字符串和Java对象互转
3、JSON优点
4、传递JSON对象
3.8 获取URL中参数@PathVariable
3.9 上传文件@RequestPart
一、什么是 Spring Web MVC
官方对于 Spring MVC 的描述是这样的:
什么是Servlet呢?
Servlet 是⼀种实现动态页面的技术. 准确来讲Servlet是⼀套 Java Web 开发的规范,或者说是⼀套 Java Web 开发的技术标准. 只有规范并不能做任何事情,必须要有人去实现它. 所谓实现 Servlet 规 范,就是真正编写代码去实现 Servlet 规范提到的各种功能,包括类、方法、属性等.Servlet 规范是开放的,除了 Sun 公司,其它公司也可以实现 Servlet 规范,目前常见的实现了Servlet 规范的产品包括 Tomcat、Weblogic、Jetty、Jboss、WebSphere 等,它们都被称为"Servlet 容器". Servlet 容器用来管理程序员编写的 Servlet 类.
总之,我们可以知道:Spring Web MVC 是⼀个 Web 框架. 简称 “Spring MVC”。
1、MVC 定义
MVC 是⼀种架构设计模式, 也⼀种思想, 而 Spring MVC 是对 MVC 思想的具体实现 . 除此之外, Spring MVC还是⼀个Web框架.总结来说, Spring MVC 是⼀个实现了 MVC 模式的 Web 框架 .
二、学习Spring MVC
- 建立连接:将用户(浏览器)和 Java 程序连接起来,也就是访问⼀个地址能够调用到我们的 Spring 程序。
- 请求:用户请求的时候会带⼀些参数,在程序中要想办法获取到参数, 所以请求这块主要是 获取参数的功能.
- 响应:执行了业务逻辑之后,要把程序执行的结果返回给用户, 也就是响应。
1、项目准备
2、建立连接
我们通过一个简单的代码来实现一下:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class demo {@RequestMapping("/hello")public String getHello() {return "Hello,Spring MVC";}
}
然后来访问: http://127.0.0.1:8080/hello, 就可以看到程序返回的数据了,如图:
2.1 @RequestMapping 注解的学习
路由映射: 当用户访问⼀个 URL 时, 将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射.
那么对于程序中加的 @RestController 注解有什么作用?
我们把 @RestController 去掉, 再来访问⼀次:
可见,报错了404,我们找不到该页面。所以@RestController 注解也很重要,不能不加。
一个项目中, 会有很多类, 每个类可能有很多的方法, Spring程序怎么知道要执行哪个方法呢?
Spring会对所有的类进行扫描, 如果类加了注解@RestController, Spring才会去看这个类里面的方法有没有加 @RequestMapping 这个注解。
2.2 @RequestMapping 使用
@RequestMapping标识⼀个类:设置映射请求的请求路径的初始信息@RequestMapping标识⼀个方法:设置映射请求的请求路径的具体信息
看如下代码:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/test")
@RestController
public class demo {@RequestMapping("/hello")public String getHello() {return "Hello,Spring MVC";}
}
访问地址:http://127.0.0.1:8080/test/hello
这里我们注意一下:
@RequestMapping 的URL 路径最前面加不加 / (斜杠)都可以, Spring程序启动时, 会进行判断, 如果 前面没有加 / , Spring会拼接上⼀个 /。如:
上面代码中 @RequestMapping("/test") 我们可以写为 @RequestMapping("test")通常情况下,我们加上 / 。@RequestMapping 的URL路径也可以是多层路径, 最终访问时, 依然是 类路径 + 方法路径
@RequestMapping("/user/m1")
@RestController
public class UserController {@RequestMapping("/say/hi")public String sayHi(){return "hello,Spring MVC";}
}
3、请求
3.1 传递单个参数
接收单个参数, 在 Spring MVC 中直接用方法中的参数就可以,比如以下代码:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/param")
public class ParamController {@RequestMapping("/m1")public String method1(String name){return "接收到参数name:"+ name;}
}
由响应的结果,可以看到, 后端程序正确拿到了name参数的值.
Spring MVC 会根据方法的参数名, 找到对应的参数, 赋值给方法如果参数名不⼀致, 是获取不到参数的.比如请求URL: http://127.0.0.1:8080/param/m1?name1=spring响应结果:
注意:
我们以下面代码为例,来测试一下:
@RequestMapping("/m1/int")
public String method1GetInt(int age) {return "接收到参数age:"+age;
}
1、正常传递参数
2、不传递age参数
http://127.0.0.1:8080/param/m1/int
浏览器响应情况:
报500 错误,可见 使用基本类型来接收参数时, 参数必须传(除boolean类型), 否则会报500错误。
3、传递参数类型不匹配
报400 错误,可见 传递的参数类型不匹配时, 会报400错误.
3.2 传递多个参数
@RequestMapping("/m2")
public Object method2(String name, String password) {return "接收到参数name:" + name + ", password:" + password;
}
可以看到, 后端程序正确拿到了name和password参数的值。
3.3 传递对象
public class Student {private Integer id;private String name;private int age;public Student(){}public Student(Integer id, String name, int age) {this.id = id;this.name = name;this.age = age;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setId(Integer id) {this.id = id;}public Integer getId() {return id;}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", id=" + id +'}';}
}
传递对象代码实现:
@RequestMapping("/m3")
public Object method3(Student student){return student.toString();
}
可以看到, 后端程序正确拿到了Student对象里各个属性的值。
3.4 后端参数重命名(后端参数映射)
@RequestMapping("/m4")
public Object method4(@RequestParam("time") String createtime) {return "接收到参数createtime:" + createtime;
}
响应:
通过控制台打印的日志信息显示: 请求参数 'time' 不存在。
- 使用 @RequestParam 进行参数重命名时, 请求参数只能和 @RequestParam 声明的名称⼀ 致, 才能进行参数绑定和赋值.
- 使用 @RequestParam 进行参数重命名时, 参数就变成了必传参数.
那么如何进行非必传参数的设置呢?
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {@AliasFor("name")String value() default "";@AliasFor("value")String name() default "";boolean required() default true;String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}
@RequestMapping("/m4")
public Object method4(@RequestParam(value = "time", required = false) String createtime) {return "接收到参数createtime:" + createtime;
}
可以看到, 添加required=false之后, time前⾯也加了key, 变成了 value = "time"注解属性赋值时, 没有指明key的话, 默认为value属性.如果需要有多个属性进行赋值时, 需要写上key
3.5 传递数组
@RequestMapping("/m5")
public String method5(String[] array) {return "接收到参数:"+ Arrays.toString(array);
}
数组参数:请求参数名与形参数组名称相同且请求参数为多个, 后端定义数组类型形参即可接收参数http://127.0.0.1:8080/param/m5? array=zhangsan&array=lisi&array=wangwu或者使用 http://127.0.0.1:8080/param/m5?array=zhangsan,lisi,wangwu
浏览器响应结果:
3.6 传递集合
默认情况下,请求中参数名相同的多个值,是封装到数组. 如果要封装到集合,要使用@RequestParam 绑定参数关系。
请求方式和数组类似:
%2c 是逗号的转义编码, 解码后的url为:http://127.0.0.1:8080/param/m6? listParam=zhangsan,lisi,wangwu
后端接收代码:
@RequestMapping("/m6")
public String method6(@RequestParam List<String> listParam){return "size:"+listParam.size() + ",listParam:"+listParam;
}
3.7 传递JSON数据
注意: JSON与Javascript的关系: 没有关系, 只是语法相似
1、JSON语法
{"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 blast"]}, {"name": "Madame Uppercut","age": 39,"secretIdentity": "Jane Wilson","powers": ["Million tonne punch", "Damage resistance", "Superhuman reflexes"]}, {"name": "Eternal Flame","age": 1000000,"secretIdentity": "Unknown","powers": ["Immortality", "Heat Immunity", "Inferno","Teleportation", "Interdimensional travel"]}]
}
- 数据在键值对(Key/Value) 中
- 数据由逗号 , 分隔
- 对象用 {} 表示
- 数组用 [] 表示
- 值可以为对象, 也可以为数组, 数组中可以包含多个对象
- 对象: 大括号 {} 保存的对象是⼀个无序的 键值对 集合. ⼀个对象以左括号 { 开始, 右括号 } 结束。每个"键"后跟⼀个冒号: ,键值对使用逗号 , 分隔
- 数组: 中括号 [] 保存的数组是值(value)的有序集合. ⼀个数组以左中括号 [ 开始, 右中括 号 ] 结束,值之间使用逗号 , 分隔
2、JSON字符串和Java对象互转
JSON本质上是⼀个字符串, 通过文本来存储和描述数据。
Spring MVC框架也集成了JSON的转换工具, 我们可以直接使用, 来完成JSON字符串和Java对象的互转。
参考代码如下:
public class JSONUtils {private static ObjectMapper objectMapper = new ObjectMapper();public static void main(String[] args) throws JsonProcessingException {Person person = new Person();person.setId(5);person.setName("zhangsan");person.setPassword("123456");//对象转为JSON字符串String jsonStr = objectMapper.writeValueAsString(person);System.out.println("JSON字符串为:"+jsonStr);//JSON字符串转为对象Person p = objectMapper.readValue(jsonStr,Person.class);System.out.println("转换的对象id:"+p.getId()+",name:"+p.getName()+",password:"+p.getPassword());}
}
使用ObjectMapper 对象提供的两个方法, 可以完成对象和JSON字符串的互转writeValueAsString: 把对象转为JSON字符串readValue: 把字符串转为对象
3、JSON优点
- 简单易用: 语法简单,易于理解和编写,可以快速地进行数据交换
- 跨平台支持: JSON可以被多种编程语言解析和生成, 可以在不同的平台和语言之间进行数据交换和传输
- 轻量级: 相较于XML格式, JSON数据格式更加轻量级, 传输数据时占用带宽较小, 可以提高数据传输速度
- 易于扩展: JSON的数据结构灵活,支持嵌套对象和数组等复杂的数据结构,便于扩展和使用
- 安全性: JSON数据格式是⼀种纯文本格式,不包含可执行代码, 不会执行恶意代码,因此具有较高的安全性
4、传递JSON对象
RequestBody: 请求正文,意思是这个注解作用在请求正文的数据绑定,请求参数必须在写在请求正文中。
后端实现:
@RequestMapping(value = "/m7")
public Object method7(@RequestBody Person person) {return person.toString();
}
这里我们来使用postman工具测试我们的后端程序,
可以看到, 后端正确接收了.
去除掉 @RequestBody 的结果:
可见,后端未能成功给Person对象赋值。
3.8 获取URL中参数@PathVariable
@RequestMapping("/m8/{id}/{name}")
public String method8(@PathVariable Integer id, @PathVariable("name") String userName){return "解析参数id:"+id+",name:"+userName;
}
如果方法参数名称和需要绑定的URL中的变量名称⼀致时, 可以简写, 不用给@PathVariable的属性赋值 , 如上述例子中的id变量;如果方法参数名称和需要绑定的URL中的变量名称不⼀致时, 需要@PathVariable的属性value赋值, 如上述例⼦中的userName变量。
3.9 上传文件@RequestPart
后端代码实现:
@RequestMapping("/m9")
public String getfile(@RequestPart("file") MultipartFile file) throws IOException {//获取⽂件名称String fileName = file.getOriginalFilename();//⽂件上传到指定路径file.transferTo(new File("D:/temp/" + file.getOriginalFilename()));return "接收到⽂件名称为: "+fileName;
}
使用Postman发送请求:
然后观察 D:/temp 路径下, 文件是否上传成功。
该篇文章就先介绍到这里了,后续内容在下篇《Spring Web Mvc的入门学习(二)》,欢迎继续收看。