SpringMVC(二)【请求与响应】

0、测试环境

我们简化开发,创建一个简单的环境(因为没有其它包比如 service、dao,所以这里不用 Spring 容器,只用 SpringMVC 容器):

Servelet 容器配置:

package com.lyh.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 * Servlet 容器配置类
 */
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

注意有了这个就不需要 web.xml 了,不然启动 tomcat 会报错!!! 

SpringMVC 配置:

package com.lyh.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.lyh.controller") // 扫描
public class SpringMvcConfig {

}

UserController:

package com.lyh.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class UserController {

    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        return "{'module':'user save'}";
    }

    @RequestMapping("/delete")
    @ResponseBody
    public String delete(){
        return "{'module':'user delete'}";
    }
}

BookController:

package com.lyh.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class BookController {

    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        return "{'module':'book save'}";
    }

}

1、请求映射路径

        在上面的环境中,我们可看到,对于不同 controller 类中存在有相同映射路径(/save),这是我们开发中经常会遇到的问题,也就是不同开发人员设置了相同的映射路径该怎么办?

解决办法:设置模块名作为请求路径前缀

        这样,我们就解决了不同业务模块请求路径冲突的问题了,但是我们发现,如果这个每个业务模块下面的方法前面都加一个( /module )是不是太冗余了。所以,SpringMVC 还能帮我们继续简化开发( 直接在 Controller 类上面定义前缀):

这里我们就可以总结一下注解 @RequestMapping 的用法了:

名称类型位置作用
@RequestMapping类注解 / 方法注解控制器类 / 控制器方法上面设置当前控制器方法请求访问路径,如果加在控制器类上则代表统一访问路径前缀

2、请求方式

2.1、Get 请求

        Get 请求非常简单,我们只需要在访问路径后面跟上一个 ?参数名=参数值 即可,如果是多个参数,直接 ?参数名1=参数值1&参数名2=参数值2  即可。

注意:我们之前在学习 Servlet 的时候,Get 和 Post 请求是区分的,但是在 SpringMVC 中,我们并不需要在方法中分开处理不同类型的请求。

2.2、Post 请求

这里用 Postman 来进行模拟发送 Post 请求:

注意Post 请求发表单的时候,我们请求体中用的应该是 x-www-from-urlencoded

from-date 区别于 x-www-from-urlencoded 不同的是,它不仅可以发表单,还可以发送文件:

2.3、Post 请求中文乱码问题

        中文乱码的问题我们之前在学习 Servlet 的时候是通过过滤器来实现的,在 SpringMVC 这里是一样的。我们不需要在负责响应的方法里去写,而是直接去 Servlet 容器配置类里重写一下 getServletFilters 方法即可:

注意这里的过滤器只对 Post 请求有效,Get 请求设置过滤器要复杂一些

2.4、请求参数

参数种类:

  • 普通参数
  • POJO
  • 嵌套POJO
  • 数组
  • 集合

2.4.1、客户端和服务端参数名不一致问题

        也就是客户端请求参数和我们服务端 Controller 类下面的方法形参名不一致,这种问题很常见,解决办法也很简单,直接通过 @RequestParam("参数名")  把客户端的参数名和我们服务端方法的形参绑定在一起:

但是需要注意的是设置了这个注解就相当于指定了客户端的参数名,也就是说客户端要想再用 name 来给服务端传递参数就不行了

2.4.2、POJO 类型参数

我们先创建一个包 domain 并创建一个简单的 User 类:

package com.lyh.domain;

public class User {

    private String name;
    private int age;

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

    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;
    }
}

在 Controller 中添加一个用 Pojo 作为参数传递的方法:

@RequestMapping("/saveByPojo")
@ResponseBody
public String saveByPojo(User user){
    System.out.println("普通参数传递 name = " + user.getName() + " , age = " + user.getAge());
    return "{'module':'user save'}";
}

