当前位置: 首页 > article >正文

二、学习SpringMVC

既然是Web框架,那么当⽤⼾在浏览器中输⼊了url之后,我们的SpringMVC项⽬就可以感知到⽤⼾ 的请求,并给予响应. 咱们学习SpringMVC,重点也就是学习如何通过浏览器和⽤⼾程序进⾏交互.

主要分以下三个⽅⾯:

1. 建⽴连接:将⽤⼾(浏览器)和Java程序连接起来,也就是访问⼀个地址能够调⽤到我们的 Spring 程序。

2. 请求:⽤⼾请求的时候会带⼀些参数,在程序中要想办法获取到参数,所以请求这块主要是获取参数 的功能.

3. 响应:执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤⼾,也就是响应.

1、建⽴连接

在SpringMVC中使⽤ @RequestMapping 来实现URL路由映射,也就是浏览器连接程序的作⽤ 我们先来看看代码怎么写 创建⼀个UserController类,实现⽤⼾通过浏览器和程序的交互,具体实现代码如下:

package com.pinkboy.springbootdemo;

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

@RestController
public class UserController {
     @RequestMapping("/sayHi")
    public String sayHi() {
        return "hello,Spring MVC";
    }
}

访问:http://127.0.0.1:8080/sayHi

1.1、@RequestMapping 注解介绍

@RequestMapping 是SpringWebMVC应⽤程序中最常被⽤到的注解之⼀,它是⽤来注册接⼝的 路由映射的. 表⽰服务收到请求时,路径为/sayHi的请求就会调⽤sayHi这个⽅法的代码.

路由映射:当⽤⼾访问⼀个URL时,将⽤⼾的请求对应到程序中某个类的某个⽅法的过程就叫路由映射.

如果去掉@RestController会怎么样?

注释@RestController 再次访问http://127.0.0.1:8080/sayHi 如下图

可以看到,程序报了404,找不到该⻚⾯. 这就是 @RestController 起到的作⽤

HTTP状态码是服务器用来告知客户端关于请求处理结果的三位数字代码。不同开头的状态码代表了不同的含义:

  • 200 开头的状态码 表示成功。这类状态码意味着服务器已经成功处理了客户端的请求,并且通常会伴随着一个响应体返回给客户端。

  • 200 ,表示一切正常,请求的资源将随响应一起返回。

  • 201  Created 表示资源已创建,

  • 204 No Content 表示请求成功但没有新的内容要返回。

  • 400 开头的状态码 表示客户端错误。这些状态码表明请求中可能存在错误或不适当的内容,导致服务器无法或不愿意进行处理。例如:

    • 400 Bad Request 表示请求中有语法错误或者格式不对。
    • 401 Unauthorized 表示请求未被授权,通常是因为缺少有效的认证信息。
    • 403 Forbidden 表示服务器理解请求但是拒绝执行它,这可能是由于权限不足。
    • 404 Not Found 表示服务器找不到请求的资源。
  • 500 开头的状态码 表示服务器端错误。这类状态码指出即使请求看起来是正确的,服务器在尝试处理时也遇到了问题。例如:

    • 500 Internal Server Error 表示服务器遇到了意外的情况,阻止了其完成请求的处理。
    • 502 Bad Gateway 表示服务器作为网关或代理,在尝试处理请求时收到了无效响应。
    • 503 Service Unavailable 表示服务器当前无法处理请求,可能是因为过载或是正在进行维护。
    • 504 Gateway Timeout 表示服务器作为网关或代理,未能及时从上游服务器接收到响应。
  • 简单来说 200开头就是成功 400开头就是客户端错误 500开头就是服务器错误

⼀个项⽬中,会有很多类,每个类可能有很多的⽅法,Spring程序怎么知道要执⾏哪个⽅法呢?

Spring会对所有的类进⾏扫描,如果类加了注解@RestController,Spring才会去看这个类⾥⾯的⽅法 有没有加 @RequestMapping 这个注解。

1.2、@RequestMapping使⽤

@RequestMapping 既可修饰类,也可以修饰⽅法,当修饰类和⽅法时,访问的地址是类路径+⽅ 法路径. @RequestMapping标识⼀个类:设置映射请求的请求路径的初始信息

