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

Request Response 基础篇

Request & Response

在之前的博客中,初最初见到Request和Response对象,是在Servlet的Service方法的参数中,之前隐性地介绍过Request的作用是获取请求数据。通过获取的数据来进行进一步的逻辑处理,然后通过对Response来进行数据响应。接下来一起学习下具体知识吧~

Request继承体系

请添加图片描述

Tomcat需要解析请求数据,封装为request对象,并且创建requestx对象传递到service方法中

Request获取请求数据

请求数据分为3部分:

  • 请求行:

    // GET/request-demo/req1?username=zhangsan HTTP/1.1
    String getMethod()		// 获取请求方式:GET
    String getContextPath():// 获取虚拟目录(项目访问路径 动态获取):/request-demo
    String Buffer getRequestURL(): // 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1
    String getRequestURI():	// 获取URI(统一资源标识符):/request-demo/req1
    String getQueryString():// 获取请求参数(GET方式):username:=zhangsan&password-=123
    
  • 请求头:

    // User-Agent:Mozilla/5.0 Chrome/91.0.4472.106  浏览器版本信息
    String getHeader(String name) //:根据请求头名称,获取值
    
  • 请求体:

    // Post情况
    // username=superbaby&password=123
    ServletInputStream getlnputStream()	// :获取字节输入流
    BufferedReader getReader()			// :获取字符输入流
    
Request通用方式获取请求参数

GET请求方式和POST请求方式区别主要在于获取请求参数的方式不一样,是否可以提供一种统一获取请求参数的方式,从而统一doGt和doPost方法内的代码?

请添加图片描述

通过上面的图片可以发现,请求数据可以通过拆分,得到具体的键值对,因此:

// GET 获取请求方式
String getQueryString()
// POST 获取请求方式
BufferedReader getReader()
// 自己去实现的统一获取请求方式
String method = this.getMethod();
//判断
if ("GET".equals(method)){//GET方式获取请求参数params = this.getQueryString();
}else if ("POST".equals(method)){//P0ST方式获取请求参数BufferedReader reader = this.getReader();params = reader.readLine();
}
// JAVA EE自带的通用方式
// Map<String,String[]> getParameterMap():获取所有参数Map集合
// String[] getParameterValues(String name):根据名称获取参数值(数组)
// String getParameter(String name):根据名称获取参数值(单个值)
// 使用通用方式获取请求参数后,屏蔽了GET和POST的请求方式代码的不同,则代码可以定义为如下格式:
//此过程中不需要判断是POST 还是 GET,这一步上面的通用方法会自己解决
@WebServlet("/reqDemo3")
public class RequestDemo3 extends HttpServlet {@overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)
}
@override
protected void doPost(HttpServletRequest req,HttpServletResponse resp){this.doGet(req,resp);
}
// 通用方式在IDEA中可以使用Servlet模板创建Servlet更高效
// 步骤:选择【包】,【右键】选择【New】选择倒数第四个【Servlet】
请求参数中文乱码处理
// 之前介绍过由于POST是通过获取字符流的方式来获取参数的,因此如果POST遇到中文字符乱码的问题,则:
request.setCharacterEncoding("UTF-8");//设置字符输入流的编码
// 而GET方式,由于在参数传递的过程中,首先会通过URL编码,然后到服务器以后再通过URL解码,但解码过程中采用的ISO-8859-1,这个是Tomcat默认的格式,因此通过修改流的方式无法改变,因此要通过:
// 1. 将URL编码的数据转换成字节数据
byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
// 2.将字节数组转为字符串
String s = new String(bytes,StandardCharsets.UTF_8);
// 该方式不仅可以解决GET的乱码问题,也可以解决POST的乱码问题
// 该问题再Tomcat 8.0以后,已将Get请求乱码问题解决,设置默认的编码方式为UTF-8

Request请求转发

一种在服务器内部的资源跳转方式。

请添加图片描述

  • 实现方式:

  • 请求转发资源间共享数据:使用Request对象

    • void setAttribute(String name,Object o):存储数据到request域中
    • Object getAttribute(String name):根据key,获取值
    • void removeAttribute(String name):根据key,删除该键值对
    //转发之前可以通过上面的方法添加数据
    req.setAttribute("msg","name")
    req.getRequestDispatcher("资源B路径").forward(req,resp); //req:请求对象 resp:响应对象
    
  • 请求转发特点:

    • 浏览器地址栏路径不发生变化
    • 只能转发到当前服务器的内部资源
    • 一次请求,可以在转发的资源间使用request共享数据

