Request Response 基础篇

news2024/11/25 12:47:20

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 {
    @override
	protected 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不能仅创建一次,因为多用户情况下,仅创建一次,对于用户体验来说 并不好

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

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

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

相关文章

隧道穿透:内网探测协议出网

目录 1、TCP/UDP 使用nc探测 使用Telnet探测 使用UDP探测 2、HTTP/HTTPS Windows &#xff08;1&#xff09;Bitsadmin &#xff08;2&#xff09;Certuil Linux &#xff08;1&#xff09;Curl &#xff08;2&#xff09;Wget 3、ICMP Windows &#xff08;1&am…

认识 SYN Flood 攻击

文章目录 1.什么是 SYN Flood 攻击&#xff1f;2.半连接与全连接队列3.如何防范 SYN Flood 攻击&#xff1f;参考文献 1.什么是 SYN Flood 攻击&#xff1f; SYN Flood 是互联网上最原始、最经典的 DDoS&#xff08;Distributed Denial of Service&#xff09;攻击之一。 SYN…

知识图谱嵌入学习在推理方法中的应用与挑战

目录 前言1 关系推理的嵌入模型1.1 嵌入模型介绍1.2 模型的差异1.3 嵌入模型的发展趋势 2 符号推理与向量推理3 嵌入模型的多样性4 强化学习与挑战5 元关系学习结论 前言 在人工智能领域&#xff0c;推理一直是关键任务之一。然而&#xff0c;传统的符号推理受限于人工定义&am…

创建与删除数据库(四)

创建与删除数据库&#xff08;四&#xff09; 一、创建数据库 1.1 使用DDL语句创建数据库 CREATE DATABASE 数据库名 DEFAULT CHARACTER 示例&#xff1a; 创建一个test 的数据库&#xff0c;并查看该数据库&#xff0c;以及该数据库的编码。 创建数据库&#xff1a; cre…

Unity中开发程序打包发布

添加ESC脚本 使用Unity打包发布的过程中&#xff0c;考虑到打开的程序会处于全屏界面&#xff0c;而此时我们又会有退出全屏的需求&#xff0c;因此需要添加ESC脚本&#xff0c;当我们单击ESC脚本的过程中&#xff0c;退出全屏模式。 在Assets/Scenes下&#xff0c;创建esc.cs…

深度学习的新前沿:突破、应用与挑战

引言 深度学习的快速发展已经在人工智能领域引起了革命性的变化。作为模仿人脑结构和功能的强大工具&#xff0c;深度神经网络在图像识别、自然语言处理、医学诊断等多个领域取得了显著成就。但是&#xff0c;随着技术的不断推进&#xff0c;深度学习也在不断地进化和扩展其能…

【python】OpenCV—Tracking(10.1)

学习来自《Learning OpenCV 3 Computer Vision with Python》Second Edition by Joe Minichino and Joseph Howse 文章目录 检测移动的目标涉及到的 opencv 库cv2.GaussianBlurcv2.absdiffcv2.thresholdcv2.dilatecv2.getStructuringElementcv2.findContourscv2.contourAreacv2…

Jmeter性能测试: Jmeter 5.6.3 分布式部署

目录 一、实验 1.环境 2.jmeter 配置 slave 代理压测机 3.jmeter配置master控制器压测机 4.启动slave从节点检查 5.启动master主节点检查 6.运行jmeter 7.观察jmeter-server主从节点变化 二、问题 1.jmeter 中间请求和响应乱码 一、实验 1.环境 &#xff08;1&#…

探索智慧文旅:科技如何提升游客体验

随着科技的迅猛发展&#xff0c;智慧文旅已成为旅游业的重要发展方向。通过运用先进的信息技术&#xff0c;智慧文旅不仅改变了传统旅游业的运营模式&#xff0c;更在提升游客体验方面取得了显著成效。本文将深入探讨科技如何助力智慧文旅提升游客体验。 一、智慧文旅的兴起与…

Android SELinux:保护您的移动设备安全的关键

Android SELinux&#xff1a;保护您的移动设备安全的关键 1 引言 移动设备在我们的生活中扮演着越来越重要的角色&#xff0c;我们几乎把所有重要的信息都存储在这些设备上。然而&#xff0c;随着移动应用程序的数量不断增加&#xff0c;安全性也变得越来越关键。这就是为什么…

基于Go-Kit的Golang整洁架构实践

如何用Golang实现简洁架构&#xff1f;本文介绍了基于Go-Kit实现简洁架构的尝试&#xff0c;通过示例介绍了简洁架构的具体实现。原文: Why is Go-Kit Perfect For Clean Architecture in Golang? 简介 Go是整洁架构(Clean Architecture)的完美选择。整洁架构本身只是一种方法…

RocketMQ—RocketMQ快速入门

RocketMQ—RocketMQ快速入门 RocketMQ提供了发送多种发送消息的模式&#xff0c;例如同步消息&#xff0c;异步消息&#xff0c;顺序消息&#xff0c;延迟消息&#xff0c;事务消息等。 消息发送和监听的流程 消息生产者 创建消息生产者producer&#xff0c;并制定生产者组…

Pymysql将爬取到的信息存储到数据库中

爬取平台为电影天堂 获取到的数据仅为测试学习而用 爬取内容为电影名和电影的下载地址 创建表时需要建立三个字段即可 import urllib.request import re import pymysqldef film_exists(film_name, film_link):"""判断插入的数据是否已经存在""&qu…

Hadoop3.x基础(3)- MapReduce

来源: B站尚硅谷 目录 MapReduce概述MapReduce定义MapReduce优缺点优点缺点 MapReduce核心思想MapReduce进程常用数据序列化类型MapReduce编程规范WordCount案例实操本地测试提交到集群测试 Hadoop序列化序列化概述自定义bean对象实现序列化接口&#xff08;Writable&#xff…

C++ 之LeetCode刷题记录(二十五)

&#x1f604;&#x1f60a;&#x1f606;&#x1f603;&#x1f604;&#x1f60a;&#x1f606;&#x1f603; 开始cpp刷题之旅。 目标&#xff1a;执行用时击败90%以上使用 C 的用户。 121. 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[…

数学建模比赛中,chatgpt、文心一言如何提问更有效?

在数学建模的战场上&#xff0c;ChatGPT和文心一言可是我们的“神助攻”&#xff01;但想让它们发挥出最大威力&#xff0c;提问可是个技术活。问题问得好&#xff0c;答案跑不了&#xff1b;问题问得妙&#xff0c;解决没烦恼&#xff01; 下面我就一个实际的对话为例&#x…

2024美赛数学建模E题思路分析 - 财产保险的可持续性

1 赛题 问题E&#xff1a;财产保险的可持续性 极端天气事件正成为财产所有者和保险公司面临的危机。“近年来&#xff0c;世界已经遭受了1000多起极端天气事件造成的超过1万亿美元的损失”。[1]2022年&#xff0c;保险业的自然灾害索赔人数“比30年的平均水平增加了115%”。[…

AI 原生时代的云计算

本文整理自2023年 12 月 20 日举办的「2023 百度云智大会智算大会」主论坛&#xff0c;百度副总裁谢广军的主题演讲《AI 原生时代的云计算》。 &#xff08;视频回放链接&#xff1a;https://cloud.baidu.com/summit/aicomputing_2023/index.html&#xff09; 大模型的到来&…

elk之基本crud

写在前面 本文看下工作中用的最多的CRUD。让我们一起来做一个帅帅的CRUD BOY吧&#xff01;&#xff01;&#xff01; 1&#xff1a;基本操作 Create 格式1(指定ID)&#xff1a;PUT 索引名称/_create/文档ID {文档json} 格式2&#xff08;不指定ID&#xff09;:POST 索引名称…

gitlab操作手册

git操作篇 1. 项目克隆 git clone gitgitlab.test.cn:pro/project1.git2. 项目的提交 注&#xff1a;如果要查看文件的状态可以用git status命令&#xff1a; 如上图所示&#xff0c;文件已经修改了。 3. 项目的推送 git push origin feature/test01注&#xff1a;如果要查…