@RequestMapping标识⼀个⽅法:设置映射请求请求路径的具体信息

UsercController类上添加@RequestMapping("/user")

package com.pinkboy.springbootdemo;

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

@RestController
@RequestMapping("/user")
public class UserController {
     @RequestMapping("/sayHi")
    public String sayHi() {
        return "hello,Spring MVC";
    }
}

访问:http://127.0.0.1:8080/user/sayHi 

1.3、@RequestMapping 是GET还是POST请求?

GET请求: 浏览器发送的请求类型都是get,通过以上案例,可以看出来。

POST请求: 我们通过form表单来构造请求:

创建在static包下创建test.html, html代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/user/sayHi" method="post">
    <input type="submit" value="提交">
</form>
</body>
</html>

访问: http://127.0.0.1:8080/test.html --> 点击提交

 从运⾏结果可以看出: @RequestMapping 既⽀持Get请求,⼜⽀持Post请求.同理,也⽀持其他的请 求⽅式.

2、Postman介绍

随着互联⽹的发展,也随着项⽬难度的增加,企业也按照开发的功能,把⼈员拆分成了不同的团队.界⾯ 显⽰交给"前端开发⼯程师",业务逻辑的实现交给"后端开发⼯程师". 后端开发⼯程师,不要求也不需要掌握前端技能了. 那后端开发⼯程师,如何测试⾃⼰的程序呢?使⽤专业的接⼝测试⼯具:Postman

2.1、传参介绍

1. 普通传参,也就是通过查询字符串来传参

URL的格式如下:

1、查询字符串就是请求的参数 

2、form-data(完整表⽰为:multipart/form-data)

3、x-www-form-urlencoded

4、raw
可以上传任意格式的文本,可以上传text、json、xml、html等 

3、请求 

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

3.1 传递单个参数

接收单个参数

package com.pinkboy.springbootdemo;

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

@RestController
@RequestMapping("/param")
public class UserController {
    @RequestMapping("/m1")
    public String method1(String name) {
        return "name:" + name;
    }
}

如果参数不⼀致,无法获取参数

注意事项

使⽤基本类型来接收参数时,参数必须传(除boolean类型),否则会报500错误

类型不匹配时,会报400错误. 

1. 正常传递参数

  @RequestMapping("/m1/int")
    public Object method1GetInt(int age) {
        return age;
    }

2.不传递age参数

尝试观察程序的错误⽇志,并解决 

一般看日志堆栈信息的首行,报错信息显示:
int类型的参数'age',虽然为可选的,但由于被声明为基本类型而不能转换为空值.考虑将其声明为对应基本类型的包装类型,按照错误信息解决错误即可 

3. 传递参数类型不匹配

对于包装类型,如果不传对应参数,Spring接收到的数据则为null 所以企业开发中,对于参数可能为空的数据,建议使⽤包装类型 

3.2、传递多个参数

使⽤多个形参

 @RequestMapping("/m2")
    public Object method2(String name, String password) {
        return "name:" + name + ","+"password:" + password;
    }

 

当有多个参数时,前后端进⾏参数匹配时,是以参数的名称进⾏匹配的,因此参数的位置是不影响后 端获取参数的结果.

 

 3.3、传递对象

如果参数⽐较多时,⽅法声明就需要有很多形参.并且后续每次新增⼀个参数,也需要修改⽅法声明. 我们不妨把这些参数封装为⼀个对象.

Spring MVC也可以⾃动实现对象参数的赋值,⽐如Person对象:

package com.pinkboy.springbootdemo;

public class Person {
    private int id;
    private String name;
    private String password;

    public Person() {
    }

    public Person(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "id:" + id + " name:" + name + " password:" + password;
    }
}
 @RequestMapping("/m3")
    public Object method3(Person person) {
        return person.toString();
    }

Spring 会根据参数名称⾃动绑定到对象的各个属性上,如果某个属性未传递,则赋值为null(基本类型则 赋值为默认初识值,⽐如int类型的属性,会被赋值为0)

3.4、后端参数重命名

