【Java EE进阶 --- SpringBoot】Spring Web MVC(Spring MVC)

乐观学习,乐观生活,才能不断前进啊!!!

我的主页:optimistic_chen

我的专栏:c语言Java,
Java EE初阶Java数据结构

欢迎大家访问~
创作不易,大佬们点赞鼓励下吧~

什么是Sping Web MVC

MVC

MVC是Model View Controller的缩写,它是软件⼯程中的⼀种软件架构设计模式,它把软件系统分为模型、视图和控制器三个基本部分

在这里插入图片描述

Spring MVC

Spring Web MVC是基于Servlet API构建的原始 Web 框架从⼀开始就包含在Spring框架中。它的正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-web mvc),但它通常被称为"Spring MVC"。

MVC是⼀种架构设计模式,也是⼀种思想, ⽽SpringMVC是对MVC思想的具体实现.除此之外,Spring MVC还是⼀个Web框架.也就是说:Spring MVC是⼀个实现了MVC模式的Web框架.

那么上篇博客写的SpringBoot和这个Spring Web MVC之间由什么关系吗?
我们知道SpringBoot是一个便捷的开发框架,在创建SpringBoot项目时,选择的Spring Web就是Spring MVC。
在这里插入图片描述
总结: Spring Boot 只是实现SpringMVC的其中⼀种⽅式⽽已。Spring Boot 可以添加很多依赖,借助这些依赖实现不同的功能.SpringBoot通过添加Spring Web MVC框架,来实现web功能

在这里插入图片描述

Servlet

既然是Web框架,那么只要在浏览器中输入url后,Spring MVC项目就能感知到请求,并响应。所以Web就可以调用Servlet来与浏览器交互。
在这里插入图片描述
上图是Servlet的官方解释,我们通俗理解 Servlet 是客户端和服务端交互的工具,是⼀种实现动态⻚⾯的技术。准确来讲Servlet是一套Java Web开发的规范,实现这个规范的产品包括:Tomcat、Weblogic、Jetty、Jboss、WebSphere等,抽象认为是"Servlet 容器"。

使用Spring MVC

目的就是使用如何通过浏览器和⽤⼾程序进⾏交互。

  1. 建⽴连接:将⽤⼾(浏览器)和Java程序连接起来,也就是访问⼀个地址能够调⽤到我们的Spring 程序。
  2. 请求:⽤⼾请求的时候会带⼀些参数,在程序中要想办法获取到参数,所以请求这块主要是获取参数的功能.
  3. 响应:执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤⼾,也就是响应

因为Spring Boot 只是实现Spring MVC的其中⼀种⽅式,所以目前Spring MVC项⽬创建和SpringBoot创建项⽬相同,在创建的时候选择SpringWeb就相当于创建了Spring MVC的项⽬.
在这里插入图片描述

建立连接

在Spring MVC中使用 @RequestMapping 注解来实现URL路由映射,连接浏览器和程序

路由映射:所谓的路由映射指的是,当⽤户访问⼀个 url 时,将⽤户的请求对应到程序中某个类的某个⽅法的过程就叫路由映射

import org.springframework.web.bind.annotation.*;

@RequestMapping("/hello")//类路径
@RestController
public class HelloController {
    //既支持get又支持post
    @RequestMapping("/hello")//方法路径
    public String  hello(){
        return "hello spring boot";
    }

@RequestMapping 是Spring Web MVC最常用的注解之一,用来注册接口的路由映射的。
@RestController Spring会对所有的类进⾏扫描,如果类加了注解@RestController,Spring才会去看这个类⾥⾯的⽅法有没有加@RequestMapping 。相当于程序的入口。

运行程序后,通过浏览器访问就可以看到数据了。
在这里插入图片描述
在之前网络知识学习中,fiddler抓包抓到的数据,报头有GET也有POST,表示了此次请求的类型是GET请求还是POST请求。
首先,@RequestMapping 既⽀持Get请求,⼜⽀持Post请求,那么我们能否指定GET或者POST类型呢?

import org.springframework.web.bind.annotation.*;

@RequestMapping("/hello")
@RestController
public class HelloController {
    //既支持get又支持post
    @RequestMapping("/hello")
    public String  hello(){
        return "hello spring boot";
    }

    @RequestMapping(value="/hello2",method = RequestMethod.GET)
    public String hello2(){
        return "hello spring boot2";
    }

    @RequestMapping(value="/hello3",method = RequestMethod.POST)
    public String hello3(){
        return "hello spring boot3";
    }

    @GetMapping("/hello4")
    public String hello4(){
        return "hello spring boot4";
    }

    @PostMapping("/hello5")
    public String hello5(){
        return "hello spring boot5";
    }
}

一般直接使用@GetMapping 或者 @PostMapping注解即可。
那么我们测试后端方法时,是不是只能通过浏览器去测试呢?又如何测试Post呢?
我使用专业的接口测试工具—Postman,具体的使用方法就需要大家去自己接触了,我这里不阐述了。

请求

访问不同的路径,就是发送不同的请求.在发送请求时,可能会带⼀些参数,所以学习Spring的请求,主要是学习如何传递参数到后端以及后端如何接收.

传递单个参数

import org.springframework.web.bind.annotation.*;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r1")
    public String r1(String keyword){
        return "接受参数"+keyword;
    }
}

