SpringMVC程序开发
- 1. 认识SpringMVC
- 1.1 SpringMVC是什么
- 1.2 SpringMVC的定义
- 1.3 MVC和SpringMVC的关系
- 经典问题:Spring / SpringBoot / SpringMVC有什区别
- 2. 学习SpringMVC的思路
- 3. Spring MVC的创建和连接
- 3.0 创建方法
- 3.1 使用到的一些注解
- 3.2 返回一个页面
- 3.3 关于@Controller的约定
- 3.4 @RequestMapping( )支持什么类型的访问方式呢
- 3.5 设置@RequestMapping( )的访问方式
- 3.6 用@GetMapping和@PostMapping标注请求方式
- 4. 获取参数
- 4.1 传递单个参数
- 4.2 获取多个参数
- 4.3 获取多个参数(用对象接收)
- 4.4 获取表单参数
- 4.5 获取ajax请求的参数
- 4.6 获取 json参数
- 1. 利用postman构造 json参数
- 2. 发送请求
- 3. @RequestBody——告诉后端从body里面获取参数
- 4.7 上传文件@RequestPart
- 1. 利用postman上传图片文件
- 2. 路由代码,保存文件
- 3. 测试结果
- 4.8 获取Cookie
- 1. 在谷歌浏览器模拟创建一个Cookie
- 2. 路由代码
- 3. 测试结果
- 4.9 获取Session
- 1. 先设置一个Session
- 2. 获取Session
- 3.10 获取header
- 4.11 重命名前端参数@RequestParam(了解)
- 4.11 获取URL中参数@PathVariable
- 5. 返回数据
- 5.1 返回静态页面
- 5.2 返回 text / html
- 5.3 返回JSON对象
- 5.4 请求转发 和 请求重定向
- 1.控制器代码
- 2.请求转发的效果
- 3. 请求重定向效果
- 4.请求转发或请求重定向的对比
1. 认识SpringMVC
1.1 SpringMVC是什么
SpringMVC是一个原始的基于Servlet API 的web框架,从一开始就包括在Spring当中。
1.2 SpringMVC的定义
MVC就是Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分
- Model(模型)是应⽤程序中⽤于处理应⽤程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
- View(视图)是应⽤程序中处理数据显示的部分。通常视图是依据模型数据创建的。
- Controller(控制器)是应⽤程序中处理⽤户交互的部分。通常控制器负责从视图读取数据,控制⽤户输⼊,并向模型发送数据。
1.3 MVC和SpringMVC的关系
MVC是一种思想,而SpringMVC是MVC思想的一种实现,并且SpringMVC还继承了Servlet API 的 Web框架
经典问题:Spring / SpringBoot / SpringMVC有什区别
- Spring是包含了许多工具的IOC容器,通过IOC容器可以有效的降低代码的耦合度
- SpringBoot 就是用来快速的开发Spring框架的,他底层就是基于Spring
- SpringMVC就只是Spring众多模块中的一个,它是一个web框架,它的诞生早于SpringBoot
2. 学习SpringMVC的思路
- 连接
- 取参
- 返回数据
3. Spring MVC的创建和连接
3.0 创建方法
Spring MVC的创建和SpringBoot的创建方式是一样的,详见:SpringBoot的创建
3.1 使用到的一些注解
之所以创建的项目是一个Spring MVC,是因为在SpringBoot中选择了这个模块:
在创建好的SpringMVC项目的demo目录下创建一个UserController:
在上面代码中,有两个注释:@Controller,@ResponseBody,这两个注释在之前的SpringBoot中并没有使用到,但是它两合起来的作用其和@RestController是一样的。@RestController是一个组合注解。
它两的作用分别如下:
- 加入@Controller类注解是让Spring框架启动时,加载这个类
- 加入@ResponseBody注解是表明返回非页面数据
@RequestMapping 注解介绍:
@RequestMapping 是 Spring Web 应⽤程序中最常被⽤到的注解之⼀,它是⽤来注册接⼝的路由映射的。
路由映射:所谓的路由映射指的是,当⽤户访问⼀个 url 时,将⽤户的请求对应到程序中某个类的某个⽅法的过程就叫路由映射
测试结果:
3.2 返回一个页面
如果你返回的是一个页面,那就可以注释去掉@ResponseBody注解:
运行结果:
3.3 关于@Controller的约定
在上面所示的代码中,我们适应到了@Controller注解,在业务上,它的作用就是让Spring框架启动时,加载这个类。那么,能不能把它换成其他的类注解呢,比如Service?
答案时不能,因为在SpringMVC约定就是用@Controller,这就是设计时的一种规范。
3.4 @RequestMapping( )支持什么类型的访问方式呢
我们用postman来测试一下:
通过用postman测试发现:@RequestMapping( )默认是支持全部类型的访问方式。
3.5 设置@RequestMapping( )的访问方式
此时再永GET以外的方式进行访问时,就会有如下结果:
3.6 用@GetMapping和@PostMapping标注请求方式
标注为GET请求:@GetMapping(“/index”)
标注为POST请求:@PostMapping(“/index”)
GET请求的三种写法:
// 写法1
@RequestMapping("/index")
// 写法2
@RequestMapping(value = "/index",method = RequestMethod.GET)
// 写法3
@GetMapping("/index")
POST请求的三种写法:
// 写法1
@RequestMapping("/index")
// 写法2
@RequestMapping(value = "/index",method = RequestMethod.POST)
// 写法3
@PostMapping("/index")
4. 获取参数
4.1 传递单个参数
代码:
@Controller
@ResponseBody
public class UserController {
@RequestMapping("/hi")
public String sayHi(String name){//想要那个参数,就写那个参数
return "参数:"+name;
}
}
测试结果:
4.2 获取多个参数
代码:
@Controller
@ResponseBody
public class UserController {
@RequestMapping("/hi")
public String sayHi(String name,String password){
return "参数1:"+name+" | 参数2:"+password;
}
}
测试结果:
4.3 获取多个参数(用对象接收)
当参数的数量足够多的时候,如果像上面这样获取的话,操作起来就会麻烦很多,所以就将它封装成对象,使得操作简单一点。
先创建一个User类:
代码:
@RequestMapping("/get1")
public String get1(User user){
return user.toString();
}
测试结果:
注意:前端传过来的参数名和应该和User类中参数的名字一样.
4.4 获取表单参数
当表单参数比较少时,就可以通过获取多个参数的形式进行获取。
当表单的数据较多时,可以通过用对象接收的方式进行获取。
先创建一个表单:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>index测试页面</title>
</head>
<body>
<h1>这是一个index页面</h1>
</body>
</html>
测试代码(用对象接收):
@RequestMapping("/login")
public String login(Student student){
return student.toString();
}
测试结果:
4.5 获取ajax请求的参数
前端代码:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
<div>
<h1> 登陆 </h1>
用户:<input id="name"><br>
密码:<input id="password"><br>
<input type="button" onclick="onsub()" value="提交">
</div>
<script>
function onsub(){
jQuery.ajax({
url:"login2",
type:"GET",
data:{"username":jQuery("#name").val(),"password":jQuery("#password").val()},
success:function(result){
alert(result);
console.dir(result);
}
});
}
</script>
</body>
</html>
路由代码:
@RequestMapping("/login2")
public HashMap<String,Object> login2(String name,String password){
HashMap<String,Object> result = new HashMap<>();
result.put("name",name);
result.put("password",password);
return result;
}
测试结果:
4.6 获取 json参数
1. 利用postman构造 json参数
2. 发送请求
@RequestMapping("/login2")
public HashMap<String,Object> login2(String name,String password){
HashMap<String,Object> result = new HashMap<>();
result.put("name",name);
result.put("password",password);
return result;
}
可以看到,此时拿到的 json参数 为空,为什么呢?
因为后端默认是从非body里面获取参数,要想获取body里面的数据,就得加一个注解,告诉它从body里面获取参数。
3. @RequestBody——告诉后端从body里面获取参数
@RequestMapping("/login2")
public HashMap<String,Object> login2(@RequestBody Student student){
HashMap<String,Object> result = new HashMap<>();
result.put("name",student.getName());
result.put("password",student.getPassword());
return result;
}
测试结果:
特别注意: 用@RequestBody获取时,只能获取到一个json对象,而不能获取到某个具体的属性。
4.7 上传文件@RequestPart
1. 利用postman上传图片文件
2. 路由代码,保存文件
@RequestMapping("/getparam")
public String getParam(String name, @RequestPart("myfile")MultipartFile file) throws IOException {
//将文件进行保存
file.transferTo(new File("C:\\work\\img1.png"));//设置目录并且设置文件名
return "上传成功!";
}
在上面保存文件时,是直接将文件格式写死的,其实也可以设置动态路径,比如:
@RequestMapping("/param9")
public String param9(String name, @RequestPart("myfile") MultipartFile file) throws IOException {
// 获取⽂件后缀名
String fileName = file.getOriginalFilename().substring(file.getOrigina
lFilename().lastIndexOf("."));
// ⽂件保存地址
String filePath = ClassUtils.getDefaultClassLoader().getResource("stat
ic").getPath() +
"/" + UUID.randomUUID() + fileName;
// 保存⽂件
file.transferTo(new File(filePath));
return filePath + " 上传成功.";
}
3. 测试结果
就会有如下文件:
4.8 获取Cookie
1. 在谷歌浏览器模拟创建一个Cookie
2. 路由代码
@RequestMapping("/getcookie")
public String getCookie(@CookieValue("name") String name){//拿到名字为name的Coookie,并将他赋值给String name.
return "name: "+name;
}
3. 测试结果
4.9 获取Session
1. 先设置一个Session
@RequestMapping("setsession")
public String setSession(HttpServletRequest request){
//获取HttpSession对象,设置参数为true表示如果没有session对象就创建一个session对象
HttpSession session = request.getSession(true);
if(session!=null){
session.setAttribute("username","lifeifei");
}
return "存储成功!";
}
2. 获取Session
@RequestMapping("/getsession")
public String getSession(@SessionAttribute(value = "username",required = false) String username){
return "username: "+username;
}
3.10 获取header
代码:
@RequestMapping("/getheader")
public String getHeader(@RequestHeader("User-Agent") String userAgent){
return "header:"+userAgent;
}
@RequestHeader(“User-Agent”) 表示读取header里面的 user-Agent 信息
测试结果;
4.11 重命名前端参数@RequestParam(了解)
某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不⼀致,⽐如前端传递了⼀个time 给后端,⽽后端⼜是有 createtime 字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使⽤ @RequestParam 来重命名前后端的参数值
代码:
@RequestMapping("/m4")
public Object method_4(@RequestParam("time") String createtime) {
System.out.println("时间:" + createtime);
return createtime;
}
测试结果:
4.11 获取URL中参数@PathVariable
代码:
@GetMapping("/m6/{name}/{password}")
public Object method_6(@PathVariable String name, @PathVariable String password) {
return "name:" + name+" | password:" + password;
}
5. 返回数据
我们知道:默认请求下⽆论是 Spring MVC 或者是 Spring Boot 返回的是视图(xxx.html),⽽现在都是前后端分离的,后端只需要返给给前端数据即可,这个时候我们就需要使⽤@ResponseBody 注解了。
5.1 返回静态页面
创建前端⻚⾯ index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>index测试页面</title>
</head>
<body>
<h1>这是一个index页面</h1>
</body>
</html>
创建控制器:
@Controller
public class RetData {
@RequestMapping("/retindex")
public Object retIndex(){
return "/index.html";
}
}
测试结果:
5.2 返回 text / html
控制器中路由代码:
@RequestMapping("rethello")
@ResponseBody
public String retHello(){
return "<h1>Hello,HTML~</h1>";
}
测试结果:
5.3 返回JSON对象
控制器代码:
@RequestMapping("/retjson")
@ResponseBody
public HashMap<String,Object> retJson(){
HashMap<String,Object> map = new HashMap<>();
map.put("name","lifeifei");
map.put("age","19");
map.put("sex","man");
return map;
}
浏览器测试结果:
Fiddler抓包结果:
可以看出,当返回给前端的数据类型为HashMap时,默认的数据格式是JSON。
5.4 请求转发 和 请求重定向
forward:请求转发
redirect:请求重定向
1.控制器代码
@Controller
public class TestController {
/*
请求转发
*/
@RequestMapping("/req_forward")
public Object req_forward(){
return "forward:index.html";
}
/*
请求重定向
*/
@RequestMapping("/req_redirect")
public Object req_redirect(){
return "redirect:index.html";
}
}
2.请求转发的效果
请求转发之后,访问的页面URL没有变,但是却显示了index.html页面的内容
3. 请求重定向效果
在浏览器输入 http://localhost:8080/req_redirect,一按回车之后:
请求重定向之后,输入的URL发生变化,直接跳转到另一个网页。
4.请求转发或请求重定向的对比
forward 和 redirect 具体区别如下:
- 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发。
- 请求重定向地址发⽣变化,请求转发地址不发⽣变化。
- 请求重定向与直接访问新地址效果⼀直,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问