某些特殊的情况下,前端传递的参数key和我们后端接收的key可以不⼀致,⽐如前端传递了⼀个 time 给后端,⽽后端是使⽤createtime字段来接收的,这样就会出现参数接收不到的情况,如果出现 这种情况,我们就可以使⽤ @RequestParam 来重命名前后端的参数值.

后端实现代码:

   @RequestMapping("/m4")
    public Object method4(@RequestParam("time") String createTime) {
        return "createTime:" + createTime;
    }

浏览器使⽤createTime进⾏参数传递就会报错

 后端日志:

可以得出结论:

1. 使⽤ @RequestParam 进⾏参数重命名时, 请求参数只能和@RequestParam一致,才能进⾏参数绑定和赋值.

2. 使⽤ @RequestParam 声明的名称⼀ @RequestParam 进⾏参数重命名时,参数就变成了必传参数.

如何使用⾮必传参数?

我们可以通过设置 @RequestParam 中的 具体实现如下:

 @RequestMapping("/m4")
    public Object method4(@RequestParam(value = "time", required = false) String createTime) {
        return "createTime:" + createTime;
    }

可以看到,添加required=false之后, time前⾯也加了key,变成了 注解属性赋值时,没有指明key的话,默认为value属性. 如果需要有多个属性进⾏赋值时,需要写上key 

3.5、传递数组

Spring MVC可以⾃动绑定数组参数的赋值

后端实现代码:

 @RequestMapping("/m5")
    public String method5(String[] arrayParam) {
        return Arrays.toString(arrayParam);
    }

浏览器: 

Postman: 

 

3.6、传递JSON数据

JSON概念

JSON:JavaScriptObjectNotation 【JavaScript 对象表⽰法】 JSON是⼀种轻量级的数据交互格式.它基于ECMAScript(欧洲计算机协会制定的js规范)的⼀个⼦集, 采⽤完全独⽴于编程语⾔的⽂本格式来存储和表⽰数据。--百度百科 简单来说:JSON就是⼀种数据格式,有⾃⼰的格式和语法,使⽤⽂本表⽰⼀个对象或数组的信息,因此 JSON本质是字符串. 主要负责在不同的语⾔中数据传递和交换

JSON语法

JSON是⼀个字符串,其格式⾮常类似于JavaScript对象字⾯量的格式

{
 "squadName": "Super hero squad",
 "homeTown": "Metro City",
 "formed": 2016,
 "secretBase": "Super tower",
 "active": true,
 "members": [{
 "name": "Molecule Man",
 "age": 29,
 "secretIdentity": "Dan Jukes",
 "powers": ["Radiation resistance", "Turning tiny", "Radiation 
blast"]
 }, {
 "name": "Madame Uppercut",
 "age": 39,
 "secretIdentity": "Jane Wilson",
 "powers": ["Million tonne punch", "Damage resistance", "Superhuman 
reflexes"]
 }, {
 "name": "Eternal Flame",
 "age": 1000000,
 "secretIdentity": "Unknown",
 "powers": ["Immortality", "Heat Immunity", "Inferno", 
"Teleportation", "Interdimensional travel"]
 }]
 }

JSON的语法:

1. 数据在 键值对 (Key/Value) 中

2. 数据由逗号 , 分隔

3. 对象⽤ {} 表⽰

4. 数组⽤ [] 表⽰

5. 值可以为对象,也可以为数组,数组中可以包含多个对象

JSON的两种结构 :

1. 对象:⼤括号 {} 保存的对象是⼀个⽆序的 键值对集合.⼀个对象以左括号 { 开始,右括号 } 结束。每个"键"后跟⼀个冒号 : ,键值对使⽤逗号 , 分隔

2. 数组:中括号 [] 保存的数组是值(value)的有序集合.⼀个数组以左中括号 [ 开始,右中括 号 ] 结束,值之间使⽤逗号 , 分隔。

JSON字符串和Java对象互转

JSON本质上是⼀个字符串,通过⽂本来存储和描述数据 Spring MVC框架也集成了JSON的转换⼯具,我们可以直接使⽤,来完成JSON字符串和Java对象的互转

JSON的转换⼯具包有很多,jackson-databind只是其中的⼀种.

在test包下的com.pinkboy.springbootdemo中创建测试类JsonUtils

package com.pinkboy.springbootdemo;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;


public class JsonUtils {
    private static ObjectMapper objectMapper = new ObjectMapper();

    @Test
    void testObjectToJson() 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());
    }
}

