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

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

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

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

相关文章

C# Onnx yolov8 水表读数检测

目录 效果 模型信息 项目 代码 训练数据 下载 C# Onnx yolov8 水表读数检测 效果 模型信息 Model Properties ------------------------- date&#xff1a;2024-01-31T10:18:10.141465 author&#xff1a;Ultralytics task&#xff1a;detect license&#xff1a;AGPL-…

c语言---访问越界之后死循环的原因

目录 死循环的概念环境题目代码运行结果对代码发生情况进行解释对i的地址和arr[12]地址一样的解释注意总结 死循环的概念 简单来说&#xff0c;死循环就是指无法靠自身的控制终止循环&#xff0c;在编程中&#xff0c;则是靠自身控制无法终止的程序。即在某一时刻&#xff0c;…

uniapp基于Android平台的校园生活服务交流论坛系统(二手,失物招领 -跑腿) 小程序hbuiderx

作为一款APP的校园论坛系统&#xff0c;面向的是大多数学者&#xff0c;软件的界面设计简洁清晰&#xff0c;用户可轻松掌握使用技巧。在调查之后&#xff0c;获得用户以下需求&#xff1a; &#xff08;1&#xff09;用户注册登录后&#xff0c;可进入系统解锁更多功能&#x…

Windows网络常用的11个命令,ping、tracert、arp、ipconfig、netstat、telnet等

1&#xff0e;ping命令 ping是个使用频率极高的实用程序&#xff0c;主要用于确定网络的连通性。ping能够以毫秒为单位显示延迟。如果应答时间短&#xff0c;表示数据报不必通过太多的路由器或网络&#xff0c;连接速度比较快。ping还能显示TTL&#xff08;Time To Live&#…

AspNet web api 和mvc 过滤器差异

最近在维护老项目。定义个拦截器记录接口日志。但是发现不生效 最后发现因为继承的 ApiController不是Controller 只能用 System.Web.Http下的拦截器生效。所以现在总结归纳一下 Web Api: System.Web.Http.Filters.ActionFilterAttribute 继承该类 Mvc: System.Web.Mvc.Ac…

客户端和服务端的简介

Client 和 Server 客户端&#xff08;Client&#xff09; 或称用户端&#xff0c;是指与服务器相对应&#xff0c;为客户提供本地服务的程序。除了一些只在本地运行的应用程序之外&#xff0c;一般安装在客户机上&#xff0c;需要与服务端互相配合运行。例如&#xff1a;下载 Q…

STM32GPIO输入(按键控制LED、光敏电阻控制蜂鸣器实例)

文章目录 一、介绍传感器模块介绍硬件电路c语言数据类型 二、实例按键控制LED接线图代码实现 光敏电阻控制蜂鸣器组装线路代码实现 相关函数解释 一、介绍 传感器模块介绍 硬件电路 上两种按下时为0&#xff0c;下两种按下时为1。 c语言数据类型 现在常用stdint头文件所定…

BeanDefinitionRegistry学习

Spring版本5.1.x 简介 在Spring框架中&#xff0c;BeanDefinitionRegistry是一个接口&#xff0c;它主要用于向注册表中注册BeanDefinition实例&#xff0c;完成注册的过程。该接口的主要方法是registerBeanDefinition&#xff0c;用于将一个BeanDefinition实例注册到注册表中…

【zip密码】zip压缩包的打开密码忘了,怎么办?

Zip压缩包设置了密码&#xff0c;解压的时候就需要输入正确对密码才能顺利解压出文件&#xff0c;正常当我们解压文件或者删除密码的时候&#xff0c;虽然方法多&#xff0c;但是都需要输入正确的密码才能完成。忘记密码就无法进行操作。 那么&#xff0c;忘记了zip压缩包的密…

一张证书如何改变职业生涯?程序员必看!