注意在Spring MVC中,不允许一个Controller下的不同方法具有相同的映射(我原本想着方法重载的,但是发现不行)。

        运行结果和之前的普通参数传递是一致的,而我们并没有做额外的操作,只是简单的修改了参数类型,SpringMVC 会帮我们自动通过对象的参数名去找到我们的方法形参。所以,这就要求我们 POJO 的参数名必须和方法形参名一致!

2.4.3、嵌套 POJO

嵌套 POJO 也就是一个对象的参数是另一个对象。

我们再创建一个 Address 类(两个属性:province 和 city,这里省略代码)并添加给 User 类。

2.4.4、数组类型

同样非常简单,在控制器类下面添加一个方法: 

发送 Post 请求:

这样,我们就通过多个相同参数名的方式实现了数组的传递。

2.4.5、集合类型

我们试着用和数组一样的方式去给集合传递参数:
在控制器类下创建一个方法:

Post 请求测试: 

运行结果:

        可以看到,服务器报了一个构造器的错误,说明服务器在尝试调用 List 的构造方法,但是我们知道 List 是一个接口,根本没有构造器。这也说明,我们上一节在用 Pojo 作为参数传递的时候,SpringMVC 底层其实是会调用形参的那个 Pojo 对象的构造器,然后通过 set 方法进行属性注入。

        解决的办法也很简单,直接通过@RequestParam 注解把我们的请求参数当做集合的元素传递给集合(如果形参前面有 @RequestParam 注解,SpringMVC 会自动识别,而不会把它当做 Pojo 通过构造器创建空对象,然后通过 set 注入属性):

运行结果:

这样就没问题了。

2.5、JSON 传参

我们实际开发用到 JSON 的情况会很多很多,所以这里需要重点学习 JSON 的传参方法。

首先我们需要导入 json 转换格式的依赖,方便之后把不同的数据类型转为 json:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.0</version>
</dependency>

还需要注意的是,使用 Postman 发送 json 格式的数据需要使用:

2.5.1、json 数组

1、给SpringMVC配置类添加注解 @EnablewebMvc

我们需要把 json 转为对象,必须给控制器类添加这个注解:

@Configuration
@ComponentScan("com.lyh.controller") // 扫描
@EnableWebMvc     // 开启 json 转对象的功能(这只是这个注解的功能之一)
public class SpringMvcConfig {

}
名称类型位置作用
@EnableWebMvc配置类注解SpringMVC配置类上方开启SpringMVC多项辅助功能(比如这里的json格式自动转换)
2、给服务端方法形参前添加注解 @RequestBody

        区别于之前我们同查询参数给 List 集合传递元素使用的注解 @RequestParam:

  • @RequestBody 主要用于处理请求体中的数据,比如这里传递 json 数据用的就是 http 请求体中的 raw 来传递的。
  • @RequestParam 主要用于处理查询参数中的数据。

什么是查询参数?

        查询参数(Query Parameters)是在HTTP请求的URL中用于传递附加信息的键值对。它们通常出现在URL的“?”之后,并以“&”符号分隔多个参数。

名称类型位置作用
@RequestBody形参注解SpringMVC控制器方法形参定义前面将请求体中的数据参数传递给控制器方法形参
    @RequestMapping("/listParamForJson")
    @ResponseBody
    public String listParamForJson(@RequestBody List<String> likes){
        System.out.println("json数据传递"+likes.toString());
        return "{'module':'list common for json param'}";
    }

 发送测试:  

运行结果:

2.5.2、json 对象

    @RequestMapping("/pojoParamForJson")
    @ResponseBody
    public String pojoParamForJson(@RequestBody User user){
        System.out.println("json对象传递"+user.toString());
        return "{'module':'pojo for json param'}";
    }

2.5.3、json 对象数组

 这里同样需要对形参添加一个注解 @RequestBody 来把