在这里插入图片描述
如果参数不一致,是获取不到参数的。

传递多个参数

和接收单个参数⼀样,直接使⽤⽅法的参数接收即可.使⽤多个形参

import org.springframework.web.bind.annotation.*;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r2")
    public String r1(String userName,String password){
        return "接受参数:"+userName+",password:"+password;
    }
}

在这里插入图片描述
当有多个参数时,前后端进⾏参数匹配时,是以参数的名称进⾏匹配的,因此参数的位置是不影响后端获取参数的结果

传递对象

如果方法需要很多参数,并且后续每增加一个参数都需要修改方法声明,我们可以把这些参数封装成一个对象。

//UserInfo对象
public class UserInfo {
    private String name;

    private Integer gender;

    private Integer age;
    public UserInfo(){

    }

    public UserInfo(String name, Integer gender, Integer age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "name='" + name + '\'' +
                ", gender=" + gender +
                ", age=" + age +
                '}';
    }
}
import org.springframework.web.bind.annotation.*;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/m1")
    public Object method(UserInfo userInfo){
        return userInfo.toString();
    }
}

在这里插入图片描述

后端参数重命名(绑定)

特殊情况下,前端传递的参数和后端接收的参数不一致,这种情况可以使用@RequestParam 注解来重命名前后端的参数。

import org.springframework.web.bind.annotation.*;

@RequestMapping("/request")
@RestController
public class RequestController {
@RequestMapping("/r4")
    public String r4(@RequestParam("q")String keyword){
        return "接收参数:keyword"+keyword;
    }
}

在这里插入图片描述

  1. 使⽤@RequestParam 进⾏参数重命名时, 请求参数只能和@RequestParam 声明的名称一致,才能进⾏参数绑定和赋值.
  2. 使⽤@RequestParam 进⾏参数重命名时,参数就变成了必传参数

去查看@RequestParam 的实现可以发现required的默认值是true,表示该注解修饰的参数默认为必传参数,那么我们就可以通过设置@RequestParam 中required=false来避免必传参数。
在这里插入图片描述

传递数组

import org.springframework.web.bind.annotation.*;

@RequestMapping("/request")
@RestController
public class RequestController {
@RequestMapping("/r5")
    public String r5(String[] arr){
        return "接收参数:"+ Arrays.toString(arr);
    }
}

在这里插入图片描述

传递集合

import org.springframework.web.bind.annotation.*;

@RequestMapping("/request")
@RestController
public class RequestController {
@RequestMapping("/r6")
    public String r6(@RequestParam List<Integer> list){//参数绑定
        return "接收参数:list="+ list;
    }
}

在这里插入图片描述

传递JSON数据

JSON:JavaScript Object Notation 【JavaScript 对象表⽰法】
简单来说:JSON就是⼀种数据格式, 有⾃⼰的格式和语法,使⽤⽂本表⽰⼀个对象或数组的信息,因此JSON本质是字符串. 主要负责在不同的语⾔中数据传递和交换

JSON的语法:
1. 数据在键值对(Key/Value)中
2. 数据由逗号分隔
3. 对象用 {} 表示
4. 数组用 [] 表示
5. 值可以为对象,也可以为数组,数组中可以包含多个对象

优点:

  1. 语法简单,易于理解和编写,可以快速的进行数据交换
  2. 跨平台支持, JSON可以被多种编程语⾔解析和⽣成可以在不同的平台和语⾔之间进⾏数据交换和
    传输
  3. 轻量级:相较于XML格式,JSON数据格式更加轻量级,传输数据时占⽤带宽较⼩,可以提⾼数据传输速度
  4. 易于扩展: JSON的数据结构灵活,⽀持嵌套对象和数组等复杂的数据结构,便于扩展和使⽤
  5. 安全性:JSON数据格式是⼀种纯⽂本格式,不包含可执⾏代码,不会执⾏恶意代码,因此具有较⾼的安全性

JSON在Web应⽤程序中被⼴泛使⽤,如前后端数据交互、API接⼝数据传输等

JSON字符串与Java对象互转:

public class JSONUtils {
    private static ObjectMapper objectMapper = new ObjectMapper();
    public static void main(String[] args) throws JsonProcessingException {
        Person person = new Person();
        person.setId(5);
        person.setName("zhangsan");
        person.setPassword("123456");
        
        //对象转为JSON字符串
        String jsonStr = objectMapper.writeValueAsString(person);
        System.out.println("JSON字符串为:"+jsonStr);
        
        //JSON字符串转为对象
        Person p = objectMapper.readValue(jsonStr,Person.class);
        System.out.println("转换的对象id:"+p.getId()+",name:"+p.getName()+",password:"+p.getPassword());
    }
}

writeValueAsString: 把对象转为JSON字符串
readValue: 把字符串转为对象

传递JSON对象

import org.springframework.web.bind.annotation.*;