运行:

使⽤ObjectMapper对象提供的两个⽅法,可以完成对象和JSON字符串的互转

writeValueAsString: 把对象转为JSON字符串

readValue: 把字符串转为对象 

JSON的优点:

1. 简单易⽤:语法简单,易于理解和编写,可以快速地进⾏数据交换

2. 跨平台⽀持: JSON可以被多种编程语⾔解析和⽣成,可以在不同的平台和语⾔之间进⾏数据交换和 传输.

3. 轻量级:相较于XML格式,JSON数据格式更加轻量级,传输数据时占⽤带宽较⼩,可以提⾼数据传输 速度

4. 易于扩展: JSON的数据结构灵活,⽀持嵌套对象和数组等复杂的数据结构,便于扩展和使⽤

5. 安全性:JSON数据格式是⼀种纯⽂本格式,不包含可执⾏代码,不会执⾏恶意代码,因此具有较⾼ 的安全性 基于以上特点,JSON在Web应⽤程序中被⼴泛使⽤,如前后端数据交互、API接⼝数据传输等

 传递JSON对象

接收JSON对象,需要使用@RequestBody注解

后端实现:

@RequestMapping(value = "/m7")
 public Object method7(@RequestBody Person person) {
 return person.toString();
 }

使⽤Postman来发送json请求参数:

去除掉 @RequestBody

后端未能成功给Person对象赋值

 获取URL中参数@PathVariable

pathvariable:路径变量
和字面表达的意思一样,这个注解主要作用在请求URL路径上的数据绑定

后端实现代码:

 @RequestMapping("/m8/{id}/{name}")
    public String method8(@PathVariable Integer id,@PathVariable("name") String userName){
        return "id:"+id+",name:"+userName;
    }

使用Postman发送请求

 如果⽅法参数名称和需要绑定的URL中的变量名称⼀致时,可以简写,不⽤给@PathVariable的属性赋 值,如上述例⼦中的id变量 如果⽅法参数名称和需要绑定的URL中的变量名称不⼀致时,需要@PathVariable的属性value赋值, 如上述例⼦中的userName变量.

3.7上传⽂件@RequestPart

后端代码实现:

    @RequestMapping("/m9")
    public String getFile(@RequestPart("file") MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        file.transferTo(new File("C:\\JavaStudy\\SpringStudy\\spring\\springboot-demo\\src\\assert\\" + file.getOriginalFilename()));
        return "名称:" + fileName;
    }

Postman发送请求:

⽂件上传成功

3.8、Cookie和Session

3.8.1、回顾Cookie

HTTP协议⾃⾝是属于"⽆状态"协议

"⽆状态"的含义指的是: 默认情况下HTTP协议的客⼾端和服务器之间的这次通信,和下次通信之间没有直接的联系。

但实际开发中,我们很多时候是需要知道请求之间的关联关系的。

上述图中的"令牌"通常就存储在Cookie字段中

⽐如去医院挂号 

1. 看病之前先挂号.挂号时候需要提供⾝份证号,同时得到了⼀张"就诊卡",这个就诊卡就相当于患 者的"令牌".

2. 后续去各个科室进⾏检查,诊断,开药等操作,都不必再出⽰⾝份证了,只要凭就诊卡即可识别出当 前患者的⾝份.

3. 看完病了之后,不想要就诊卡了,就可以注销这个卡.此时患者的⾝份和就诊卡的关联就销毁了.(类 似于⽹站的注销操作)

4. ⼜来看病,可以办⼀张新的就诊卡,此时就得到了⼀个新的"令牌"

此时在服务器这边就需要记录"令牌"信息,以及令牌对应的⽤⼾信息,这个就是Session机制所做的⼯ 作

3.8.2、理解Session

我们先来了解⼀下什么是会话.

会话:对话的意思