随着信息产业的迅猛发展&#xff0c;对行业人才的需求也在逐年扩大。据统计&#xff0c;未来五年&#xff0c;我国对信息化人才的总需求量将高达1500万至2000万人。以软件开发为例&#xff0c;我国对软件人才的需求正以每年20%的速度递增&#xff0c;每年新增的需求接近百万。计…

1 初识JVM

JVM&#xff08;Java Virtual Machine&#xff09;&#xff0c;也就是 “Java虚拟机”。 对于第三点功能&#xff1a;即时编译 常见的JVM 默认安装在JDK中的虚拟机为HotSpot&#xff1a;可以用“java -version”进行查看

云原生 API 网关链路追踪能力重磅上线

云原生API网关介绍 云原生 API 网关是腾讯云基于开源网关推出的一款高性能高可用的云原生 API 网关产品&#xff0c;作为云上流量入口&#xff0c;集成请求分发、API 管理、流量监控、访问限制等功能&#xff0c;是微服务架构和容器架构中的重要组件。 TSE 云原生 API 网关提…

数据分析基础之《pandas(4)—pandas画图》

1、DataFrame.plot(xNone, yNone, kindline) 说明&#xff1a; x&#xff1a;设置x轴标签 y&#xff1a;设置y轴标签 kind&#xff1a; line 折线图 bar 柱状图 hist 直方图 pie 饼图 scatter 散点图 # 找到p_change和turnover之间的关系 data.plot(xvolume, yturnover, kinds…

【数据库】分区的优点和缺点

​ &#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;数据库 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 优点&#xff1a; 缺点&#xff1a; 结语 我的其他博客 ​ 前言 数据库中的分区技术为处理大规模数据提供了一种有效的手段…

五大浏览器内核及代表浏览器,一文讲透!

Hi,我是贝格前端工场&#xff0c;在进行web前端开发的时候&#xff0c;浏览器兼容性一直是让所有前端工程师头疼的问题&#xff0c;其根源在于不同的浏览器应用了不同的内核&#xff0c;其对html、css、js的解析规则也是不一样的&#xff0c;作为前端开发的你&#xff0c;如果不…

一文掌握单基因GSEA富集分析

本期教程 本期教程原文:一文掌握单基因GSEA富集分析 | gseaGO and gseaKEGG 写在前面 关于GSEA分析,我们在前期的教程单基因GSEA富集分析 | 20220404有出过类似的分享。今天,我们也结合相关的资源整理出一篇关于GSEA的教程及出图教程。每个方法的教程很多,我们大家结合自…

2024美赛数学建模A题思路分析 - 资源可用性和性别比例(2)

# 1 赛题 问题A&#xff1a;资源可用性和性别比例 虽然一些动物物种存在于通常的雄性或雌性性别之外&#xff0c;但大多数物种实质上是雄性或雌性。虽然许多物种在出生时的性别比例为1&#xff1a;1&#xff0c;但其他物种的性别比例并不均匀。这被称为适应性性别比例的变化。…

打造实用Python学生管理系统:设计与实现

引言 在信息化教育管理的背景下&#xff0c;一个高效、便捷的学生管理系统对于提升教学管理效率具有重大意义。Python作为一种功能强大且易读易写的编程语言&#xff0c;非常适合用于开发此类系统。本文将探讨如何使用Python设计并实现一个基础的学生管理系统。 一、系统需求…

Leetcode—33. 搜索旋转排序数组【中等】

2024每日刷题&#xff08;一百一&#xff09; Leetcode—33. 搜索旋转排序数组 实现代码 class Solution { public:int search(vector<int>& nums, int target) {int n nums.size();int l 0, r n - 1;while(l < r) {int m l (r - l) / 2;if(nums[m] targe…

将结构体中的浮点数数据提取出来并发送至串口屏显示

1、由于项目中定义了一个结构体如下&#xff1a; typedef struct {uint16_t number;uint16_t LocationData;uint16_t PersonData; // _calendar_obj calendar; // uint16_t LiuLiang_Value;float LiuLiang_Value;_calendar_obj calendar_records; } Frame; 现需要将其中的flo…