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.rhkb.cn/news/250820.html

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

相关文章

如何搭建私有云盘SeaFile并实现远程访问本地文件资料

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-hsDnDEybLME85dTx {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

MySQL 多表查询

重点&#xff1a; MySQL 的 三种安装方式&#xff1a;包安装&#xff0c;二进制安装&#xff0c;源码编译安装。 MySQL 的 基本使用 MySQL 多实例 DDLcreate alter drop DML insert update delete DQL select 3.5&#xff09;DDL 语句 表&#xff1a;二维关系 设计表&…

python计算两个DataFrame的指定两列中,相同的数据有多少

目的&#xff1a;查询数据1和数据2中&#xff0c;red与red列相同 并且blue与blue列相同的&#xff0c;情况有多少。 &#xff08;备注&#xff1a;两个数据中格式不一致&#xff0c;需要经过json提取等处理步骤&#xff09; 思路步骤&#xff1a; 1、读取数据1&#xff0c;筛选…

跨平台开发:浅析uni-app及其他主流APP开发方式

随着智能手机的普及&#xff0c;移动应用程序&#xff08;APP&#xff09;的需求不断增长。开发一款优秀的APP&#xff0c;不仅需要考虑功能和用户体验&#xff0c;还需要选择一种适合的开发方式。随着技术的发展&#xff0c;目前有多种主流的APP开发方式可供选择&#xff0c;其…

OfficeWeb365 Readfile 任意文件读取漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

使用Eclipse搞Android项目报错

相信现在都没什么人还会用Eclipse来开发的了。 不过安装完后&#xff0c;打开Eclipse会提示我的Jdk版本不符合 --------------------------- Incompatible JVM --------------------------- Version 1.8.0_391 of the JVM is not suitable for this product. Version: 17 or g…

PHP中的stdClass:一个动态的空白板

PHP中的stdClass&#xff1a;一个动态的空白板 在PHP编程中&#xff0c;灵活性和动态性是开发人员追求的重要目标。而stdClass作为PHP中的一个特殊类&#xff0c;为我们提供了一个通用的空白板&#xff0c;允许在运行时动态地添加属性和方法。它的存在为处理动态数据结构和临时…

MySQL的ACID、死锁、MVCC问题

1 ACID ACID代表原子性&#xff08;atomicity&#xff09;、一致性&#xff08;consistency&#xff09;、隔离性&#xff08;isolation&#xff09;和持久性&#xff08;durability&#xff09;。一个确保数据安全的事务处理系统&#xff0c;必须满足这些密切相关的标准。 原…

docker集成 nacos/nacos-server (包括踩的坑)

tips 这边需要的数据库我已经安装好了&#xff0c;所以数据库的安装这边已经省略了 拉取镜像&#xff08;这边使用nacos1.4.1作为例子&#xff09; docker pull nacos/nacos-server:1.4.1创建映射的文件夹 (conf存放配置文件&#xff0c;logs存放日志文件) mkdir -p /data/n…

java常量和kotlin常量

在java中使用final声明常量在kotlin中使用const val声明常量 常量在编译为字节码后会直接把调用常量的地方直接替换为常量值&#xff0c;示例如下&#xff1a; public class ConstDemo {public static final String NAME "Even";private static final int ID 100…

Python爬虫http基本原理

Python爬虫逆向系列&#xff08;更新中&#xff09;&#xff1a;http://t.csdnimg.cn/5gvI3 HTTP 基本原理 在本节中&#xff0c;我们会详细了解 HTTP 的基本原理&#xff0c;了解在浏览器中敲入 URL 到获取网页内容之间发生了什么。了解了这些内容&#xff0c;有助于我们进一…

蓝桥杯-常用STL(一)

常用STL &#x1f388;1.动态数组&#x1f388;2.vector的基础使用&#x1f52d;2.1引入库&#x1f52d;2.2构造一个动态数组&#x1f52d;2.3插入元素&#x1f52d;2.4获取长度并且访问元素&#x1f52d;2.5修改元素&#x1f52d;2.6删除元素&#x1f52d;2.7清空 &#x1f38…

【力扣白嫖日记】SQL

前言 练习SQL语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 1387.使用唯一标识码替代员工ID 表&#xff1a;Employees 列名类型idintnamevarchar 在 SQL 中&#xff0c…

c#的反汇编对抗

文章目录 前记nim攻防基础FFI内存加载加解密、编码 后记C#类型转换表nim基础 前记 随便编写一个c#调用winapi并用vs生成dll,同时用csc生成exe using System; using System.Runtime.InteropServices; namespace coleak {class winfun{[DllImport("User32.dll")]publ…

只用一台服务器部署上线(宝塔面板) 前后端+数据库

所需材料 工具&#xff1a;安装宝塔面板服务器至少一台、域名一个 前端&#xff1a;生成dist文件&#xff08;前端运行build命令&#xff09; 后端&#xff1a;生成jar包&#xff08;maven运行package命令&#xff09; 准备&#xff1a; 打开宝塔面板&#xff0c;点击进入软…

centOS+nodejs+mysql阿里云部署前后端个人网站

centOSnodejsmysql阿里云部署前后端个人网站 参考&#xff1a; 部署NodeExpressMySQL项目到阿里云轻量应用服务器 阿里云轻量应用服务器部署Node.jsReactMongoDB前后端分离项目 参考&#xff1a;在阿里云上部署nodejs服务 https 部署的原理就是你在本地测试的时候在地址栏&am…

EasyExcel使用,实体导入导出

简介 Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存&#xff0c;poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题&#xff0c;但POI还是有一些缺陷&#xff0c;比如07版Excel解压缩以及解压后存储都是在内存中…

Flume搭建

压缩包版本&#xff1a;apache-flume-1.9.0-bin.tar 百度盘链接&#xff1a;https://pan.baidu.com/s/1ZhSiePUye9ax7TW5XbfWdw 提取码&#xff1a;ieks 1.解压 tar -zxvf /opt/software/apache-flume-1.9.0-bin.tar.gz -C /opt/module/ 2. 修改文件名 [rootbigdata1 opt]…

银行数据仓库体系实践(8)--主数据模型设计

主数据区域中保留了数据仓库的所有基础数据及历史数据&#xff0c;是数据仓库中最重要的数据区域之一&#xff0c;那主数据区域中主要分为近源模型区和整合&#xff08;主题&#xff09;模型区。上一节讲到了模型的设计流程如下图所示。那近源模型层的设计在第2.3和3这两个步骤…

探索Gin框架:Golang使用Gin完成文件上传

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站https://www.captainbed.cn/kitie。 前言 在之前的文章中&#xff0c;我们讲解了Gin框架的快速入门使用&#xff0c;今天我们来聊聊如何使用…