Spring MVC 简介
- 什么是Spring MVC
- 了解 MVC
- MVC 和Spring MVC的联系
- 如何创建一个Spring Web项目
- 在Spring Web 项目中,如何连接Http请求
- @Controller注解可以用其他类注解代替吗
- 连接其他类型的请求
- 如何获取请求中的数据
- 获取单个请求参数
- 获取多个请求参数
- 获取对象
- 获取表单参数
- 获取JSON对象
- 获取请求中的文件
- 获取请求中Cookie/Session/header
- 获取请求中Cookie
- 获取请求中Session
- 获取请求中Header
- 获取请求数据的特殊情况
- 后端参数重名
- 获取URL中参数
- 返回数据给前端
- 返回静态⻚⾯
- 返回数据
- 请求转发或请求重定向
- 请求转发vs请求重定向
什么是Spring MVC
Spring MVC 全名是 Spring Web MVC,简称 Spring MVC或者 Spring Web.
Spring MVC 是基于Servlet API的web框架,从一开始Spring框架是包含Spring MVC部分,也就是说Spring MVC是Spring 框架的一部分。
了解 MVC
MVC的英文全称是 Model View Controller,它是软件工程的软件架构模式,它把软件系统分为视图,模型,控制器三个部分。
model :程序逻辑部分
controller:前后端交互部分
view: 页面显示部分
MVC 和Spring MVC的联系
MVC只是软件架构模式,是一种思想,而Spring MVC这是MVC的一种具体的实现。
如何创建一个Spring Web项目
创建Spring Web项目的创建方式有很多种,这里介绍通过Spring Boot来创建一个Spring Web项目
通过Spring Boot来创建Spring Web 项目是一个非常简单的是,我们只需要在添加依赖的步骤添加一个Spring Web依赖就可以了
在Spring Web 项目中,如何连接Http请求
我们在学习Serlvet API的时候,是通过@WebServlet()来配置路由的。
而我们在使用Spring MVC的时候,则是通过@RequestMapping()这个注解来配置路由。
@RequestMapping()注解的作用:只有一个,就是用来配置路由,用来连接http请求
@RequestMapping()注解可以放在类前,也可以放在方法前。放在类前表示一级路径,放在方法前表示二级路径
有了@RequestMapping()注解还不够,还要加一个类注解@Controller,让Spring容器能够加载该类。
@RequestMapping("/user")
@Controller
public class UserController {
@RequestMapping("/m")
public String user() {
return "ok";
}
}
这样写还是有一些问题,这样写默认返回的并不是ok这个信息,而是一个视图,根我们想的不太一样。如何返回信息能?
使用@ResponseBody可以解决这个问题
@RequestMapping("/user")
@Controller
@ResponseBody
public class UserController {
@RequestMapping("/m")
public String user() {
return "ok";
}
}
@ResponseBody注解的用法:
@ResponseBody注解可以作用在类前,也可以作用在方法前
@ResponseBody注解作用在类前表示该类里面设置的路由返回的都是数据不是视图
@ResponseBody注解作用在方法前表示只有该路由返回的是数据不是视图
如果,我们觉得写@Controller,@ResponseBody这两个注解太麻烦了,这里还有一个组合注解包含了这两个部分:@RestController注解
@RestController
public class UserController {
@PostMapping("/user")
public String user() {
return "ok";
}
}
@Controller注解可以用其他类注解代替吗
不能,虽然五大类注解都可把对象交给Spring容器进行管理,但是,五大类注解不仅仅只有这个功能,他们分工明确,@Controller是用来进行前后端交互的,其他类注解是无法替代。
连接其他类型的请求
@RequestMapping()注解比较强大,默认情况下,get和post类型的请求都可以连接
【连接get请求】
//方法一
@RequestMapping("/user")
//方法二
@RequestMapping(value = "/user",method = RequestMethod.GET)
//方法三
@GetMapping("/user")
【连接post请求】
//方法一
@RequestMapping("/user")
//方法二
@RequestMapping(value = "/user",method = RequestMethod.POST)
//方法三
@PostMapping("/user")
如何获取请求中的数据
获取单个请求参数
【方法一】通过Servlet的request对象来获取
特殊说明:在Spring MVC中默认内置隐藏了两个参数,一个是request(HttpServletRequest),一个是response(HttpServletResponse) 对象,所以如果想要使用这两个对象,只需要在方法中申明即可。
@GetMapping("/user1")
public String user1(HttpServletRequest request, HttpServletResponse response) {
String name = request.getParameter("name");
return "name:"+name;
}
【方法二】在 Spring MVC 中可以直接⽤⽅法中的参数来实现传参
@GetMapping("/user2")
public String user1(String name) {
return "name:"+name;
}
注意:参数变量的名称要和请求中要获取的值的键名相同。
获取多个请求参数
【方法一】通过Servlet的request对象来获取
【方法二】在 Spring MVC 中可以直接⽤⽅法中的参数来实现传参
注意:参数变量的名称要和请求中要获取的值的键名相同,参数的顺序没必要一一对应。
@GetMapping("/user3")
public String user3(String name,Integer age) {
return "name:"+name+" | age:"+age;
}
获取对象
如果,请求所传递的值太多了,使用参数来接收就有些不太合适了,这时候可以使用对象来接收
注意:
对象里的属性的名称要和请求中要获取的值的键名相同,否则无法赋值,必须要有相对应的setter方法,否则名字相同但是也无法赋值
public class User {
private String name;
private Integer age;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
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;
}
}
@GetMapping("/user4")
public String user4(User user){
return user.toString();
}
获取表单参数
参数的请求类型:
- 通过url方式发送http请求
- 通过Ajax方式发送http请求
- 通过form表单方式发送http请求
获取表单的参数可以通过上面三种方法:获取单个参数,获取多个参数,获取对象 来获取
获取JSON对象
获取json对象和上面获取对象 是不一样的。上面的介绍获取对象的方法只能获取普通的对象,并不能获取json格式的对象。要获取json格式的对象,就要在参数前面加一个**@RequestBody**
@PostMapping("/user5")
public String user5(@RequestBody User user){
return user.toString();
}
获取请求中的文件
使用@RequestPart注解来指定接收文件的名称,参数的类型是MultipartFile
@PostMapping("/ref")
public String ref(String name, @RequestPart("milfile")MultipartFile file) throws IOException {
//保存文件到本地电脑,使用transferTo()方法,实参是File类型
File file1 = new File("D:\\JAVAcode\\Java Web 练习\\spring mvc - demo03\\ww.png");
file.transferTo(file1);
System.out.println(name);
return "文件保存成功";
}
获取请求中Cookie/Session/header
获取请求中Cookie
【方法一】通过Servlet的request对象来获取(最原始的方法)
@GetMapping("/user1")
public String user1(HttpServletRequest request, HttpServletResponse response) {
//获取全名cookie
Cookie[] cookies = request.getCookies();
return "key:"+cookies[0].getName()+"val:"+cookies[0].getValue();
}
这种方法比较暴力,将cookie全部获取
【方法二】使用SpringMVC提供的方法
使用@CookieValue注解获取cookie的值,一次只能获取一个cookie的值,通过设置cookie的key值来获取cookie的值,@CookieValue注解是加在方法参数前面的。
@GetMapping("/user6")
public String user6(@CookieValue("name") String val) {
return "val:"+val;
}
获取请求中Session
【方法一】通过Servlet的request对象来获取(最原始的方法)
@GetMapping("/user7")
public String user7(HttpServletRequest request, HttpServletResponse response) {
//参数true,如果没有HttpSession对象,会创建一个HttpSession对象
HttpSession aTrue = request.getSession(true);
return "ok";
}
【方法二】使用SpringMVC提供的方法
使用@SessionAttribute注解,设置里面两个参数value和required 。
value是设置要查找值的键名,而required 则是设置是否必须要有值,默认是true表示一定要有值,否则会报错,
false表示不一定要有值,没有则给变量赋一个null。
Session对象里面是通过键值对的方式来保存数据
@GetMapping("/user8")
public String user8(@SessionAttribute(value = "age",required = false) Integer age) {
return "age:"+age;
}
获取请求中Header
我们学习过Http协议,了解http协议的请求,我们知道请求头是以键值对的方式存在的,键和值之间使用冒号(:)隔开
【方法一】使用request对象来获取Header(最原始的方法)
@Controller
@ResponseBody
public class TeacherController {
@RequestMapping("/get_header")
public String getHeader(HttpServletRequest request) {
String header = request.getHeader("User-Agent");
return "User-Agent:"+header;
}
}
【方法二】使用SpringMVC提供的方法
使用@RequestHeader注解来设置我们需要获取请求header的值的键名。
@Controller
@ResponseBody
public class TeacherController {
@RequestMapping("/get_header1")
public String getHeader1(@RequestHeader("User-Agent") String header) {
return "User-Agent:"+header;
}
}
@RequestHeader注解不仅仅可以设置要获取请求的header,还可以设置required参数
required参数的值可以为true和false
值为true表示如果请求头没有相应的header则会报错
值为false表示如果请求头没有相应的值,则不会报错,会给方法中相对应的参数赋空值
所以,@RequestHeader注解中的required参数的设置就是确保否必须要有值。
获取请求数据的特殊情况
后端参数重名
我们在获取单个参数和获取多个参数时,我们规定请求参数的名称和后端方法参数名称是要相同的,否则后端获取不到请求内容。
但是,如果在实际情况,前后端的参数名称不一致,如果获取请求相对应的参数值呢?
在后端方法参数前使用@RequestParam注解指定获取请求的哪个参数
@RequestParam注解可以设置两个参数
value参数:设置获取请求的哪个参数
required参数:规定前端是否一定要传这个参数,默认是true。true表示必须传,false表示不是必须传,如果没有给后端相对应的参数赋空值
@RequestMapping("/date")
public String date(@RequestParam(value = "username",required = false) String name) {
return "name:"+name;
}
获取URL中参数
我们一般前端传参是通过Query Params方式来进行,有种特殊的url传参是将参数之间写到路径中。这样我们该如何获取参数呢?
@RequestMapping("/date1/{name}/{age}")
public String date1(@PathVariable String name,@PathVariable String age) {
return "name:"+name+" age:"+age;
}
我们可以看到,这里配置的路由都跟我们之前有一些不一样,要获取的部分用花括号({})括起来,表示这个是动态的,可变,是需要被后端获取的。
后端则是要在相对应的方法的参数前面加上@PathVariable注解。
@PathVariable注解可以设value参数和required参数,效果和之前注解是一样的,这里就不写了
强调一下,在使用@PathVariable注解但是不设置参数值,那么方法的参数名要与设置路由使用花括号的名字相同,否则获取不到相对应的值。
返回数据给前端
返回静态⻚⾯
要想返回静态页面,首先在resources.static包下要有静态页面,并且与前端交互的xxxController的类不能有@ResponseBody注解。
@Controller
public class PeoController {
@RequestMapping("/pe")
public String pe() {
return "/index.html";
}
}
返回数据
使用@ResponseBody注解就能解决这个问题,返回数据的类型项目会自己识别,不需要程序员自己设置。
@ResponseBody注解写在类前表示该类每一个方法配置的路由都是返回数据的。
@ResponseBody注解写在方法前表示该方法配置的路由返回的是数据。
@RequestMapping("/p_user")
@ResponseBody
public User getUser(@RequestBody User user) {
return user;
}
当返回的类型是对象和HashMap对象的时候,返回的类型是json类型
请求转发或请求重定向
在返回视图的时候,我们不仅仅可以返回视图,还可以实现跳转,跳转的方式有两种:
- forward:请求转发
- redirect:请求重定向
请求转发vs请求重定向
- 请求重定向将请求重新定位到资源,而请求转发则是在服务器内部进行转发
- 请求重定向地址栏发生变化,请求转发地址栏没有发生变化‘
- 请求重定向与直接访问新地址效果一样,不存在原来的外部资源不可访问;请求转发服务器端转发有可能造成外部资源不能访问的情况
@Controller
public class PeoController {
/**
* 请求转发
* @return
*/
@RequestMapping("/fo")
public String fo() {
return "forward:/index.html";
}
/**
* 请求重定向
* @return
*/
@RequestMapping("/re")
public String re() {
return "redirect:/index.html";
}
}
注意:千万不能加@ResponseBody注解,否则会被解析成返回数据,则不能实现页面的跳转