在计算机领域, 会话是⼀个客⼾与服务器之间的不中断的请求响应.对客⼾的每个请求,服务器能够识 别出请求来⾃于同⼀个客⼾.当⼀个未知的客⼾向Web应⽤程序发送第⼀个请求时就开始了⼀个会话. 当客⼾明确结束会话或服务器在⼀个时限内没有接受到客⼾的任何请求时,会话就结束了.

举个例子:

⽐如我们打客服电话 每次打客服电话,是⼀个会话.挂断电话,会话就结束了 下次再打客服电话,⼜是⼀个新的会话. 如果我们⻓时间不说话,没有新的请求,会话也会结束.

服务器同⼀时刻收到的请求是很多的.服务器需要清楚的区分每个请求是属于哪个⽤⼾,也就是属于哪个会话,就需要在服务器这边记录每个会话以及与⽤⼾的信息的对应关系. Session是服务器为了保存⽤⼾信息⽽创建的⼀个特殊的对象.

Session的本质就是⼀个"哈希表",存储了⼀些键值对结构.Key就是SessionID,Value就是⽤⼾信息(⽤ ⼾信息可以根据需求灵活设计) 

SessionId 是由服务器⽣成的⼀个"唯⼀性字符串",从Session机制的⻆度来看,这个唯⼀性字符串称 为"SessionId". 但是站在整个登录流程中看待,也可以把这个唯⼀性字符串称为"token". 上述例⼦中的令牌ID,就可以看做是SessionId,只不过令牌除了ID之外,还会带⼀些其他信息,⽐如时 间,签名等.

1. 当⽤⼾登陆的时候,服务器在Session中新增⼀个新记录,并把sessionId返回给客⼾端.(通过 HTTP响应中的Set-Cookie字段返回).

2. 客⼾端后续再给服务器发送请求的时候,需要在请求中带上sessionId.(通过HTTP请求中的 Cookie 字段带上).

3. 服务器收到请求之后,根据请求中的sessionIdSession信息中获取到对应的⽤⼾信息,再进⾏后 续操作.找不到则重新创建Session,并把SessionID返回

 Session 默认是保存在内存中的.如果重启服务器则Session数据就会丢失.

3.8.3、Cookie 和Session的区别

Cookie是客户端保存用户信息的一种机制.Session是服务器端保存用户信息的一种机制.
Cookie和Session之间主要是通过Sessionld关联起来的,Sessionld是Cookie和Session之间的
桥梁
Cookie和Session经常会在一起配合使用.但是不是必须配合.
 完全可以用Cookie来保存一些数据在客户端.这些数据不一定是用户身份信息,也不一定是
Sessionld
Session中的sessionld也不需要非得通过Cookie/Set-Cookie传递,比如通过URL传递.

3.8.4、Cookie读取

使⽤HttpServletRequest获取Cookie

在浏览器中伪造cookie

 @RequestMapping("/getCookie")
    public String getCookie(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        
        if (cookies != null) {
            Arrays.stream(cookies).forEach(cookie -> System.out.println(cookie.getName() + " : " + cookie.getValue()));
        }
        return "获取cookie成功!";
    }

 在浏览器中显示 “获取cookie成功!"

 在服务器中显示 "username : zhangsan"

使用@CookieValue 注解获取Cookie
 //获取cookie
    @RequestMapping("/getCookie2")
    public String getCookie(@CookieValue String username) {
        return "cookie存储的username :" + username;
    }

浏览器中显示的结果 

 3.8.5、Session的读取

服务器中的Session不可伪造

使⽤HttpServletRequest设置Session

    @RequestMapping("/setSession")
    public String setSession(HttpServletRequest request) {
        HttpSession session = request.getSession();
        session.setAttribute("username", "张三");
        return "success";
    }

在浏览器中显示 

方式一: 使⽤HttpServletRequest获取Session

 //获取Session
    @RequestMapping("/getSession")
    public String getSession(HttpServletRequest request) {
        HttpSession session = request.getSession(true);
        if (session != null) {
            String username = (String) session.getAttribute("username");
            return "登录用户:" + username;
        }
        return "session 为空";
    }

 在浏览器中显示

 方式二:使用注解 @SessionAttribute

@RequestMapping("/getSession2")
    public String getSession2(@SessionAttribute(required = false) String username) {
        return "username:" + username;
    }

 

