【SpringMVC】请求与响应

👉 博客主页:准Java全栈开发工程师
👉 00年出生,即将进入职场闯荡,目标赚钱,可能会有人觉得我格局小、觉得俗,但不得不承认这个世界已经不再是以一条线来分割的平面,而是围绕财富旋转的球面,成为有钱人不是为了去掌控球体的转向,而是当有人恶意掌控时,努力保护好家人和自己。

  • SpringMVC 作为 Web 层框架,最主要的作用就是接收请求、接收数据、数据响应。所以,如果我们想扎实的掌握 SpringMVC ,搞懂这部分内容还是非常重要的。

一、如何避免映射路径同名问题

1、问题描述

  • 我们在 controller 类中使用 @RequestMapping 注解指定映射路径时,不免会出现两个不同的 controller 类中出现同样的映射路径。
@Controller
public class UserController {
    @ResponseBody
    @RequestMapping("/select")
    public String save(){
        System.out.println("qdxorigin save ...");
        return "{'msg':'qdxorigin'}";
    }
}

@Controller
public class AccountController {
    @ResponseBody
    @RequestMapping("/select")
    public String save(){
        System.out.println("qdxorigin account save ...");
        return "{'msg':'qdxorigin'}";
    }
}
  • 此时,我们运行项目启动 tomcat 时就会报错。
    在这里插入图片描述
  • 这是因为当在访问 /select 映射路径时,并不能清楚的知道应该与那个方法相匹配导致的。

2、解决方式

方式一
@Controller
public class UserController {
    @ResponseBody
    @RequestMapping("/user/select")
    public String save(){
        System.out.println("qdxorigin user save ...");
        return "{'msg':'qdxorigin'}";
    }
}

@Controller
public class AccountController {
    @ResponseBody
    @RequestMapping("/account/select")
    public String save(){
        System.out.println("qdxorigin account save ...");
        return "{'msg':'qdxorigin'}";
    }
}
  • 在方法的映射路径上加上所在的类名,如上所示,这样就不会再出现重复的问题,但是如果 controller 中涉及到非常多的方法,都要一个一个在方法的映射路径上加上 “/user” 或 “/account” 吗?是不是很麻烦,且存在写错的问题。所以在解决映射路径重名问题时推荐使用方式二。
方式二
@Controller
@RequestMapping("/user")
public class UserController {
    @ResponseBody
    @RequestMapping("/select")
    public String save(){
        System.out.println("qdxorigin user save ...");
        return "{'msg':'qdxorigin'}";
    }
}
  • 在每个 controller 类上,使用 @RequestMapping 注解指定路径前缀,之后在方法上就无需再添加 /user 这些,简便易修改还不易出错。

二、如何接收请求参数

1、接收普通参数

@Controller
@RequestMapping("/user")
public class UserController {
    @ResponseBody
    @RequestMapping("/select")
    public String select(String name, Integer age){
        System.out.println("name = " + name + " , age = " + age);
        return "{'msg':'qdxorigin'}";
    }
}
  • 对于普通参数的接收,直接在方法的形参列表中添加即可。
  • 使用 Postman 工具测试。
    在这里插入图片描述
  • 控制台返回数据。
    在这里插入图片描述
  • 在发送请求时,请求路径中的参数名和方法形参名是一致的,所以能够准确的赋值,但是如果请求路径中的参数名和方法形参名不同应该如何解决呢?解决方式也非常的简单,只需要在形参列表中使用 @RequestParam(“username”) 指定请求路径参数名即可。
@Controller
@RequestMapping("/user")
public class UserController {
    @ResponseBody
    @RequestMapping("/select")
    public String select(@RequestParam("username") String name, Integer age){
        System.out.println("name = " + name + " , age = " + age);
        return "{'msg':'qdxorigin'}";
    }
}
  • 再次发送 GET 请求,查看是否能够成功接收到数据,此时请求路径的参数名已经改为了 username 。
    在这里插入图片描述
  • 在控制台仍然能够准确的获取数据,这是 @RequestParam(“username”) 起作用了。
    在这里插入图片描述

2、接收实体类

