Spring MVC介绍

Source

什么是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();

    }

获取表单参数

参数的请求类型:

  1. 通过url方式发送http请求
  2. 通过Ajax方式发送http请求
  3. 通过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类型

请求转发或请求重定向

在返回视图的时候,我们不仅仅可以返回视图,还可以实现跳转,跳转的方式有两种:

  1. forward:请求转发
  2. redirect:请求重定向

请求转发vs请求重定向

  1. 请求重定向将请求重新定位到资源,而请求转发则是在服务器内部进行转发
  2. 请求重定向地址栏发生变化,请求转发地址栏没有发生变化‘
  3. 请求重定向与直接访问新地址效果一样,不存在原来的外部资源不可访问;请求转发服务器端转发有可能造成外部资源不能访问的情况
@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注解,否则会被解析成返回数据,则不能实现页面的跳转