方式三:使用 HttpSession

@RequestMapping("/getSession3")
    public String getSession3(HttpSession session) {
        String username = (String) session.getAttribute("username");
        return "登录用户:" + username;
    }

3.8.6 获取Header

方式一:从 HttpServletRequest 中获取

 @RequestMapping("/getHeader")
    public String getHeader(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        return "User-Agent:" + userAgent;
    }

方式二:通过注解获取 @RequestHeader

@RequestMapping("/getHeader2")
    public String getHeader(@RequestHeader("User-Agent") String userAgent) {
        return "User-Agent:" + userAgent;
    }

4、响应

4.1、返回静态页面

创建前端⻚⾯index.html(注意路径)

html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index首页</title>
</head>
<h1>index首页</h1>
<body>

</body>
</html>

后台代码:

@RequestMapping("/return")
@RestController
//@Controller
public class ReturnController {
    @RequestMapping("/index")
    public String returnIndex() {
        return "/index.html";
    }
}

浏览器显示:http://127.0.0.1:8080/return/index

修改注释 将 @RestController 修改为 @Controller 再次运行后端服务器

浏览器显示:http://127.0.0.1:8080/return/index

4.2、@RestController 和 @Controller的关联和区别

随着互联⽹的发展,⽬前项⽬开发流⾏"前后端分离"模式, Java主要是⽤来做后端项⽬的开发,所以也就 不再处理前端相关的内容了

MVC的概念也逐渐发⽣了变化,View不再返回视图,⽽是返回显⽰视图时需要的数据.

所以前⾯使⽤的 @RestController 其实是返回的数据.

@RestController = @Controller + @ResponseBody

@Controller 定义⼀个控制器,Spring框架启动时加载,把这个对象交给Spring管理.
@ResponseBody 定义返回的数据格式为⾮视图,返回⼀个text/html信息

如果想返回视图的话,只需要把 @ResponseBody 去掉就可以了,也就是 @Controller 

4.3、返回数据@ResponseBody

@Controller
public class ReturnController {

    @ResponseBody
    @RequestMapping("/index")
    public String returnIndex() {
        return "/index.html";
    }
}

加上 @ResponseBody 注解,该⽅法就会把"/index.html"当做⼀个数据返回给前端

@ResponseBody 既是类注解,⼜是⽅法注解

如果作⽤在类上,表⽰该类的所有⽅法,返回的都是数据,如果作⽤在⽅法上,表⽰该⽅法返回的是数据.

也就是说:在类上添加 @ResponseBody 就相当于在所有的⽅法上添加了 同样,如果类上有 @ResponseBody 注解. @RestController 注解时:表⽰所有的⽅法上添加了 @ResponseBody 注 解,也就是当前类下所有的⽅法返回值做为响应数据.

如果去掉 @ResponseBody 注解,程序会报404错误.

@Controller
public class ReturnController {

    @ResponseBody
    @RequestMapping("/index")
    public String returnIndex() {
        return "/index.html";
    }

   // @ResponseBody
    @RequestMapping("/returnData")
    public String returnData() {
        return "返回视图所需要的数据";
    }
}

 浏览器输入:http://127.0.0.1:8080/return/returnData

程序会认为需要返回的是视图,根据内容去查找⽂件,但是查询不到,路径不存在,报404 

 4.4、返回代码片段

后端返回数据时,如果数据中有HTML代码,也会被浏览器解析

   @ResponseBody
    @RequestMapping("/returnHtml")
    public String returnHtml() {
        return "<h1>返回HTML代码片段</h1>";
    }

通过Fiddler观察响应结果, Content-Type text/html

响应中的Content-Type常见取值有以下几种:
1、text/html:body数据格式是HTML
2、text/css:body         数据格式是CSS
3、application/javascriptbody  数据格式是 JavaScript
4、application/json:body数据格式是JSON

        
如果请求的是js文件,SpringMvc会自动设置Content-Type为application/javascript
如果请求的是css文件,SpringMVC会自动设置Content-Type为text/csS

4.5、返回JSON

