JavaWeb开发 —— 请求响应

news2025/1/18 7:25:51

目录

一、概述

二、请求

1.  postman工具

 2.  简单参数

3.  实体参数

4.  数组集合参数

 5.  日期参数

6.  JSON参数

7.  路径参数

三、响应

1.  @ResponseBody

2.  统一响应结果

3.  案例


一、概述

通过之前对 JavaWeb开发 —— Web入门 的学习,我们开发了一个很简单的入门程序。

我们运行启动类运行启动内嵌的Tomcat Web服务器之后,就可以打开浏览器,然后在浏览器地址栏通过访问路径访问到我们部署在Tomcat中的应用程序。Controller接收到请求之后并处理,处理完毕之后再给浏览器响应对应的结果。

客户端浏览器与服务器进行数据传输的时候,是基于HTTP协议。HTTP协议就规定了浏览器与服务器进行数据传输的规则。而我们之前编写的Controller 仅仅是一个简单的Java类,并没有实现任何的接口,也没用继承任何的类,那么这个程序不能被Tomcat识别不能够直接运行。

Tomcat虽然不识别我们编写的Controller程序,但是其识别JavaEE规范中的Servlet,因为Tomcat我们也称为Servlet容器。而我们基于SpringBoot开发的Web入门程序当中,SpringBoot底层给我们提供了一个非常核心的Servlet程序 —— DispatcherServlet,其就实现了Servlet规范当中的Servlet接口。


有了DispatcherServlet之后,前端浏览器发送的请求都会先经过DispatcherServlet,并将请求传给后面各个Controller程序,由Controller程序再对请求进行处理,处理完毕后再由Controller程序返回给DispatcherServlet,再响应给浏览器数据。因此我们也称DispatcherServlet为前端控制器。

① 那么我们如何从DispatcherServlet 中获取请求的数据呢? 

前端浏览器发送请求会携带HTTP的请求数据,而Web服务器就负责对这些请求数据进行解析,所以Tomcat就会接收到这些请求数据,并对请求数据进行解析,并且将解析后的所有信息最终封装到一个对象当中 —— HttpServletRequest(请求对象),接下来应用程序就可以从HttpServletRequest对象当中获取请求数据,然后再对数据进行处理,处理完毕之后Tomcat服务器就会根据HTTP协议响应数据格式给浏览器响应数据。

② Tomcat如何知道给浏览器响应什么数据呢?