@RequestMapping("/request")
@RestController
public class RequestController {
@RequestMapping("/r7")
    public String r7(@RequestBody UserInfo userInfo){
        return userInfo.toString();
    }
}

@RequestBody 请求正文,这个注解作⽤在请求正⽂的数据绑定,请求参数必须在写在请求正⽂中
在这里插入图片描述
抓包看到,请求参数类型为json
在这里插入图片描述

获取URL中参数@PathVariable

import org.springframework.web.bind.annotation.*;

@RequestMapping("/request")
@RestController
public class RequestController {
@RequestMapping("/article/{articleId}")
    public String r8(@PathVariable("articleId") Integer article){
        return "获取文章ID:"+article;
    }
}

如果⽅法参数名称和需要绑定的URL中的变量名称不⼀致时,需要@PathVariable的属性value赋值
在这里插入图片描述

上传文件@RequestPart

@RequestMapping("/m9")
    public String getfile(@RequestPart("file") MultipartFile file) throws IOException {
        //获取⽂件名称
        String fileName = file.getOriginalFilename();
        
        //⽂件上传到指定路径
        file.transferTo(new File("D:/temp/" + file.getOriginalFilename()));
        return " 接收到⽂件名称: "+fileName;
    }
}

获取Cookie/Session

这里需要我们对网络由一定了解,具体可以去看看我的博客:【Java EE初阶 — 网络原理】应用层—HTTP(HTTPS)协议

Session(会话):计算机领域中,会话是⼀个客⼾与服务器之间的不中断的请求响应。
服务器同⼀时刻收到的请求是很多的.服务器需要清楚的区分每个请求是属于哪个⽤⼾,也就是属于哪个会话,就需要在服务器这边记录每个会话以及与⽤⼾的信息的对应关系.
Session是服务器为了保存⽤⼾信息⽽创建的⼀个特殊的对象
整个过程:

  1. 当用户登录时,服务器在Session中新增一个记录,并把sessionId返回给客户(通过
    HTTP响应中的Set-Cookie字段返回)
  2. 客户端再发送请求时,需要在请求中带上sessionId((通过HTTP请求中的
    Cookie 字段带上)
  3. 服务器收到请求之后,根据请求中的sessionId在Session信息中获取到对应的⽤⼾信息,再进⾏后续操作.找不到则重新创建Session,并把SessionID返回

Cookie和Session的区别:
• Cookie是
客⼾端
保存⽤⼾信息的⼀种机制.Session是服务器端保存⽤⼾信息的⼀种机制.
• Cookie和Session之间主要是通过
SessionId关联起来的,SessionId是Cookie和Session之间的桥梁
• Cookie和Session经常会在⼀起配合使⽤.但是不是必须配合
**

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r10")
    public String r10(HttpServletRequest request, HttpServletResponse response){
        Cookie[] cookies=request.getCookies();
        if(cookies!=null){
            for(Cookie cookie:cookies){
                System.out.println(cookie.getName()+":"+cookie.getValue());
            }
        }
        return "返回cookie成功";
    }
}

Spring MVC是基于ServletAPI构建的原始Web框架,也是在Servlet的基础上实现的,所以HttpServletRequest , HttpServletResponse 两个类是Servlet提供的,是Spring MVC⽅法的内置对象.需要时直接在⽅法中添加声明即可

在这里插入图片描述

Session存储

@RequestMapping("/setSession")
    public String setSession(HttpServletRequest request){
        //从cookie中获取sessionId,根据sessionId获取session对象
        HttpSession session=request.getSession(true);
        //默认存在内存
        session.setAttribute("userName","zhangsan");
        session.setAttribute("age",10);
        return "设置session成功";
    }

Session读取

@RequestMapping("/getSession")
    public String getSession(HttpServletRequest request){
        //从cookie中获取sessionId, 根据sessionId 获取Session对象
        HttpSession session = request.getSession(false);
        //如果用户登录, session 有值, 未登录, session为null
        if (session==null){
            return "用户未登录";
        }else {
            //从session中获取登录用户的信息
            String userName = (String)session.getAttribute("userName");
            return "登录用户为: " + userName;
        }
    }
@RequestMapping("/getSession2")
    public String getSession2(HttpSession session){
        //从session中获取登录用户的信息
        String userName = (String)session.getAttribute("userName");
        return "登录用户为: " + userName;
    }
@RequestMapping("/getSession3")
    public String getSession3(@SessionAttribute("userName") String userName){
            return "登录用户为:"+userName;
    }

三种获取方法皆可。

获取Header

//使用Selvert获取Header
@RequestMapping("/getHeader")
    public String getHeader(HttpServletRequest request){
        String userAgent=request.getHeader("User-Agent");
        return "从header中获取userAgent"+userAgent;
    }
//使用RequestHeader注解获取Header
@RequestMapping("/getHeader2")
    public String getHeader2(@RequestHeader ("user-Agent")String userAgent){
        return "从header中获取userAgent"+userAgent;
    }

在这里插入图片描述

完结

点一个免费的赞并收藏起来~
点点关注,避免找不到我~
我的主页:optimistic_chen我们下期不见不散 ~ ~ ~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Optimistic _ chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值