Spring MVC

hi,今天为大家带来Spring MVC相关知识

文章目录

🌻1.什么是Spring MVC?

Spring MVC是一个基于Servlet API构建的Web框架,是一种基于MVC(模型-视图-控制器)模式的框架,用于构建Web应用程序。它是Spring框架的一部分,提供了一个容易扩展和灵活的方式来开发Web应用程序。

Spring MVC特性:

1.Spring MVC是一个Web框架

2.Spring MVC是基于Servlet api构建的

🍬1.1什么是MVC?

MVC,全称Model Version Controller,模型视图控制器,是一种软件架构模式

MVC执行流程

图片版本

文字版本

1.用户发出请求先到Controller

2.Comtroller把请求转发给Model层

3.Model处理请求并将数据返回给Controller

4.Controller继续转发数据给View

5.View将数据可视化返回给用户

Controller(控制器)是应⽤程序中处理⽤户交互的部分。通常控制器负责从视图读取数据,控制⽤户输⼊,并向模型发送数据.

模型(Model):负责数据管理和业务逻辑,通常包括数据库操作、数据验证、数据转换等。

视图(View):负责呈现数据给用户,通常包括用户界面、报表、图表等。

🍬1.2MVC和Spring MVC的关系

MVC是一种思想,Spring MVC是MVC思想的具体实现

🌻2.Spring MVC的意义

⼤部分的 Java 项⽬都是基于 Spring(或 Spring Boot)的,Spring 的核⼼就是 SpringMVC,也就是说 Spring MVC 是 Spring 框架的核⼼模块,所以Spring MVC很重要

🍬2.1Spring MVC和Spring Boot区别

Spring MVC是Spring Framework的一部分,它是一个基于Servlet的Web框架,用于开发Web应用程序。它提供了一种按照模型-视图-控制器(MVC)模式来组织代码的方式,使得Web应用程序的开发更加灵活和可维护。在开发过程中,需要手动配置各种依赖项和设置。

Spring Boot是一个基于Spring Framework的快速开发框架,它的目的是简化Spring应用程序的开发、部署和运行。它提供了自动配置、约定优于配置(Convention over Configuration)和快速启动等功能,使得开发者无需手动配置和管理依赖项,只需添加所需的依赖项即可快速启动应用程序。

Spring Boot在某些方面比Spring MVC更加方便和简化,尤其是在快速开发和部署方面。但是,Spring MVC的灵活性更高,它可以更好地满足定制化需求

🌻3.Spring MVC的三大要点

连接功能:用户和服务器程序连接

获取参数:用户访问带的参数后端可以获取

返回数据:服务器处理好请求,返回给用户

🍬3.1Spring MVC创建和连接

🧊3.1.1 创建Spring MVC项目

Spring MVC项目就是基于Spring Boot项目多了一个Spring Web依赖

🧊3.1.2实现客户端和程序之间的连接

🍧3.1.2.1@RequestMapping,@PostMapping,@GetMapping

@RequestMapping既可以修饰类又可以修饰方法,一般来说方法是一定要加这个注解的,类可加可不加

java 复制代码
package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-08-04
 * Time: 17:27
 */
@RestController
@RequestMapping("/test")
public class TestController {
    @RequestMapping("/hi")
    public String sayHi(){
        return "hi ,spring mvc";
    }

}

运行结果

那么方法可以写多个路径吗?可以的


默认情况下@RequestMapping既支持get请求又支持post请求

我们来验证一下,这个时候就得请出我们的老朋友了postman

由此可见上述结论正确

那么如果想要一个post请求呢?

三种方法