Response继承体系

请添加图片描述

Response设置响应数据功能介绍
响应数据分为3部分
  • 响应行

    HTTP/1.1 200 OK
    void setStatus(int sc)  //:设置响应状态码
    
  • 响应头

    Content-Type:text/html
    void setHeader(String name,.String value)  //:设置响应头键值对
    
  • 响应体

    <html><head>head><body></body></html>
    PrintWriter getWriter()					//:获取字符输出流
    ServletOutputStream getOutputStream()	//:获取字节输出流
    
Response完成重定向

重定向(Redirect):一种资源跳转方式,访问流程如下:

请添加图片描述

resp.setStatus(302);                       //resp 响应对象
resp.setHeader("location”,“资源B的路径");	//resp 响应对象
//简化方式完成重定向
response.sendRedirect("资源B的路径");

重定向特点:

  • 浏览器地址栏路径发生变化
  • 可以重定向到任意位置的资源(服务器内部、外部均可)
  • 两次请求,不能在多个资源使用request共享数据
路径问题

在上面的资源转发和重定向 路径中,时常会遇到需要使用到虚拟路径或不适用虚拟路径的问题,那么什么时候使用,什么时候不使用呢?

这需要明确路径是谁在使用

  • 浏览器使用:需要加虚拟目录(项目访问路径)
  • 服务端使用:不需要加虚拟目录
Response响应字符数据
  • 使用:

    • 通过Response对象获取字符输出流

      PrintWriter writer = resp.getWriter(); //resp 响应对象
      
    • 写数据

      writer.write("aaa");
      // 细节:流不需要关闭
      // 设置流的编码,同时设置了响应头
      response.setcontentType("text/html;charset=utf-8");
      
Response响应字节数据
  • 使用:

    • 通过Response对象获取字节输出流(字节数据:图片、音频、视频等)

      ServletOutputStream outputStream = resp.getOutputStream();
      
    • 写数据

      outputStream.write(字节数据);
      
  • 举例,向客户端传送一张图片:

    • 导入工具commons-io

      <!--先引入一个commons-io 依赖-->
      <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version>
      </dependency>
      
    • 实现逻辑代码:

      //1.读取文件
      FileInputStream fis = new FileInputStream("d://a.jpg");
      //2.获取response字节输出流
      ServletoutputStream os = response.getOutputStream();
      IOUtils.copy(fis,os);
      fis.close();
      

案例:用户登录

  • 流程说明:
    • 用户填写用户名密码,提交到LoginServlet
    • 在LoginServlet中使用MyBatisi查询数据库,验证用户名密码是否正确
    • 如果正确,响应“登录成功”,如果错误,响应“登录失败”
//这里仅给出逻辑代码,对于MyBatis和Maven的配置,以及相关Mapper文件、pojo类、映射文件的接口等代码见前面的文章
//1.接收用户名和密码
String username = request.getParameter(name:"username");
String password = request.getParameter(name:"password");
//2.调用MyBatis完成查询
//2.1获取SqlSessionFactory对象
String resource = "mybatis-config.xml";
Inputstream inputstream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.2获取SqlSession.对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//2.3获取Mapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//2.4调用方法
User user = userMapper.select(username,password);
//2.5释放资源
sqlSession.close();
//获取字符输出流,并设置content type
response.setcontentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
//3.判断user是否为null
if(user != null){//登陆成功writer.write(s:"登陆成功");
}else{//登陆失败writer.write(S:"登陆失败");
}

用户注册

  • 流程说明
    • 用户填写用户名、密码等信息,点击注册按钮,提交到RegisterServlet
    • 在RegisterServlet中使用MyBatis保存数据
    • 保存前,需要判断用户名是否已经存在:根据用户名查询数据库
//相较于上面,这里需要对数据库进行两次操作,一次是查询,一次是添加,内容见前面博客
//1.接收用户数据
String username = request.getParameter(name:"username");
String password = request.getParameter(name:"password");
/封装用户对象
User user = new User();
user.setUsername(username);
user.setPassword(password);
//2.调用mapper根据用户名查询用户对象
//2.1获取SqlSessionFactory对象
String resource = "mybatis-config.xml";
Inputstream inputstream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.2获取SqlSession.对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//2.3获取Mapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//2.4调用方法
User u = userMapper.selectByUsername(username);
//3.判断用户对象是否为null
if(u == null){// 用户名不存在,添加用户userMapper.add(user);// 提交事多sqlSession.commit();// 释放资源sqlSession.close();
}else{//用户名存在,给出提示信息response.setContentType("text/html;charset=utf-8");response.getWriter().write("用户名已存在");// 释放资源sqlSession.close();
}