@Controller
@RequestMapping("/user")
public class UserController {
    @ResponseBody
    @RequestMapping("/select2")
    public String select2(User user){
        System.out.println(user);
        return "{'msg':'qdxorigin'}";
    }
}

public class User {
    private String name;
    private Integer age;
    private Account account;
}
  • 不用过于纠结我的方法名和映射路径,只是为了对相应技术进行测试,在实际开发中,还是需要遵循见名知意的。
  • 实体类的接收和普通类型非常相似,也是在方法形参中声明即可。
    在这里插入图片描述
  • 请求路径中的 key 值是需要和 User 类的属性名保持一致的,不一致就无法完成数据的绑定。
    在这里插入图片描述
  • 因为并没有为传 account 参数,数据绑定失败,以默认值代替。

3、接收嵌套实体类

@Controller
@RequestMapping("/user")
public class UserController {
    @ResponseBody
    @RequestMapping("/select2")
    public String select2(User user){
        System.out.println(user);
        return "{'msg':'qdxorigin'}";
    }
}

public class User {
    private String name;
    private Integer age;
    private Account account;
}

public class Account {
    private Integer id;
    private Double money;
}
  • 在上一个部分接收实体类参数时,没有传入 account 参数,是因为 account 自己也是一个实体类,他的传参方式有些许特别。
    在这里插入图片描述
  • 嵌套实体的传参方式为 “对象.属性”的方式,有点像我们调用时的形式。
    在这里插入图片描述
  • 这一次控制台可以完整的打印出 user 信息了。

4、接收数组类型的参数

@Controller
@RequestMapping("/user")
public class UserController {
    @ResponseBody
    @RequestMapping("/select3")
    public String select3(String[] names){
        System.out.println(Arrays.toString(names));
        return "{'msg':'qdxorigin'}";
    }
}
  • 看到这,是否对接收方式有一点了解了,其实就是需要接收什么,就将它扔到形参列表中即可。
    在这里插入图片描述
  • 对于数组类型的参数,传参时提供多个同名的 key 即可,接收时回自动封装到数组中。
    在这里插入图片描述
  • 但是对于一个 Java 程序员来说,使用数组的机会不是很多,更多情况下我们都会选择使用集合来代替数组。

5、接收集合类型的参数

@Controller
@RequestMapping("/user")
public class UserController {
    @ResponseBody
    @RequestMapping("/select4")
    public String select4(@RequestParam List<String> names){
        System.out.println(names);
        return "{'msg':'qdxorigin'}";
    }
}
  • 接收集合类型的参数时,除了在形参列表中声明外,还需要使用 @RequestParam 注解将传入的参数值映射到集合对象中,如果不指定,会报错,报错原因是错误的认为 List 集合是一个实体类,想要调用构造方法创建对象时,发现并没有提供对应的构造方法(因为 List 是一个接口,没有提供构造方法)。
    在这里插入图片描述
  • 传参方式和数组类型是一模一样的,就连打印结果也是一样的。
    在这里插入图片描述
  • 前面演示了这么多,都是演示的 GET 请求,接下来就简单演示一下 POST 请求,其实这两种方式是非常相似的。

6、POST 请求简单演示

  • 首先需要将请求方式改为 POST ,除此之外,POST 请求的传参位置也有所变化,不再在 Params 中,而是转到了 Body 下的 x-www-form-urlencoded 中进行,之后的和 GET 请求并无太大差别。
    在这里插入图片描述
  • 控制台仍然能够正确接收。
    在这里插入图片描述
  • 对于其他类型的参数接收在此就不一一展示了,感兴趣的小伙伴可以自己测试一下。

三、json类型数据

  • 异步调用作为最近比较流行的开发方式,也推动了 json 类型数据的使用,那么,我们该如何传输和接收 json 数据呢?

1、常见的 json 数据类型

  • 普通数组:[“value1”,“value2”,“value3”,…]
  • json对象:{key1:value1,key2:value2,…}
  • 对象数组:[ {key1:value1,…},{key2:value2,…} ]

2、导入依赖

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.1</version>
    </dependency>
  • 为了能准确的完成 json 数据的绑定,我们需要导入相应的 jar 包才能实现。

3、配置类开启注解支持