@RequestMapping("/listPojoParamForJson")
@ResponseBody
public String listPojoParamForJson(@RequestBody List<User> users){
    System.out.println("json对象数组传递");
    for (User user : users)
        System.out.println(user.toString());
    return "{'module':'list pojo for json param'}";
}

        对于 json 对象数组数据的发送,Postman 会自动帮我们设置 Content-type 格式为 application/json:

测试结果:

2.6、日期类型参数传递

常见的日类型格式:

  • 2024-04-14
  • 2024/04/14(这种格式 SpringMVC 可以直接处理)
  • 04/14/2024 

对于另外两种类型的日期格式,SpringMVC 要求通过 @DateTimeFormat  注解的 pattern 属性来指定日期的格式:

    @RequestMapping("/dateParam")
    @ResponseBody
    public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date date){
        System.out.println("日期类型参数传递" + date.toString());
        return "{'module':'date param'}";
    }

测试: 

运行结果: 

2.7、类型转换器 

        上面的日期格式转换其实也是依赖于上面我们在 SpringMVC 配置类上开启的注解:@EnableWebMvc

        而这些所有的格式转换全部依赖于底层的 Converter 接口:

        这个接口提供了大量的数据格式转换,其中一部分数据转换是默认开启的,但是大部分是不默认开启的,所以一定要记得通过注解 @EnableWebMvc 来开启类型转换!

3、响应

3.1、响应界面

在 webapp 下创建一个文件 index.jsp

在控制器类中设置响应方法并返回响应页面的路径:

@Controller
public class BookController {

    @RequestMapping("/index")
    public String jumpToIndex(){
        return "index.jsp";
    }
}

注意:这里我把 BookController 上面的路径前缀(/book)注解 @RequestMapping 给去掉了,不然到时候会尝试访问 /book/index.jsp 而不是 /index.jsp,会报错。

3.2、响应文本

响应文本的时候为了避免 SpringMVC 把我们的响应文本解读为资源路径需要加一个注解:@ResponseBody 

@RequestMapping("/text")
@ResponseBody
public String reposeText(){
    return "Hello Spring";
}

运行结果: 

 

其实响应文本的本质还是返回一个页面:

    @RequestMapping("/text")
    @ResponseBody
    public String reposeText(){
        return "<h1>Hello Spring</h1>";
    }

测试结果: 

 

3.3、响应 json 对象

        响应 json 对象很简单,直接返回一个对象即可,我们之前导入的依赖 jackson 会自动帮我们把 Java 对象转为 json: 

    @RequestMapping("/jsonPojo")
    @ResponseBody
    public User reposeJsonPojo(){
        return new User("谢永强",25);
    }

测试结果: 

3.4、响应 json 对象集合

同样很简单,和响应对象一样,只不过是把对象放进了集合。同样,一定要导入 Jackson 依赖。

    @RequestMapping("/jsonList")
    @ResponseBody
    public List<User> reposeJsonList(){
        List<User> list = new ArrayList<User>();
        list.add(new User("谢永强", 25));
        list.add(new User("王小蒙", 25));
        return list;
    }

测试结果: 

名称类型位置作用
@ResponseBody方法注解控制器方法上方将当前控制器方法返回值违响应体

        如果该控制器方法返回值是 String 类型的文本,@ResponseBody 会把它转为响应体而不是把该文本当做资源路径;如果是对象类型,则把它转为我们浏览器可识别的数据类型,比如把 Java 对象转为 json。

3.5、类型转换器 HttpMessageConverter 

        这里的转换用的是并不是我们前面说的 Converter 接口,而是 HttpMessageConverter 接口,这个接口有一个实现类叫做 MappingJackson2HttpMessageConverter ,所以只要我们导入了 Jackson 包,它就可以帮我们把对象转为 json 格式。

        这也是我之前疑惑的地方:为什么不用 alibaba 的 fastjson 呢,原来是因为人家 SpringMVC 底层用的是 Jackson。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/553314.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jmeter及PTS压测介绍和使用