🥝1.采用@RequestMapping("/xxx)

🥝2.@RequestMapping(value = "/xxx",method = RequestMethod.POST)

java 复制代码
 @RequestMapping(value = "/hii",method = RequestMethod.POST)
    public String sayhi2(){
        return "zezeze";
    }

method规定了请求的方法为post

这里的post请求是不支持get请求的,因为默认浏览器的URL都被封装为get请求

🥝3.@PostMapping("/xxx")

java 复制代码
@PostMapping("/h")
    public String sayhi(){
        return "wyb";
    }

如果想要一个get请求呢?

  1. @RequestMapping("/xxx")

2.@RequestMapping(value="/xxx",method=RequestMethod.GET)_

java 复制代码
 @RequestMapping(value = "/hiii",method = RequestMethod.GET)
    public String sayhi3(){
        return "zezeze";
    }

3.@GetMapping("/xxx")

java 复制代码
@GetMapping("/hello")
    public String saihi4(){
        return "who";
    }

🍬3.2获取参数

🧊3.2.1获取单个参数

比如要获取姓名

java 复制代码
package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-08-04
 * Time: 20:02
 */
@RestController
@RequestMapping("/u")
public class TestController2 {
    @RequestMapping("/h")
    public String getName(HttpServletRequest request){
        return "Name"+request.getParameter("name" );
    }
}


因为Spring MVC是基于servlet实现的,所以获取参数可以使用servlet的那一套方法获取,但是有了Spring MVC,就有了更简单的写法

java 复制代码
package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-08-04
 * Time: 20:02
 */
@RestController
@RequestMapping("/u")
public class TestController2 {
    @RequestMapping("/h")
    public String getName(HttpServletRequest request){
        return "Name"+request.getParameter("name" );
    }
    @RequestMapping("/b")
    public String getName2(String name){
        return "Name"+name;
    }
}

也是没有问题的

🧊3.2.2 获取多个参数

比如要获取姓名和年龄

java 复制代码
@RequestMapping("/d")
    public String get(String name,Integer age){
        return "Name"+name+"Age"+age;

    }

🧊3.2.3 获取对象

java 复制代码
package com.example.demo.controller;

import com.example.demo.model.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-08-04
 * Time: 20:21
 */
@RestController
@RequestMapping
public class UserController {

    @RequestMapping("/getUser")
    public User getUser(User user){
        
        return user;
    }
}

啥都不传递的时候会发现都是该类型的默认值

现在进行传参

我们在浏览器拿到结果的时候发现一个问题

浏览器显示的是json对象,我们在后端没有手动的转换对象

在servlet阶段,我们需要使用jQuery的objectMappper对象的方法将Java对象转换为json字符串,然后返回给前端,现在有了框架,框架为我们自动转换为json格式返回给前端~~

如果返回的是HTML格式,就会直接返回成HTML,不会再自动转换

举个例子

java 复制代码
 @RequestMapping("/html")
    public String html(){
        return "<h1>hello<h1>";
    }

抓包看看

类型就是text/plain,也就是text/html

🧊3.2.4表单传递参数

采用postman 演示

传递成功,后端返回的依然是json格式

🧊3.2.5 重命名后端参数

当前端传递过来的时候名字和后端程序员想起的名字不一样,这个时候可以采用重命名的方式,使用注解@RequestParam

这里意味着前端传递过来的参数是n,后端不想用n,起名用了name,但是在浏览器的URL上必须用n,不然会报错


有一个问题,为什么其他的不传参数时不会报错,这里就会报错?

是因为这个@RequestParam的源码

required这里,默认必须有参数,我们改一下

当不传参数的时候,不会报错

🧊3.2.6@RequestBody接收JSON对象

对于前端来说,对象和json对象是两个不同的概念,对象对于前端来说就是一些属性 ,最后后端返回给前端的时候就是json,当前端传递的是json时,返回的时候拿不到结果了,我们拿postman验证一下

点击发送根本拿不到了,打开fiddler抓包工具看看

那么后端要咋样获取前端的json对象呢?

java 复制代码
   @RequestMapping("/transjson")

    public User transjson(@RequestBody User user){
        return user;
    }
}

采用@RequestBody 这个注解

拿到了

再抓包看看

