Spring MVC是一个基于Servlet API构建的web框架,它包含在Spring框架中,是Spring的核心。它包含三层架构:表现层、业务层、数据访问层。其中的MVC是指Model(模型)、View(视图)、Controller(控制器)三个单词的缩写,它是表现层里面的东西,它是软件工程当中的一种软件架构模型,该模型将软件系统分为模型、视图、控制器三个基本部分:
1.Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
2.View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
3.Controller(控制层)是应用层序中处理用户交互的部分。通常控制层负责从视图读取数据,控制用户输入,并向模型发送数据。
学习Spring MVC最主要就是学习创建一个web项目,而创建一个web项目,就需要从以下三点出发:
- 连接功能:将用户(浏览器)和Java程序连接起来
- 获取参数的功能:用户在访问的时候会带一些参数,在程序中得想办法获取到这些参数
- 输出数据的功能:将程序执行的结果返回个用户
Spring MVC创建和连接
Spring MVC的创建和Spring Boot一样,只不过再添加框架的时候多添加一个web框架就可以了。
Spring MVC的连接方式有三种:使用@RequestMapping注解、使用@GetMapping注解、使用@PostMapping注解。这三种注解作用都是用来注册一个url路由,通过这个路由,前端的请求就可以实现和后端程序的交互,区别就是@RequestMapping注解既能修饰类也可以修饰方法,而@GetMapping注解、@PostMapping注解只能用来修饰方法。
@RequestMapping注解
@RequestMapping这个注解既可以修饰方法又可以修饰类,默认情况下@RequestMapping会返回一个html页面,当加上@ResponseBody注解之后就能够返回非页面数据了,当@ResponseBody放在类上时,那么整个类中的方法返回的就是非页面数据。
1.@RequestMapping在不指定任何参数的情况下,可以支持任何方法的请求(get/post...) ;
2.当给@RequestMapping设置了method属性之后,它只能支持设置的请求类型,其他类型会报错(405)
@GetMapping注解
@GetMapping注解 就相当于@RequestMapping(value = "/hi",method = RequestMethod.GET)
使用该注解,只能发送GET请求
@PostMapping
@PostMapping注解就相当于@RequestMapping(value = "/hi",method = RequestMethod.POST)
使用该注解,只能发送POST请求
Spring MVC获取参数
获取单个参数
在Spring MVC中可以直接用方法中的参数来实现传参:
一:在传递单个参数的时候一定要注意,前端传递的参数key一定要和方法中的参数名一致,否者无法获取到参数。传递时推荐使用包装类,而不是基本数据类型,因为传递基本数据类型时没有获取到参数,服务器就会报错。
二:传递的参数顺序可以不一样
获取对象
单个参数传递的方式在参数很多时就不适用了,这个时候往往是使用传递对象的方式来获取参数。
package com.example.springmvc.model;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class User {
private String name;
private Integer age;
private Integer id;
private Integer sex;
}
package com.example.springmvc.controller;
@Controller
@ResponseBody //当前的方法(或者类)返回是非页面的数据,如果不加这个注解就会返回一个页面
public class UserController {
@GetMapping("/get-object")
public Object GetObject(User user){
return user;
}
}
重命名后端参数
现在的Spring项目基本上都是前后端分离的,前端和后端负责的类容不一样,有时会遇到前端传递的参数中的key和后端方法中的key名称不一样的情况,而且后端方法中key在很多处都有设置,这个时候去改后端的参数就显得不现实,为了解决这一问题,就引出了重命名后端方法中参数的方法。
只需要在后端参数前面加上一个@RequestParam("key")注解即可,它的原理就是将前端的time的key值赋值给后端的createtime变量:
@GetMapping("/get-time")
public String GetTime(String createtime){
return "时间:"+createtime;
}
@GetMapping("/get-time")
public String GetTime(@RequestParam("time") String createtime){
return "时间:"+createtime;
}
@RequestParam("key")注解有一个特点那就是使用这个注解它默认key值必须传递,如果不传递的话则会报错:
若想使用这个注解,但是又不确定是否要传递参数,这个时候只需要将该注解的required()参数改为false即可:
@GetMapping("/get-time")
public String GetTime(@RequestParam(value = "time",required = false) String createtime){
return "时间:"+createtime;
}
利用@RequestBody获取JSON对象
在企业中前端发送数据一般都是以JSON格式的形式来传递请求参数,但是在后端如果不对JSON格式的数据做处理,后端是拿不到响应的数据的:
@PostMapping("/post-object")
public Object PostObject(User user){
return user;
}
只有在后端获取JSON数据方法参数的前面加上@RequestBody这个注解才行:
@PostMapping("/post-object")
public Object PostObject(@RequestBody User user){
return user;
}
获取URL中的参数
有些公司的网址中就包含有一些参数信息,这样做的好处用户在搜索时能够快速的定位到这个网址中的关键信息。这种URL的格式一般如下面这样:
....../m6/{name}/{password}
上面m6是路由地址,根据设定而不同。name、password就是参数,凡是带来花括号的都是参数。
在获取这样的参数时,需要用到@PathVariable这个注解
@GetMapping("/p/{name}/{password}")
public String GetUrlMess(@PathVariable String name,@PathVariable String password){
return "姓名:"+name+", 密码:"+password;
}
利用@RequestPart注解上传文件
在发送请求时,有时会遇到上传文件的操作,这个时候只需要利用@RequestPart注解即可,在上传文件之前,的先配置一下开发环境和生产环境,然后让程序自动生成一个文件名唯一的文件:
一:配置生产环境和开发环境
上面文件的格式必须这样写application-文件名.properties
因为我们要上传文件,所以就得指定要上传到文件的目录:
然后在控制层里面读取配置文件:
然后在利用@RequestPart注解来上传文件操作:
@PostMapping("/file")
public String upload(@RequestPart("myfile") MultipartFile file) throws IOException {
//1.上传文件(从配置文件中读取)
String basePath = uploadPath;
//2.生成动态文件名(包含后缀),通过uuid的方式来生成一个不同文件名的文件
String fileName = UUID.randomUUID()+(file.getOriginalFilename().substring(
file.getOriginalFilename().lastIndexOf(".")
));
System.out.println();
System.out.println("fileName="+fileName);
System.out.println();
//3.保存文件
file.transferTo(new File(basePath+fileName));
return "上传成功";
}
利用postman来上传一张图片到指定的文件中:
查看结果:
获取Cookie/Session/header
一:获取Cookie
当用户发送请求时,浏览器会带上Cookie/Session/header相关的信息,这些信息对于校验登录状态等很有帮助,所以也应该获取这部分数据。
方式一:使用传统Servlet的方式获取Cookie等信息
之所以可以利用这种方式,是因为在SpringMvc中,所有映射方法中默认就包含HttpServletRequest和HttpServletResponse两个对象
@GetMapping("/getck")
public Cookie[] getCk(HttpServletRequest request, HttpServletResponse response){
//得到所有的Cookie
Cookie[] cookies = request.getCookies();
return cookies;
}
在浏览器上面访问的时候,因为我们没有配置Cookie,所以什么都访问不到:
为了获取到Cookie信息,我们就需要伪造Cookie:
在这上面我们就伪造了两个Cookie:java、mysql
刷新浏览器:
方式二:使用@CookieValue注解的方式获取到Cookie
@GetMapping("/getck2")
public String getCk2(@CookieValue("java") String java){
return java;
}
二:获取Session
获取Session的方式同获取Cookie一样也是两种
方式一:使用传统Servlet的方式获取Cookie等信息
为了获取到Session,首先就得存储Session
@RequestMapping("/setsession")
public String setsession(HttpServletRequest request){
//这里的参数设置为true,表示如果没有session、对象就创建一个session
HttpSession session = request.getSession(true);
if(session!=null){
session.setAttribute("username","MysSQL");
}
return "设置Session成功";
}
@RequestMapping("/getSession")
public String getSession(HttpServletRequest request){
//这里的参数设置为false,表示Seesion不存在则不会创建
HttpSession session = request.getSession(false);
String username = "没有";
if(session!=null&&session.getAttribute("username")!=null){
username = (String) session.getAttribute("username");
}
return "username:"+username;
}
方式二:使用@SessionAttribute注解获取Session
@RequestMapping("/getSession2")
public String getSession2(@SessionAttribute(value = "username",required = false) String username){
return "username:"+username;
}
三:获取header
使用@RequestHeader注解来获取header中的某项数据
@RequestMapping("/header")
public String header(@RequestHeader("User-Agent")String userAgent){
return "userAgent:"+userAgent;
}
总结Spring MVC获取参数的方法:
1. 获取单个参数(几个参数):在方法中写相应的参数就可以实现;
2.获取对象:在方法中直接写对象就可以实现;
3.获取JSON对象:将@RequestBody注解加到方法中的参数的前面;
4.获取文件:使用@RequestPart注解;
5.获取用户的Cookie/Session/Header:分别使用@CookieValue/@SessionAttribute/@RequestHeader注解
Spring MVC返回参数
返回静态页面
为了返回一个静态的页面,首先就得写一个html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Hello Spring MVC</h1>
</body>
</html>
然后在控制层里面调用这个html文件:
@RequestMapping("/index")
public Object index(){
return "/index.html";
}
如果上面不把@ResponseBody屏蔽掉,加载出来的就是非页面的东西
返回text/html
@RequestMapping("/text")
public String text(){
return "<h1>李华</h1>";
}
注意在代码的最上面是加了@ResponseBody注解的,如果不加就会返回一个页面
这里虽然我们返回的是一个html格式的文件,但是这个请求的Content-Type确实是text/html的,我们可以通过抓包来观察:
之所以会这样,是因为Spring MVC它底层做了一个适配
返回JSON对象
@RequestMapping("/json")
public HashMap<String,Object> json(){
HashMap<String,Object> map = new HashMap<>();
map.put("Java","Java Value");
map.put("MySQL","MySQL Value");
map.put("Linux","Linux Value");
map.put("Redis","Redis Value");
return map;
}
请求转发和请求重定向
请求转发和请求重定向都是用来返回一个跳转页面的,两种方式:forward——请求转发、redirect——请求重定向。
现在要求在Controller层里面写一个TestContoller类,使用这个类来观察请求转发和请求重定向的区别
请求转发
@Controller
@RequestMapping("/art")
public class TestContoller {
/*
* 请求转发
*
*/
@RequestMapping("/add")
public String forward(){
System.out.println();
System.out.println("进行了请求转发");
System.out.println();
//伪代码:假设现在没有登录
return "forward:/login.html";
}
}
请求重定向
@Controller
@RequestMapping("/art")
public class TestContoller {
/*
* 请求重定向
*/
@RequestMapping("add2")
public String redirect(){
System.out.println();
System.out.println("进行了请求转发");
System.out.println();
//伪代码:假设现在没有登录
return "redirect:/login.html";
}
}
通过上面的比较可以发现,总结到请求转发和请求重定向的区别如下:
1.请求转发URL地址不变,因为是服务器进行转发和响应;请求重定向URL地址会发生改变,因为服务器端直接将请求重定向到具体的地址上。
2.使用请求转发有可能请求的外部资源会丢失,访问不到;而请求重定向是直接重定向到URL地址,所以请求重定向和直接目标地址的效果是一摸一样的,所以不会存在外部资源丢失的情况。