一、常用压测工具&#xff1a; loadrunner apache ab&#xff08;单接口压测最方便&#xff09; jmeter 阿里云PTS&#xff08;原生上传jmeter脚本进行压测&#xff09; 二、jmeter可以压测不同的协议和应用 web http https jdbc for database TCP 三、使用场景及优点 1、功能…

飞行机器人专栏(十四)-- Kinect DK 人体骨骼点运动提取方法

系列文章目录 Ubuntu 18.04/20.04 CV环境配置&#xff08;下&#xff09;--手势识别TRTposeKinect DK人体骨骼识别_ubuntu kinect骨骼测试-CSDN博客文章浏览阅读1.3k次。trt_pose_ros kinect实现手势识别和人体骨骼识别&#xff0c;用于机器人运动控制参考_ubuntu kinect骨骼测…

SpringCloud(一)

微服务框架 一、分布式架构 分布式架构︰根据业务功能对系统进行拆分&#xff0c;每个业务模块作为独立项目开发&#xff0c;称为一个服务。 优点: 降低服务耦合有利于服务升级拓展 微服务是一种经过良好架构设计的分布式架构方案&#xff0c;微服务架构特征: 单一职责:微…

【函数式接口使用✈️✈️】通过具体的例子实现函数结合策略模式的使用

目录 前言 一、核心函数式接口 1. Consumer 2. Supplier 3. Function,> 二、场景模拟 1.面向对象设计 2. 策略接口实现&#xff08;以 Function 接口作为策略&#xff09; 三、对比 前言 在 Java 8 中引入了Stream API 新特性&#xff0c;这使得函数式编程风格进…

数据库工具解析之 OceanBase 数据库导出工具

背景 大多数的数据库都配备了自己研发的导入导出工具&#xff0c;对于不同的使用者来说&#xff0c;这些工具能够发挥不一样的作用。例如&#xff1a;DBA可以使用导数工具进行逻辑备份恢复&#xff0c;开发者可以使用导数工具完成系统间的数据交换。这篇文章主要是为OceanBase…

编曲知识20:人声和声处理 分轨导出 总线处理

和声处理 和声 声像注意不要和主旋律重叠 各个效果器的处理幅度可以更大 呼吸音可直接去掉 尽量不要和主旋律共用一个混响延迟轨 注意音量、注意主次 和声拓展-模拟合唱 录制两轨同八度的主旋律或低八度高八度的主旋律 声像左右分配 音量拉低 将各个合唱轨进行失真处理 …

【Pytorch】VSCode实用技巧 - 默认终端修改为conda activate pytorch

VScode修改配置使得启动终端为conda环境 VScode跑项目&#xff0c;在启动pytorch项目时往往会有千奇百怪的问题&#xff0c;最常见的就是显示“conda activate pytorch”后会要求“conda init”&#xff0c;但输入后实际上也不行&#xff0c;这是因为VSCode默认终端为 Powersh…

网站模板-慈善捐赠基金会网站模板 Bootstrap4 html

目录 一.前言 二.预览 三.下载链接 一.前言 这是一个慈善网站的页面。页面包含了导航栏、横幅部分、关于、使命、新闻、活动、捐赠和页脚等不同的部分。该网站还包含了一些CSS样式和JavaScript脚本来实现交互和样式效果。 这个网站的具体结构如下&#xff1a; 导航栏部分&a…

kafka---topic详解

一、分区与高可用 在Kafka中,事件(events 事件即消息)是以topic的形式进行组织的;同时topic是分区(partitioned)的,这意味着一个topic分布在Kafka broker上的多个“存储桶”(buckets)上。这种数据的分布式放置对于可伸缩性非常重要,因为它允许客户端应用程序同时从多个…

第十三章 使用深度和法线纹理

获取深度和法线纹理 背后的原理 深度纹理是一张渲染纹理,它里面存储的像素值不是颜色,而是一个高精度的深度值。深度值范围是[0, 1],非线性分布的。这些深度值来自于顶点变换后得到的归一化的设备坐标(NDC)。一个模型想要被绘制在屏幕上,需要把它的顶点从模型空间变换到齐…