没有问题,我们也可以发现前端传递json对象时返回的格式也是json对象

🧊3.2.7获取URL参数

不采用querystring的方法获取属性,而是跟在路由之后,/后跟,采用@PathVariable注解,来举个例子

java 复制代码
 /**
     * 以获取文章id为例
     */
    @RequestMapping("/article/{id}")
    public Integer article(@PathVariable("id") Integer aid){
        return aid;

    }

但是注意,当自定义的名字和注解或者和路由注解的名字一样的时候,就可以省略@PathVariable后面的括号

java 复制代码
@RequestMapping("/article/{aid}")
    public Integer article2(@PathVariable Integer aid){
        return aid;

    }

看到返回的依然还是json对象

当要获取URL的多个参数时,这样写

java 复制代码
    @RequestMapping("/article/{aid}/{name}")
    public String  article2(@PathVariable Integer aid,@PathVariable String name){
        return "id"+aid+"name"+name;

    }

🧊3.2.8上传文件

采用@RequestPart注解,Multipartfile接收

采用transferto方法保存到路径

java 复制代码
package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-08-05
 * Time: 8:43
 */
@RestController
@RequestMapping("/hhh")
public class UserController {
    @RequestMapping("/upfile")
    public String upload(@RequestPart("myfile")MultipartFile file) throws IOException {
           String path="D:\\image\\img.png";
           //保存文件
            file.transferTo(new File(path));
            return path;
    }

}

上传文件的时候只能用post请求,因为get请求的文件流比较小,post支持的文件流比较大,上传文件的时候文件流是很大的

文件上传成功

但是我们保存的图片名字被限制了.根据上述代码假如有100个人上传图片,因为 名字一样,前99个被覆盖,还有可能用户上传的是一个视屏,后来存入格式命名为.png,这也是不对的,所以需要源文件的后缀名