在Servlet程序当中,我们可以借助另外一个对象来设置响应数据 —— HttpServletResponse(响应对象),通过这个对象就可以设置我们想要的数据,然后Tomcat根据我们在 HttpServletResponse中设置的响应信息来响应数据给浏览器。

 请求响应:

  • 请求(HttpServletRequest):获取请求数据
  • 响应(HttpServletResponse):设置响应数据
  • BS架构:Browser / Server,浏览器 / 服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。(维护方便 但 体验一般
  • CS架构:Client / Server,客户端 / 服务器架构模式。(开发、维护麻烦 但 体验不错

二、请求

1.  postman工具

Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。

作用:常用于进行接口测试

下载:postman下载与安装

 2.  简单参数

① 原始方式:在原始的web程序中,获取请求参数,需要通过HttpServletRequest对象手动获取。

//测试请求参数接收
@RestController
public class RequestController {
    //原始方式
    @RequestMapping("/simpleParam")
    public String simpleParam(HttpServletRequest request){
        //获取请求参数
        String name = request.getParameter("name");
        String ageStr = request.getParameter("age");

        int age = Integer.parseInt(ageStr);
        System.out.println(name+" : "+age);
        return "OK";
    }
}

② SpringBoot方式:

  • 参数名与形参变量名相同,定义形参即可接收参数。
  • 如果方法形参名称与请求参数名称不匹配,可以使用 @RequestParam 完成映射。
//基于SpringBoot方式
@RequestMapping("/simpleParam")
    public String simpleParam(String name,Integer age){
        System.out.println(name+" : "+age);
        return "OK";
    }

@RequestMapping("/simpleParam")
    public String simpleParam(@RequestParam(name = "name")String username,Integer age){
        System.out.println(username+" : "+age);
        return "OK";
    }

注意事项:@RequestParam 中的required属性默认为true,代表该请求参数必须传递,如果不传递将报错。如果该参数是可选的,可以将required属性设置为false。

3.  实体参数

① 简单实体对象:请求参数名与形参对象属性名相同,定义POJO接收即可。

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


//简单实体参数
    @RequestMapping("/simplePojo")
    public String simplePojo(User user){
        System.out.println(user);
        return "OK";
    }

② 复杂实体对象:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数。

public class User {
    private String name;
    private Integer age;
    private Address address;
}

public class Address{
    private String province;
    private String city;
}

//复杂实体参数
    @RequestMapping("/simplePojo")
    public String simplePojo(User user){
        System.out.println(user);
        return "OK";
    }

4.  数组集合参数

① 数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数。

//数组参数
    @RequestMapping("/arrayParam")
    public String arrayParam(String[] hobby){
        System.out.println(Arrays.toString(hobby));
        return "OK";
    }

② 集合参数:请求参数名与形参集合名称相同且请求参数为多个,@RequestParam 绑定参数关系。

//集合参数
    @RequestMapping("/listParam")
    public String listParam(@RequestParam List<String> hobby){
        System.out.println(hobby);
        return "OK";
    }

 5.  日期参数

日期参数:使用 @DateTimeFormat 注解完成日期参数格式转换

 //日期参数
    @RequestMapping("dataParam")
    public String dateParam(@DataTimeFormat(Pattern = "yyyy-MM-dd HH:mm;ss")LocalDateTime updateTime){
        System.out.println(updateTime);
        return "OK";
    }

6.  JSON参数

JSON参数:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数,需要使用 @RequestBody 标识。

public class User {
    private String name;
    private Integer age;
    private Address address;
}

public class Address{
    private String province;
    private String city;
}

//JSON参数
    @RequestMapping("/jsonParam")
    public String jsonParam(@RequestBody User user){
        System.out.println(user);
        return "OK";
    }

7.  路径参数

路径参数:通过请求URL直接传递参数,使用 {..} 来标识该路径参数,需要使用 @PathVariable 获取路径参数。

① 单个路径:

//路径参数
//单个路径
//路径{id}动态
@RequestMapping("/path/{id}")
   public String pathParam(@PathVariable Integer id){
        System.out.println(id);
        return "OK";
}

② 多个路径:

//路径参数
//多个路径
@RequestMapping("/path/{id}/{name}")
    public String pathParam2(@PathVariable Integer id,@PathVariable String name){
        System.out.println(id);
        System.out.println(name);
        return "OK";
    }

三、响应

1.  @ResponseBody

① 类型:方法注解、类注解。

② 位置:Controller方法上 / 类上。

③ 作用:将方法返回值直接响应,如果返回值类型是 实体对象 / 集合,将会转换为JSON格式响应。

④ 说明:@RestController = @Controller + @ResponseBody ;

@RestController
public class ResponseController {
    @RequestMapping("/hello")
    public String hello(){
        System.out.println("Hello World");
        return "Hello World";
    }

    @RequestMapping("/getAddr")
    public Address getAddr(){
        Address addr = new Address();
        addr.setProvince("北京");
        addr.setCity("北京");
        return addr;
    }

    @RequestMapping("listAddr")
    public List<Address> listAddr(){
        List<Address> list = new ArrayList<>();

        Address addr1 = new Address();
        addr1.setProvince("北京");
        addr1.setCity("北京");

        Address addr2 = new Address();
        addr2.setProvince("山东");
        addr2.setCity("青岛");

        list.add(addr1);
        list.add(addr2);

        return list;
    }
}

每一个方法其实都是一个功能接口,而之前我们学习的项目开发中的开发文档就是用来描述功能接口的请求路径、请求参数、响应数据各是什么。

在上面的代码经过@ResponseBody处理返回给前端数据分别为字符串、JSON格式的数据和数组,每一个接口返回的数据很随意,没有规范而言。但是在实际开发中,我们所涉及的功能接口种类很多,没有统一的规范,前端人员发送请求所访问到我们开发的接口,我们最终返回的数据各式各样,前端人员解析不方便,整个项目不便管理,难以维护。

这里就需要:

2.  统一响应结果

public class Result {
  //响应码,1代表成功; 0代表失败
  private Integer code;
  //提示信息
  private String msg;
  //返回的数据
  private Object data;
}

更改上述代码格式:

@RestController
public class ResponseController {
    @RequestMapping("/hello")
    public Result hello(){
        System.out.println("Hello World");
        //return new Result(1,"success","Hello World");
        return Result.success("Hello World");
    }

    @RequestMapping("/getAddr")
    public Result getAddr(){
        Address addr = new Address();
        addr.setProvince("北京");
        addr.setCity("北京");
        return Result.success(addr);
    }

    @RequestMapping("listAddr")
    public Result listAddr(){
        List<Address> list = new ArrayList<>();

        Address addr1 = new Address();
        addr1.setProvince("北京");
        addr1.setCity("北京");

        Address addr2 = new Address();
        addr2.setProvince("山东");
        addr2.setCity("青岛");

        list.add(addr1);
        list.add(addr2);

        return Result.success(list);
    }
}

//统一响应结果封装类
public class Result {
    private Integer code; // 1 成功 0 失败
    private String msg;  //提示信息
    private Object data;  //数据 data

    public Result(){}
    public  Result(Integer code,String msg,Object data){
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static Result success(Object data){
        return new Result(1,"success",data);
    }
    public  static Result success(){
        return new Result(1,"success",null);
    }
    public static Result error(String msg){
        return new Result(0,msg,null);
    }

    @Override
    public String toString() {
        return "Result{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }
}

3.  案例

需求:获取员工数据,返回统一响应格式,在页面渲染展示。

  • 加载并解析emp.xml文件中的数据,完成数据处理,并在页面展示。

① 操作步骤:

  • 在pom.xml文件中引入dom4j的依赖,用于解析XML文件。
  • 引入资料中提供的解析XML的工具类XMLParserUtils.对应的实体类Emp. XML文件emp.xml。
  • 引入资料中提供的静态页面文件,放在resources 下的static目录下。
  • 编写Controller程序,处理请求,响应数据。
  • 详细数据见资料分享 。

Springboot项目的静态资源(html,css,js等前端资源)默认存放目录为:classpath:/static 、 classpath:/public、classpath:/resources。

② 代码实现:

//EmpController
@RestController
public class EmpController {
    @RequestMapping("/listEmp")
    public Result list(){
        //1.加载并解析emp.xml
        //String file = "F:\\idea\\idea_workplace\\springboot-web-req-resp\\src\\main\\resources\emp.xml";
        //动态获取
        String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
        System.out.println(file);
        List<Emp> empList= XmlParserUtils.parse(file, Emp.class);
        //2.数据进行转换处理 -gender job
        empList.stream().forEach(emp ->{
            String gender = emp.getGender();
          if("1".equals(gender)){
              emp.setGender("男");
          }else if ("2".equals(gender)){
              emp.setGender("女");
          }

          String job = emp.getJob();
            if("1".equals(job)){
                emp.setJob("讲师");
            }else if ("2".equals(job)){
                emp.setJob("班主任");
            }else if ("3".equals(job)){
                emp.setJob("就业指导");
            }
        });

        //3.响应数据
        return Result.success(empList);
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

失眠一月码出527页文档,详解SpringCloud微服务和分布式系统实践

所谓的分布式系统&#xff0c;就是一组计算机为了共同完成业务功能通过网络协作的多节点系统。分布式系统本身也有一系列需要解决的问题&#xff0c;包括多个计算机节点的路由选择、各个服务实例的管理、节点监控、节点之间的协作和数据一致性等&#xff0c;当然还有网络故障、…

lamp 架构的搭建

php 解释动态页面 php来连接数据库 mysql 页面信息和端口信息 存放数据 apache 前端web服务器&#xff0c;展现页面 源码编译安装这三个服务 配置下载apache: systemctl stop firewalld 关闭安全机制&#xff0c;防火墙 可以一条命令:systemctl is-enabled firewalld 和 s…

【推荐系统】model 落地(样本/特征/预测服务)

兜率宫小道童的个人空间-兜率宫小道童个人主页-哔哩哔哩视频&#xff08;如下是该视频课系列的笔记&#xff09; 1-深度学习在搜索、广告、推荐系统中的应用-业务问题建模_哔哩哔哩_bilibili 其他章节 目录 二、深度学习落地 模型训练服务流程 1-样本生成-标签拼接 1-样本…

OJ练习第73题——解数独

解数独 力扣链接&#xff1a;37. 解数独 题目描述 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一…

MySQL-中间件mycat(二)

目录 &#x1f341;部署主从复制 &#x1f341;mycat读写分离 &#x1f342;修改配置文件 &#x1f342;设置balance与writeType &#x1f342;设置switchType与slaveThreshold &#x1f342;启动程序 &#x1f342;验证读写分离 &#x1f341;垂直拆分-分库 &#x1f342;实现…

【从零开始学Skynet】基础篇(九):调试控制台服务

Skynet自带了一个调试控制台服务debug_console&#xff0c;启动它之后&#xff0c;可以查看节点的内部状态。 1、启用调试控制台 &#xff08;1&#xff09;在skynet/examples目录下新建main_console.lua文件&#xff0c;代码如下所示&#xff1a; local skynet require &quo…

【Python_Scrapy学习笔记(二)】创建Scrapy爬虫项目

创建Scrapy爬虫项目 前言 本文主要介绍如何创建并运行 Scrapy 爬虫项目。 正文 1、创建 Scrapy 框架 Scrapy 框架提供了 scrapy 命令用来建立 Scrapy 工程&#xff0c;在终端 terminal 中输入以下命令&#xff1a; scrapy startproject 自定义的项目名称创建好爬虫项目文件…

2023年超实用的27个VSCode插件推荐

Visual Studio Code&#xff0c;或者称作VS Code&#xff0c;是一个广为人知且评价很高的代码编辑器&#xff0c;它有许多特性和扩展功能&#xff0c;以增强开发体验。使用VS Code的主要好处之一是它的灵活性&#xff0c;允许开发人员根据自己的特定需求进行自定义。此外&#…

02-app漏洞发现

漏洞发现-APP应用之漏洞探针类型利用修复 一、思维导图&#xff1a; 思路说明&#xff1a; apk反编译提取URL或抓包获取url&#xff0c;进行web应用测试&#xff0c;如不存在或走其他协议的情况下&#xff0c;需采用网络接口抓包进行数据获取&#xff0c;转至其他协议安全测试…

【jvm系列-05】精通运行时数据区共享区域---方法区

JVM系列整体栏目 内容链接地址【一】初识虚拟机与java虚拟机https://blog.csdn.net/zhenghuishengq/article/details/129544460【二】jvm的类加载子系统以及jclasslib的基本使用https://blog.csdn.net/zhenghuishengq/article/details/129610963【三】运行时私有区域之虚拟机栈…

Redis 6.0的多线程是如何工作的

来了解下 6.0 版本中新出的多线程特性。 1、多线程处理网络IO&#xff0c;单线程执行命令 Redis 一直被大家熟知的就是它的单线程架构&#xff0c;虽然有些命令操作可以用后台线程或子进程执行&#xff08;比如数据删除、快照生成、AOF 重写&#xff09;&#xff0c;但是&…

freeswitch带媒体压力测试方案

概述 原本的计划是使用sipp完成带媒体压力测试&#xff0c;但是实际测试过程中发现sipp的媒体处理功能有问题&#xff08;也有可能是我使用的姿势不对&#xff09;。 sipp在带媒体的情况下&#xff08;600路并发开始&#xff09;&#xff0c;出现大量的不响应和响应延迟&…

请求响应-响应

前面已经说了我们重点关注的就是XXXcontroller类 进行请求接收 和响应 接收参数那些我们在请求部分讲过了 现在我们来处理响应部分 响应 设置响应数据 可以发现其实我们之前都是设置过的 比如那个Hello World 浏览器都接收到了且在浏览器上进行了输出 这里的是返回值作为这个…

Direct3D 12——纹理——纹理

纹理不同于缓冲区资源&#xff0c;因为缓冲区资源仅存储数据数组&#xff0c;而纹理却可以具有多个mipmap层级(后 文有介绍)&#xff0c;GPU会基于这个层级进行相应的特殊操作&#xff0c;例如运用过滤器以及多重采样。支持这些特殊 的操作纹理资源都被限定为一些特定的数据格式…

7 个最好的 Word 转 PDF 转换器

如果您使用 Word 文件&#xff0c;您可能在某个时候遇到过将 Word 文件转换为 PDF 的紧迫问题。PDF 文件有很多优点。它们通常更紧凑&#xff0c;无论您在哪里打开它们看起来都一样。PDF 还允许您共享文档&#xff0c;而不必冒有人更改内容的风险。那么如何将 Word 文档转换为 …

小白学网络安全要学些什么?

一.网络安全学些什么呢&#xff1f; 虽然网上已经有非常多的学习路线了&#xff0c;但是仍然有很多零基础的小白还是不懂网络安全到底应该要怎么去学习&#xff0c;我也经常会在后台收到这样的问题“我想学网络安全&#xff0c;需要先学编程语言吗&#xff1f;”、“学渗透就业…

【python零碎】

1. 拼接字符中&#xff0c;插入变量 >>> shepherd "Mary" >>> age 32 >>> stuff_in_string "Shepherd {} is {} years old.".format(shepherd, age) >>> print(stuff_in_string) Shepherd Mary is 32 years old. &…

HIT-CSAPP 第五章 面向程序的优化方法(1)

考纲: 1.面向程序性能的优化 面向编译器的程序优化方法:减少过程调用、减少内存引用、指令并行等方法等方法。面向流水线、超标量、向量CPU的程序优化方法。 2.存储器的层次结构 优化编译器的能力和局限性 内存别名使用妨碍函数优化 void twiddle1(long *xp, long *yp){ //…

ERTEC200P-2 PROFINET设备完全开发手册(4-1)

ERTEC200P-2作为应用处理器&#xff0c;既可以单独使用&#xff0c;通过GPIO扩展实现基本的IO功能。也可以配合外部主机&#xff08;例如单片机&#xff09;实现更复杂的应用。ERTEC200P-2与外部主机接口的示意图如下。常用的接口包括UART&#xff0c;SPI&#xff0c;XHIF接口。…

MSI: 基于多元同步索引的SSVEP频率识别算法

MSI: 基于多元同步索引的SSVEP频率识别算法1.算法背景2.算法原理3.Python代码实现1.算法背景 脑机接口&#xff08;Brain-Computer Interface, BCI&#xff09;因其在神经工程与神经科学中的广泛应用价值而备受研究者们的关注。BCI系统可以在人类或动物被试与外部设备之间提供…