@Configuration
@ComponentScan("qdxorigin.controller")
@EnableWebMvc
public class SpringMvcConfig {
}
  • @EnableWebMvc 注解能够开启 json 数据类型自动转换,该注解的功能非常强大,还有其他用处,在此不一一介绍,用到时再做阐述。

4、接收普通数组

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/forJson")
    @ResponseBody
    public String forJson(@RequestBody String[] names){
        System.out.println(Arrays.toString(names));
        return "{'msg':'qdxorigin'}";
    }
}
  • @RequestBody 注解将外部传递的 json 数组数据映射到形参的集合对象中。
    在这里插入图片描述
  • 传入 json 数据时,要在 Body 下的 raw 区域进行,类型选择为 JSON。
    在这里插入图片描述

5、接收 json 对象

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/forJson3")
    @ResponseBody
    public String forJson3(@RequestBody User user){
        System.out.println(user);
        return "{'msg':'qdxorigin'}";
    }
}

public class User {
    private String name;
    private Integer age;
    private Account account;
}

在这里插入图片描述

  • 注意区分使用 “[ ]” 和 “{ }”。
    在这里插入图片描述

6、接收对象数组

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/forJson4")
    @ResponseBody
    public String forJson4(@RequestBody List<User> users){
        System.out.println(users);
        return "{'msg':'qdxorigin'}";
    }
}

在这里插入图片描述

  • 传入对象数组,其实就是对象和数组的结合,并没有什么吓人的。
    在这里插入图片描述

7、@RequestBody VS @RequestParam

  • @RequestParam 用于接收 url 地址传参,表单传参。
  • @RequestBody 用于接收 json 数据。

四、日期类型参数

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/forDate")
    @ResponseBody
    public String date(Date date,
                       @DateTimeFormat(pattern = "yyyy-MM-dd") Date date2,
                       @DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date3){
        System.out.println("yyyy/MM/dd : " + date);
        System.out.println("yyyy-MM-dd : " + date2);
        System.out.println("yyyy/MM/dd HH:mm:ss : " + date3);
        return "{'msg':'qdxorigin'}";
    }
}
  • 对于日期类型的参数,如果传入的参数类型是 “yyyy/MM/dd” 的,则无需进行类型指定,能够自动封装。
  • 除此之外的其他类型,都需要使用 @DateTimeFormat 注解设定日期时间型数据的格式。使用pattern 属性指定日期时间格式字符串。
    在这里插入图片描述
  • 所有的数据都能够准确接收。
    在这里插入图片描述
  • 修改一个小问题:上图中的 “yyyy/MM/ss" 应该改为”yyyy/MM/dd"。

五、响应

讲了这么久的请求问题,终于来到了响应问题。

1、响应页面

<!-- index.jsp页面 -->
<html>
<body>
<h2>Hello World!</h2>
<h2>index.jsp</h2>
<h2>qdxorigin</h2>
</body>
</html>
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/forPage")
    public String forPage(){
        System.out.println("forPage ...");
        return "index.jsp";
    }
}
  • 此处无需再添加 @ResponseBody 注解,因为返回的不再是字符串,而是需要被解析的页面。
  • 在浏览器中输入网址测试,成功实现页面的跳转。
    在这里插入图片描述

2、响应 JSON 数据

响应 POJO 类型数据
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/forUser")
    @ResponseBody
    public User forUser(){
        User user = new User();
        user.setName("Tom");
        user.setAge(35);
        return user;
    }
}
  • 发送请求时,无需传递参数。
    在这里插入图片描述
响应集合对象
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/forList")
    @ResponseBody
    public List<User> forList(){
        User user1 = new User();
        user1.setName("Tom");
        user1.setAge(35);

        User user2 = new User();
        user2.setName("Jerry");
        user2.setAge(22);
        ArrayList<User> users = new ArrayList<>();
        users.add(user1);
        users.add(user2);
        return users;
    }
}

在这里插入图片描述

👉 以上就是文章的全部内容啦,诸佬如果有任何建议都可以提哦。
👉 创作不易,如果觉得对您有帮助的话,欢迎关注✨点赞👍收藏📂哦。

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

准Java全栈开发工程师

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

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

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

打赏作者

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

抵扣说明:

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

余额充值