OpenCV从入门到精通实战(三)——全景图像拼接

全景图像拼接实现 定义 Stitcher 的类&#xff0c;用于实现两张图片的拼接。使用的技术是基于 SIFT 特征点检测与匹配&#xff0c;以及利用视角变换矩阵来对齐和拼接图像。 import numpy as np import cv2class Stitcher:#拼接函数def stitch(self, images, ratio0.75, repro…

云手机助力舆情监测,智慧引领信息时代

随着信息时代的到来&#xff0c;舆情监测已成为政府、企业、高校、金融机构等各行业的必备利器。在这个信息爆炸的时代&#xff0c;如何及时准确地感知民意、把握市场动态&#xff0c;已成为各界迫切需要解决的问题。而云手机作为信息时代的新生力量&#xff0c;在舆情监测方面…

C++ UML 类图介绍与设计

1 类图概述 UML(Unified Modeling Language)&#xff0c;即统一建模语言&#xff0c;是用来设计软件的可视化建模语言。它的特点是简单、统一、图形化、能表达软件设计中的动态与静态信息。UML从目标系统的不同角度出发&#xff0c;定义了用例图、类图、对象图、状态图、活动图…

PostgreSQL的学习心得和知识总结(一百三十八)|深入理解PostgreSQL数据库之Protocol message构造和解析逻辑

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

牛客 NC205 跳跃游戏(三)【中等 贪心 Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/14abdfaf0ec4419cbc722decc709938b 思路 参考答案Java import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可*** …

带缓存的输入输出流(I/O)

文章目录 前言一、带缓冲的输入输出流是什么&#xff1f;二、使用方法 1.BufferedInputStream与BufferedOutputStream类2.BufferedReader与BufferedWriter类总结 前言 输入输出流可以视为&#xff0c;从A点把货物搬运至B点。那么带缓冲的意思可以视为用货车把A点的货物搬运至B点…

代码随想录算法训练营DAY28(记录)|C++回溯算法Part.5|491.递增子序列、46.全排列、47.全排列II

文章目录 491.递增子序列思路伪代码CPP代码优化代码 46.全排列思路伪代码CPP代码 47.全排列IICPP代码 491.递增子序列 力扣题目链接 文章链接&#xff1a;491.递增子序列 视频连接&#xff1a;回溯算法精讲&#xff0c;树层去重与树枝去重 | LeetCode&#xff1a;491.递增子序列…

安装GPT 学术优化 (GPT Academic)@FreeBSD

GPT 学术优化 (GPT Academic)是一个非常棒的项目 可以帮助我们完成中科院的一些日常工作。 官网&#xff1a;GitHub - binary-husky/gpt_academic: 为GPT/GLM等LLM大语言模型提供实用化交互接口&#xff0c;特别优化论文阅读/润色/写作体验&#xff0c;模块化设计&#xff0c;…

win2022服务器apache配置https(ssl)真实环境实验(避坑之作)不依赖宝塔小皮等集成环境

本次实验背景&#xff1a; 完全参考官方 https://cloud.tencent.com/document/product/400/4143 文档流程&#xff0c;没有搞定&#xff0c;于是写下避坑之作。 服务器&#xff1a;腾讯云轻量应用服务器 操作系统&#xff1a; Windows Server 2022 DataCenter 64bit CN apache…

51-41 Stable Video Diffusion,高质量视频生成新时代

23年11月&#xff0c;Stability AI公司公开了稳定视频扩散模型Stable Video Diffusion(SVD)的代码和权重&#xff0c;视频生成迎来了新时代。SVD是一种潜在扩散模型&#xff0c;支持文本生成视频、图像生成视频以及物体多视角3D合成。从工程角度来看&#xff0c;本文主要提出了…
最新文章