【Spring】Spring MVC请求响应

文章目录

  • [1. 请求](#1. 请求)
    • [1.1 传递单个参数](#1.1 传递单个参数)
    • [1.2 传递多个参数](#1.2 传递多个参数)
    • [1.3 传递对象](#1.3 传递对象)
    • [1.4 后端参数重命名](#1.4 后端参数重命名)
    • [1.5 传递数组](#1.5 传递数组)
    • [1.6 传递集合](#1.6 传递集合)
    • [1.7 传递JSON对象](#1.7 传递JSON对象)
    • [1.8 获取URL中参数](#1.8 获取URL中参数)
    • [1.9 上传⽂件](#1.9 上传⽂件)
    • [1.10 获得Cookie](#1.10 获得Cookie)
    • [1.11 获得Session](#1.11 获得Session)
    • [1.12 获得Header](#1.12 获得Header)
  • [2. 响应](#2. 响应)
    • [2.1 返回静态界面](#2.1 返回静态界面)
    • [2.2 返回数据](#2.2 返回数据)
    • [2.3 返回HTML代码片段](#2.3 返回HTML代码片段)
    • [2.4 返回JSON](#2.4 返回JSON)
    • [2.5 设置状态码](#2.5 设置状态码)

1. 请求

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

传递参数,我们通过postman测试。

1.1 传递单个参数

java 复制代码
@RequestMapping("/param")
@RestController
public class ParamController {
    @RequestMapping("/m1")
    public String m1(String name){
        return "name: " + name;
    }
}    

正常传递:

可以看到, 后端程序正确拿到了name参数的值。

Spring MVC 会根据⽅法的参数名, 找到对应的参数, 赋值给⽅法。

所以这里要注意,传递的参数要和后端代码中的参数一致。

那不一致会出现什么现象呢?我们直接测试,如图:

可以发现是获不得参数的,name依旧为空。

这里还需要注意,参数的类型如果不是包装类(boolean),参数必须传,不然会报500错误,类型也要一致,不然会报400错误。

对于参数可能为空的数据,建议使⽤包装类型。

把参数类型修改为int:

java 复制代码
@RequestMapping("/param")
@RestController
public class ParamController {
    @RequestMapping("/m1")
    public String m1(int n){
        return "n = " + n;
    }
}    

500

400

1.2 传递多个参数

java 复制代码
@RequestMapping("/param")
@RestController
public class ParamController {
    @RequestMapping("/m2")
    public String m2(String name, Integer age){
        return "name: " + name + ", age: " + age;
    }
}    

正常传递:

参数要一致,但是它们顺序可以调换。 要求和单个参数一样的。

但是可以发现这种还是有弊端,就是当增加新的参数,修改代码会非常麻烦,这个时候就可以把这些参数封装成对象,当增加新的参数,只需要多封装个属性。

1.3 传递对象

创建Person类:

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

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getPassword() {
        return password;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", password='" + password + '\'' +
                '}';
    }
}

这个时候,传递对象代码:

java 复制代码
public class ParamController {
    @RequestMapping("/m4")
    public String m4(Person person){
        return person.toString();
    }
}

正常传参:

当传参后,后端代码拿到对应的参数,Spring 会根据参数名称⾃动绑定到对象的各个属性上, 如果某个属性未传递, 则赋值为null(基本类型则

赋值为默认初识值, ⽐如int类型的属性, 会被赋值为0)。

如果增加新的参数,只需要修改Person中代码,变得更加简单。

1.4 后端参数重命名

有时,前端参数的名字,我们想做出修改,让它更加的方便区分,这个时候就用到@RequestParam ,这个注解可以后端参数映射为其他名。

修改m2方法。

java 复制代码
@RequestMapping("/param")
@RestController
public class ParamController {
    @RequestMapping("/m2")
    public String m2(@RequestParam("name") String myName, @RequestParam("age") Integer myAge){
        return "name: " + myName + ", age: " + myAge;
    }
}    

相同请求不受影响:

映射后要注意,映射的参数会变成必传参数。

参数不传:

但也可以改变,查看@RequestParam源码:

发现required默认值为true,含义就是它修饰的参数为必传,那么只要修改它的返回值即可

如下面代码,这时就不是比传参数。

java 复制代码
public String m2(@RequestParam(value = "name",required = false) String myName, @RequestParam(value = "age", required = false) Integer myAge){
        return "name: " + myName + ", age: " + myAge;
    }

1.5 传递数组

java 复制代码
@RequestMapping("/param")
@RestController
public class ParamController {
    @RequestMapping("/m5")
    public String m5(String[] array){
        return Arrays.toString(array);
    }
}

传参:

我们可以使用, 直接分割。

1.6 传递集合

java 复制代码
@RequestMapping("/param")
@RestController
public class ParamController {
    @RequestMapping("/m6")
    public String m6(@RequestParam List<String> list){
        return list + "";
    }
}

当用postman传参:

可以正常请求,但是当使用浏览器时,有时要进行转义编码。

例如:, 转义为%2c。

且需要使⽤ @RequestParam 绑定参数关系。

默认情况下,请求中参数名相同的多个值,是封装到数组. 如果要封装到集合,要使⽤@RequestParam绑定参数关系。

1.7 传递JSON对象

java 复制代码
    @RequestMapping("/m7")
    public String m7(@RequestBody Person person){
        return person.toString();
    }

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

RequestBody: 请求正⽂,意思是这个注解作⽤在请求正⽂的数据绑定,请求参数必须在写在请求正⽂中。

不使用注解将无法赋值。

传递参数:

这时,请求类型就是JOSN。

1.8 获取URL中参数

java 复制代码
    @RequestMapping("/m8/{age}/{name}")
    public String m8(@PathVariable Integer age, @PathVariable("name") String useName){
        return "解析参数: " + age + ", name: " + useName;
    }

传参:

@PathVariable:这个注解主要作⽤在请求URL路径上的数据绑定。
如果⽅法参数名称和需要绑定的URL中的变量名称⼀致时, 可以简写, 不⽤给@PathVariable的属性赋值, 如上述例⼦中的id变量。
如果⽅法参数名称和需要绑定的URL中的变量名称不⼀致时, 需要@PathVariable的属性value赋值,如上述例⼦中的userName变量。

1.9 上传⽂件

java 复制代码
    @RequestMapping("/m9")
    public String m9(@RequestPart("file") MultipartFile file) throws IOException {
        //获得文件名称
        String s = file.getOriginalFilename();
        //上传到指定路径
        file.transferTo(new File("D:/temp/" + file.getOriginalFilename()));
        return s;
    }

传参:

上传文件:

D:\temp中:

上传文件要使用@RequestPart注解,注解中参数要和传的参数名一致。

1.10 获得Cookie

java 复制代码
    @RequestMapping("/m10")
    public String m10(HttpServletRequest request){
        //获得所有Cooike
        Cookie[] cookies = request.getCookies();
        //打印
        StringBuilder stringBuilder = new StringBuilder();
        if(cookies != null){
            for (Cookie cookie: cookies) {
            	stringBuilder.append(cookie.getName() + " : " + cookie.getValue());
            }
        }
        return "Cookie: " + stringBuilder;
    }

上面是Servlet获得Cookie的方式,因为Spring MVC是基于Servlet API实现的Web框架,所以HttpServletRequest , HttpServletResponse 是Servlet提供的两个类, 是Spring MVC⽅法的内置对象. 需要时直接在⽅法中添加声明即可。

响应结果并没有Cookie,这是因为网站中并没有Cookie,直接在postman中添加Cookie即可。


通过这个也可以看出,Cookie是可以伪造的,后端收到Cookie要进行校验。

上面方式也可以通过注解@CookieValue 简化,简化后的代码如下。

java 复制代码
    @RequestMapping("/getCookie")
    public String getCookie(@CookieValue String xiaochen){
        return "name: " + xiaochen;
    }
}

1.11 获得Session

java 复制代码
    @RequestMapping("/setSession")
    public String setSession(HttpServletRequest request){
        HttpSession session = request.getSession();
        if(session != null){
            session.setAttribute("name","java");
        }
        return "存储成功";
    }

Session在服务端,所以无法直接添加,可以通过上述方式。

HttpSession getSession(boolean create) : 参数如果为 true, 则当不存在会话时新建会话; 参数如果为 false, 则当不存在会话时返回 null 。默认为true。

void setAttribute(String name, Object value): 使⽤指定的名称绑定⼀个对象到该 session 会话。

通过Fiddler观察Http请求和响应情况:

获得Session方法和获得Cookie一样有很多种,通常使用下面简单的两种。

HttpSession session = request.getSession();

Session 不存在的话, 会⾃动进⾏创建。

java 复制代码
    @RequestMapping("/getSession1")
    public String getSession(@SessionAttribute(required = false) String name){
        return "name: " + name;
    }
    @RequestMapping("/getSession2")
    public String getSession2(HttpSession session){
        String name = (String) session.getAttribute("name");
        return "name: " + name;
    }

1.12 获得Header

java 复制代码
    @RequestMapping("/getHeader")
    public String getHeader(@RequestHeader("User-Agent") String useragent){
        return useragent;
    }

使用@RequestHeader 注解即可获得。

2. 响应

在我们前⾯的代码例⼦中,都已经设置了响应数据, Http响应结果可以是数据, 也可以是静态⻚⾯,也可以针对响应设置状态码, Header信息等。

2.1 返回静态界面

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index页面</title>
</head>
<body>
    Hello,Spring MVC.
</body>
</html>

前端代码,注意文件位置。

后端返回代码如何写呢?先按照响应的模式写,代码如下。

java 复制代码
@RequestMapping("/return")
@RestController
public class ReturnController {
    @RequestMapping("/index")
    public String returnIndex(){
        return "/index.html";
    }
}

直接返回,运行查看:

这很不明显不对,这是返回了一个字符串。

这时,就需要另一个注解了,我们需要把最前面的@RestController 改为 @Controller。

再次请求,便可以得到我们想要的结果:

2.2 返回数据

java 复制代码
@RequestMapping("/return")
//@RestController
@Controller
@ResponseBody
public class ReturnController {
    @RequestMapping("returnData")
    public String returnData(){
        return "返回数据";
    }
}

返回数据,前面其实一直在用,如果返回静态界面,需要写@Controller 注解,如果要直接返回数据,还需要加上个@ResponseBody注解。注意:@ResponseBody 即可作用在类上,表示类中所以方法返回都是数据,也可以作用在方法上,只表示该方法返回数据,这两个注解也可以和二为一,就是前面经常写的@RestController,但它也只能修饰类了。

2.3 返回HTML代码片段

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

当返回数据有HTML代码,浏览器会自动解析:

如果用Fiffler抓包,可以看到Content-Type为text/html。

响应中的 Content-Type 常⻅取值有以下⼏种:

  • text/html : body 数据格式是 HTML。
  • text/css : body 数据格式是 CSS。
  • application/javascript : body 数据格式是 JavaScript。
  • application/json : body 数据格式是 JSON。

如果请求的是js⽂件, 那么Spring MVC会⾃动设置Content-Type为 application/javascript。

如果请求的是css⽂件, 那么SpringMVC会⾃动设置Content-Type为 text/css。

2.4 返回JSON

java 复制代码
    @RequestMapping("/returnJosn")
    @ResponseBody
    public HashMap<String,String> josn(){
        HashMap<String,String> map = new HashMap<>();
        map.put("Java","Java V");
        map.put("Mysql","Mysql V");
        return map;
    }

响应:

JOSN内也是键值对,可以使用map。

2.5 设置状态码

java 复制代码
    @RequestMapping("/setStatus")
    @ResponseBody
    public String setStatus(HttpServletResponse response){
        response.setStatus(401);
        return "设置状态码成功";
    }

直接设置即可:

抓包:

相关推荐
腥臭腐朽的日子熠熠生辉21 分钟前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian23 分钟前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之28 分钟前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码1 小时前
Spring Task 定时任务
java·前端·spring
俏布斯1 小时前
算法日常记录
java·算法·leetcode
27669582921 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息1 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
程序猿chen1 小时前
《JVM考古现场(十五):熵火燎原——从量子递归到热寂晶壁的代码涅槃》
java·jvm·git·后端·java-ee·区块链·量子计算
松韬2 小时前
Spring + Redisson:从 0 到 1 搭建高可用分布式缓存系统
java·redis·分布式·spring·缓存
绝顶少年2 小时前
Spring Boot 注解:深度解析与应用场景
java·spring boot·后端