Spring MVC也可以返回JSON 后端⽅法返回结果为对象

 @ResponseBody
    @RequestMapping("/returnJson")
    public String returnJson() {
        Person peperson = new Person(1, "张三", 20);
        return "id:" + peperson.getId() + ",name:" + peperson.getName() + ",age:" + peperson.getAge();
    }

    @ResponseBody
    @RequestMapping("/returnMap")
    public Map<String, String> returnMap() {
        Map<String, String> kv = new HashMap<>();
        kv.put("k1", "v1");
        kv.put("k2", "v2");
        kv.put("k3", "v3");
        return kv;
    }

浏览器输入http://127.0.0.1:8080/return/returnMap

通过Fiddler观察响应结果, Content-Type 为 application/json

4.6、设置状态码

 Spring MVC会根据我们⽅法的返回结果⾃动设置响应状态码,程序员也可以⼿动指定状态码 通过SpringMVC的内置对象HttpServletResponse提供的⽅法来进⾏设置

    @ResponseBody
    @RequestMapping("/returnStatus")
    public String returnStatus(HttpServletResponse response) {
        response.setStatus(401);
        return "设置状态码";
    }

 状态码不会影响页面的展示

4.7、设置Header

Http响应报头也会向客⼾端传递⼀些附加信息,⽐如服务程序的名称,请求的资源已移动到新地址等,如: Content-Type, Local等

4.7.1、设置Content-Type

通过设置produces属性的值,设置响应的报头Content-Type

@RequestMapping(value = "/returnJson2",produces = "application/json")
 @ResponseBody
 public String returnJson2() {
 return "{\"success\":true}";
 }

 浏览器响应结果如下:http://127.0.0.1:8080/returnJson2

通过Fiddler来观察设置的结果:

如果不设置produces,⽅法返回结果为String时,SpringMVC默认返回类型,是text/html. 

去掉produces 重复上述操作 在Fiddler中的结果:

4.7.2、设置其他Header

设置其他Header的话,需要使⽤SpringMVC的内置对象HttpServletResponse提供的⽅法来进⾏设置

 @ResponseBody
    @RequestMapping(value = "/setHeader", produces = "application/json;charset=UTF-8")
    public String r1(HttpServletResponse response) {
        response.setHeader("myheader", "myHeaderValue");
        return "{OK:1}";
    }

void setHeader(String name, String value) 设置⼀个带有给定的名称和值的header.如果name 已经存在,则覆盖旧的值.

运⾏程序,浏览器响应结果如下: http://127.0.0.1:8080/setHeader

通过Fiddler来观察设置的结果:


http://www.kler.cn/a/506257.html

相关文章:

  • 配置AOSP下载环境
  • c#-Halcon入门教程——标定
  • 计算机网络的五层协议
  • 音视频入门基础:RTP专题(1)——RTP官方文档下载
  • IDEA的Java注释在Toggle Rendered View下的字号调整方式
  • 【数据结构】基础知识
  • 微软徽标认证WHQL
  • thinkphp6 + redis实现大数据导出excel超时或内存溢出问题解决方案
  • Nvidia Blackwell架构深度剖析:深入了解RTX 50系列GPU的升级
  • leetcode118.杨辉三角
  • C++实现设计模式---外观模式 (Facade)
  • RK3399开发板Linux实时性改造
  • STM32+W5500+以太网应用开发+003_TCP服务器添加OLED(u8g2)显示状态
  • stm32步进电机曲线控制程序
  • 【2025 Rust学习 --- 18 IO操作和网络】
  • 基于unity的多人家装应用的设计与实现
  • 【Python】-- 趣味代码 - 发牌游戏
  • 【Web】Web API 简介
  • Portainer CE本地化部署与远程可视化管理Docker容器实战指南
  • [Qt] 系统相关_1 | 常见事件 | 事件分发器 | 过滤器
  • 【Apache Paimon】-- 源码解读之 PaimonSparkSessionExtensions
  • 高阶数据结构之跳表
  • 【NLP高频面题 - 高效微调篇】LoRA微调时有哪些可配置的参数?
  • vscode——如何让标点总是成对出现
  • 启航数据结构算法之雅舟,悠游C++秘境——单链表之美妙构筑
  • Docker PG流复制搭建实操