java 复制代码
    public String upload(@RequestPart("myfile")MultipartFile file) throws IOException {
         //生成唯一id,采用UUID
        String name= UUID.randomUUID().toString().replace("-","");
        //得到源文件后缀名
        name+=(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")));
        String path="D:\\image\\"+name;
           //保存文件
            file.transferTo(new File(path));
            return path;
    }


每一次地址都不一样,图片命名也不一样,不会被覆盖

UUID是全球唯一id,等于MAC地址+随机种子+加密算法,是一个十六进制三十二位的数

🧊3.2.9获取Cookie

使用注解@CookieValue

java 复制代码
 @RequestMapping("/getcookie")
    public String getcookie(@CookieValue("java") String cookie){
                return cookie;
    }

什么都没有获取到就会报错,

因为它的源码也是默认有参数,我们设定一下,就不会报错了

现在来设定一下cookie

🧊3.2.10获取Session

session来自于服务器,我们要先存session,才能取seesion

java 复制代码
//存session
 public static  String Sessionkey="session";
    @RequestMapping("/setsession")
    public String setsession(HttpServletRequest request){
        HttpSession session=request.getSession();
        if(session!=null){
            session.setAttribute("Sessionkey","王麻子");
            return "success";
        }else{
            return "fail";
        }

    }

获取session,采用注解@SessionAttribute

java 复制代码
@RequestMapping("/getsession")
    public String getSessionkey(@SessionAttribute(value="Sessionkey",required = false)String session){
                return session;
    }

结果

3.2.11 获取Header

采用@RequestHeader注解

java 复制代码
    @RequestMapping("/header")
    public String getheader(@RequestHeader("User-Agent") String userAgent){
        return "userAgent"+userAgent;
    }

🍬3.3返回数据

🧊3.1返回静态页面

当默认情况下只加@Controller注解的时候,返回的是一个静态页面

java 复制代码
@Controller
public class TestController {
    @RequestMapping("/hi")
    public String hi(){
        return "hello";
    }
}


这个代码默认情况下返回的是hello.html页面,在resources下没有找到这个页面,所以报错

在static下创建一个hello.html

java 复制代码
@Controller
public class TestController {
    @RequestMapping("/hi")
    public String hi(){
        return "hello.html";
    }
}

返回的是静态页面的结果,如果想要打印hello.html这个语句,加注解@ResponseBody

🧊3.2返回json对象

java 复制代码
 @RequestMapping("/json")
    @ResponseBody
    public HashMap<String, String> method() {
        HashMap<String, String> map = new HashMap<>();
        map.put("Java", "Java Value");
        map.put("Oracle", "MySQL Value");
        map.put("Spring", "Spring Value");
        return map;
    }

🧊3.3请求转发VS请求重定向

举个例子:李华想吃辣条,告诉爸爸想吃辣条.爸爸有两种做法,第一种:可以选择帮李华去买

第二种;可以选择把钱给李华,让李华自己去买

第一种就叫做请求转发,也就是服务器帮着干

第二种就是请求重定向,也就是客户端自己跳转到另一个网址自己干

1.请求重定向(redirect):将请求重新定位到资源;

2.请求转发(forward)服务器端转发

3.请求重定向地址发⽣变化,请求转发地址不发⽣变化

4.请求重定向与直接访问新地址效果一样,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问(对应上述的例子,李华自己买辣条知道自己口味,他爹买可能买不到李华喜欢的)

区别:

🐷处理方式不同:

重定向是通过将请求发送到另一个URL来完成的,客户端将收到一个新的响应,浏览器将向新的URL发出请求并在地址栏中显示新的URL。重定向是一种客户端行为,它是通过HTTP响应码实现的,例如302、307或303。

请求转发是在服务器上进行的,当服务器接收到请求并处理它时,它直接将请求发送到另一个资源(Servlet或JSP),该资源将处理并发送响应。请求转发对客户端是透明的,客户端只知道最初请求的URL,不知道服务器之间的转发操作。

🐷对浏览器地址栏的影响不同:

在重定向过程中,浏览器将会看到URL的变化,因为浏览器地址栏中将显示一个新的URL。这意味着即使用户保存旧URL,也不能保证它们仍然有效,因为它们将被重定向到新的URL。

在请求转发过程中,浏览器地址栏中显示的URL不会发生变化,因为客户端不知道服务器之间的转发操作。

🐷对数据传递的影响不同:

在重定向过程中,数据必须通过URL传递,因为浏览器会向新的URL发送一个新的请求。因此,如果需要传递大量的数据,使用重定向不是一个好的选择。

在请求转发过程中,数据可以在服务器之间共享,因为请求仍然是相同的请求,并且在服务器之间传递。因此,如果需要传递大量的数据,使用请求转发可能更加有效。

今天的讲解就到这里.下期见,拜拜~

相关推荐
陈大爷(有低保)21 分钟前
UDP Socket聊天室(Java)
java·网络协议·udp
kinlon.liu34 分钟前
零信任安全架构--持续验证
java·安全·安全架构·mfa·持续验证
哈喽,树先生41 分钟前
1.Seata 1.5.2 seata-server搭建
spring·springcloud
王哲晓1 小时前
Linux通过yum安装Docker
java·linux·docker
java6666688881 小时前
如何在Java中实现高效的对象映射:Dozer与MapStruct的比较与优化
java·开发语言
Violet永存1 小时前
源码分析:LinkedList
java·开发语言
执键行天涯1 小时前
【经验帖】JAVA中同方法,两次调用Mybatis,一次更新,一次查询,同一事务,第一次修改对第二次的可见性如何
java·数据库·mybatis
Jarlen1 小时前
将本地离线Jar包上传到Maven远程私库上,供项目编译使用
java·maven·jar
蓑 羽1 小时前
力扣438 找到字符串中所有字母异位词 Java版本
java·算法·leetcode
Reese_Cool1 小时前
【C语言二级考试】循环结构设计
android·java·c语言·开发语言