案例代码优化

  • 问题:
    • 代码重复:建立工具类
    • SqlSessionFactory工厂只创建一次,不要重复创建,因为里面存在数据库连接池,特别浪费资源:静态代码块
//工具类代码:
public class SqlSessionFactoryutils{private static SqlSessionFactory sqlSessionFactory;static {// 静态代码块会随着类的加载而自动执行,且只执行一次try{String resource "mybatis-config.xml";Inputstream inputStream = Resources.getResourceAsstream(resource);sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}catch (IOException e){e.printstackTrace();}public static SqlSessionFactory getSqlSessionFactory(){return sqlSessionFactory;}
}
// 然后在上面2.1修改代码,调用静态方法,得到sqlSessionFactory对象即可
// 与sqlSessionFactory不同的是:sqlSession不能仅创建一次,因为多用户情况下,仅创建一次,对于用户体验来说 并不好

如果觉得文章对您有帮助,请帮忙点赞或者收藏,如果在文章中发现什么错误或不准确的地方,欢迎与我交流。

相关文章:

Request Response 基础篇

Request & Response 在之前的博客中&#xff0c;初最初见到Request和Response对象&#xff0c;是在Servlet的Service方法的参数中&#xff0c;之前隐性地介绍过Request的作用是获取请求数据。通过获取的数据来进行进一步的逻辑处理&#xff0c;然后通过对Response来进行数…...

数据爬虫是什么

数据爬虫是一种自动化程序&#xff0c;用于从互联网上收集数据。它通过模拟人类浏览器的行为&#xff0c;访问网页并提取所需的数据。数据爬虫通常使用网络爬虫框架或库来实现。 数据爬虫的工作流程通常包括以下几个步骤&#xff1a; 发起请求&#xff1a;爬虫发送HTTP请求到…...

Java注解与策略模式的奇妙结合:Autowired探秘

大家好&#xff0c;欢迎收听今天的播客节目&#xff01;我是你们的主持人&#xff0c;也是一位对软件开发充满热情的开发者。在今天的节目中&#xff0c;我们将探讨如何巧妙地结合注解与策略模式&#xff0c;创建一个灵活而强大的策略规则工厂。让我们带着好奇的心情一同深入研…...

Datax3.0+DataX-Web部署分布式可视化ETL系统

一、DataX 简介 DataX 是阿里云 DataWorks 数据集成的开源版本&#xff0c;主要就是用于实现数据间的离线同步。DataX 致力于实现包括关系型数据库&#xff08;MySQL、Oracle 等&#xff09;、HDFS、Hive、ODPS、HBase、FTP 等各种异构数据源&#xff08;即不同的数据库&#x…...

【Java 数据结构】排序

排序算法 1. 排序的概念及引用1.1 排序的概念1.2 常见的排序算法 2. 常见排序算法的实现2.1 插入排序2.1.1 直接插入排序2.1.2 希尔排序( 缩小增量排序 ) 2.2 选择排序2.2.1 直接选择排序2.2.2 堆排序 2.3 交换排序2.3.1冒泡排序2.3.2 快速排序2.3.3 快速排序非递归 2.4 归并排…...

Deepin如何开启与配置SSH实现无公网ip远程连接

文章目录 前言1. 开启SSH服务2. Deppin安装Cpolar3. 配置ssh公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 前言 Deepin操作系统是一个基于Debian的Linux操作系统&#xff0c;专注于使用者对日常办公、学习、生活和娱乐的操作体验的极致&#xff0…...

【Springcloud篇】学习笔记十(十七章):Sentinel实现熔断与限流——Hystrix升级

第十七章_Sentinel实现熔断与限流 1.Sentinel介绍 1.1是什么 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点&#xff0c;从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 用来代替Hystrix Sentinel 具有…...

【算法与数据结构】718、1143、LeetCode最长重复子数组 最长公共子序列

文章目录 一、718、最长重复子数组二、1143、最长公共子序列三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、718、最长重复子数组 思路分析&#xff1a; 第一步&#xff0c;动态数组的含义。 d p [ i ] [ j ] dp[i]…...

C# SSH.NET 长命令及时返回

在SSH中执行长时间的命令&#xff0c;SSH.NET及时在文本框中返回连续显示结果。 c# - Execute long time command in SSH.NET and display the results continuously in TextBox - Stack Overflow 博主管理了一个服务器集群&#xff0c;准备上自动巡检工具&#xff0c;测试在…...

Rust学习之Features

Rust学习之Features 一 什么是 Features二 默认 feature三 简单的features应用示例四 可选(optional)的依赖五 依赖的特性5.1 在依赖表中指定5.2 在features表中指定 六 命令行中特性控制七 特性统一路径八 其它8.1 相互排斥特性8.2 观察启用特性8.3 Feature resolver version …...

云计算基础(云计算概述)

目录 一、云计算概述 1.1 云计算的概念 1.1.1 云计算解决的问题 1.1.2 云计算的概念 1.1.3 云计算的组成 1.2 云计算主要特征 1.2.1 按需自助服务 1.2.2 泛在接入 1.2.3 资源池化 1.2.4 快速伸缩性 1.2.5 服务可度量 1.3 云计算服务模式 1.3.1 软件即服务(Softwar…...

【机器学习】科学库使用手册第2篇:机器学习任务和工作流程(已分享,附代码)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论人工智能相关知识。主要内容包括&#xff0c;了解机器学习定义以及应用场景&#xff0c;掌握机器学习基础环境的安装和使用&#xff0c;掌握利用常用的科学计算库对数据进行展示、分析&#xff0c;学会使用jupyter note…...

【React】前端项目引入阿里图标

【React】前端项目引入阿里图标 方式11、登录自己的iconfont-阿里巴巴矢量图标库&#xff0c;把需要的图标加入到自己的项目中去&#xff1b;2、加入并进入到项目中去选择Font class 并下载到本地3、得到的文件夹如下4. 把红框中的部分粘贴到自己的项目中&#xff08;public 文…...

Javascript入门:第三个知识点:javascript里的数据类型、运算符

数字类型 123 //整数 123.1 //浮点数 1.123e3 //科学计数法 -10 //负数 NaN //not a number Infinity //无限大 以上的类型在javascript里都是数字类型 字符串类型 在开始之前&#xff0c;我需要先说明白两个知识点&#xff1a; console.log()是啥&#xff1f; let 与 v…...

最新版国产会声会影2024新功能爆料

会声会影2024是一个视频编辑软件&#xff0c;具备以下功能&#xff1a; 会声会影2024安装包下载如下: https://wm.makeding.com/iclk/?zoneid55677 1. 视频剪辑&#xff1a;可以对视频进行剪辑、裁剪、拼接和分割操作&#xff0c;实现对视频片段的精确控制。 2. 音频编辑&…...

Pandas处理Excel文件的实用指南 - Python开发技巧XI

处理Excel文件是数据分析师日常工作中的常见任务之一。 幸运的是&#xff0c;Python的Pandas库提供了一套强大的工具&#xff0c;使得读取、处理和写入Excel文件变得既清晰又快捷。 在本篇博客中&#xff0c;我们将探讨如何使用Pandas的 read_excel 方法来读取Excel文件&#x…...

泰克示波器(TBS2000系列)触发功能使用讲解——边沿触发

# Trigger区域 触发区域用于对触发功能进行配置。示波器的触发功能用于采集&#xff08;Acquire&#xff09;那些在瞬间出现的信号&#xff0c;便于我们分析观察&#xff0c;此时可以当做逻辑分析仪使用。触发区域按钮包括&#xff1a;menu、Level\Force Trig三个。 目录 1.1 …...

C++学习Day01之C++对C语言增强和扩展

目录 一、程序及输出1.1 全局变量检测增强1.2 函数检测增强1.3 类型转换检测增强1.4 struct增强1.5 bool类型扩展1.6 三目运算符增强1.7 const增强1.7.1 全局Const对比1.7.2 局部Const对比1.7.3 Const变量初始化数组1.7.3 Const修饰变量的链接性 二、分析总结 一、程序及输出 …...

【文件上传WAF绕过】<?绕过、.htaccess木马、.php绕过

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…...

flutter如何实现省市区选择器

前言 当我们需要用户填写地址时&#xff0c;稳妥的做法是让用户通过“滚轮”来滑动选择省份&#xff0c;市&#xff0c;区&#xff0c;此文采用flutter的第三方库来实现这一功能&#xff0c;比调用高德地图api简单一些。 流程 选择库 这里我选择了一个最近更新且支持中国的…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

uniapp 小程序 学习(一)

利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 &#xff1a;开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置&#xff0c;将微信开发者工具放入到Hbuilder中&#xff0c; 打开后出现 如下 bug 解…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...