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发送一个新的请求。因此,如果需要传递大量的数据,使用重定向不是一个好的选择。

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

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

相关推荐
BioRunYiXue1 分钟前
甘油不够了,能用植物油保存菌种吗?
java·linux·运维·服务器·网络·人工智能·eclipse
y = xⁿ4 分钟前
【黑马点评二刷日记】分布式锁和Redisson
java·redis·分布式·缓存
空空kkk6 分钟前
JVM面试知识点总结
java·jvm·面试
zdl68612 分钟前
spring Profile
java·数据库·spring
m0_7066532312 分钟前
数据倾斜全面解析与解决方案探析
java
程序员飞哥16 分钟前
有个同事因为恐惧 AI 要离职了
java·后端·程序员
vanvivo16 分钟前
springboot3.X 无法解析parameter参数问题
java
zhougl99622 分钟前
Maven build配置
java·linux·maven
喵喵蒻葉睦24 分钟前
力扣 hot100 最小覆盖子串 哈希表 滑动窗口 Java 题解
java·算法·leetcode·哈希算法·散列表·滑动窗口
SimonKing28 分钟前
AI时代,一个Skill如何让Java项目结构自动化?
java·后端·程序员