HttpServletRequest和HttpServletResponse

tech2022-08-04  147

HttpServletRequest和HttpServletResponse

在前几篇博客中介绍了servlet,也详细描述了自定义的类继承HttpServlet作为一个标准类的原因。

这篇来分析一下doGet和doPost方法中的参数

doGet/Post方法,见名知意,表示的是对get/post请求的处理

因为post的请求方式太过于少见,只用于表单提交数据的请求当中

最常用的是get方式的请求。

因为一个标准servlet类中存在着doPost和doGet方法

所以提供一种小技巧:在doPost方法中调用doGet方法,一劳永逸。

另外需要进行补充的是:在Tomcat8及其之后的版本中,对于get的请求方式,Tomcat使用的是utf-8进行解析的;对于post请求方式,Tomcat采用的是ISO-8859-1的方式来进行解析,所以,如果要是使用表单的请求方法是post进行请求的,那么在接收请求参数之前,需要先指定解析方式,然后再去进行获取参数。否则乱码

获取请求行中的信息

思想良久:还是将请求方式的总结写在前面

我将请求方式分为两种:

第一种:超链接

http://www.baidu.com?username=guang&password=guang http://localhost:8080/guang/login?username=guang&password=guang

如果请求参数有多个,那么使用&来进行分隔

在请求地址后面加上?参数1=参数值1&参数2=参数2&....

表单方式的get方式提交

<form action="/xxx" method="get"> 姓名:<input type="text name="username"/><br> 密码:<input type="password" name="password"/><br> 性别:<input type="radio" name="sex" value="man"/><input name="radio" name="sex" value="famale"/><br> 爱好:<input type="checkbox" name="hobby" value="sing"><input type="checkbox" name="hobby" value="skip"><input type="checkbox" name="bobby" value="rap">rap<br> <input type="submit" value="提交" /> </form>

总结:对于get方式作为请求参数需要满足的条件:

在请求地址后面加上?参数1=参数值1&参数2=参数2&....

参数在请求行中

第二种:表单

表单形式的post方式进行提交

<form action="/xxx" method="get"> 姓名:<input type="text name="username"/><br> 密码:<input type="password" name="password"/><br> 性别:<input type="radio" name="sex" value="man"/><input type="radio" name="sex" value="famale"/><br> 爱好:<input type="checkbox" name="hobby" value="sing"><input type="checkbox" name="hobby" value="skip"><input type="checkbox" name="bobby" value="rap">rap<br> <input type="submit" value="提交" /> </form>

总结:对于post方式提交表单来说,满足的参数是:

①在表单中;②必须拥有name和value值;③请求地址

需要进行解释的三点:

对于text和password,value就是我们输入的内容

对于radio和checkbox,需要保证上面的三个条件之外,还需要保证name都是一样的,不然

对于radio来说,不再是单选,而是可以进行多选的;对于checkbox来说,提交的name不一致了,那么参数的名称也就不同了。

如果在action中仍然携带了参数,那么这个参数是无效的,不会发送这样的参数

<form aciton="www.baidu.com?name=guang>

在发送参数的时候,不会写在name=guang这个参数信息过去的。

正式开始进行讲解:

对于一个请求协议包而言,分为了三大部分:

通过对比可以发现,post方式有请求体,而get方式没有请求体。

那么对于post方式的请求体是什么?放的是请求的参数信息,可以放的比较多的请求数据。

对于post请求来说,放的参数信息都在请求行中

先来看下请求协议包中都有着哪些东西:

在请求行中的信息: Request URL: https://www.baidu.com/?username=guang&password=guang request Method: GET Remote Address: 14.215.177.39:443 请求URI和URL请求参数请求方式请求时候本机地址

对于使用java方法来进行操作

getMethod();获取请求方式getRemoteAddr():是哪台计算机发起请求的,IP地址是多少**getContextPath()😗*获得部署到服务器上的项目名称**getRequestURI()😗*获得请求地址,不带项目名**getRequestURL():**获得请求地址,带项目名字

再次进行提醒的是前端发送多来的参数都是字符串。如果需要解析,请使用对应的方式来进行解析

最常见的是两种:整数和日期

对于请求头来说:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36 Accept:告知服务器,我能就收什么样的数据格式,也就是传输过来的数据进行解码的格式Accept-Encoding:压缩算法,不常用Accept-Language:浏览器接收的语言是中文User-Agent:客户端的信息全部暴露出来了。使用的操作系统版本号,多少位操作系统,什么浏览器等等

因为这里的数据还没有使用到,所以在这里就不再过多的进行解释!

对于post方式提交的数据来说,请求参数在请求体中,我用的是谷歌浏览器,这种看不到,所以这里无法进行展示,但是,可以猜测出来这里的数据

username=liguang&password=guang

综合比较而言,我们更常用的是获取得到请求的参数!!!

所以下面着重来讲解这个地方。

来啦老弟!

HttpServletRequest

见名知意,http协议的servlet的请求处理,我们着重分析的是获取得到参数,这里有各种各样的方法来进行操作。

我觉得在这里有必要对HttpServletRequest和HttpServletResponse做一个生命周期的介绍。

HttpServletRequest继承体系

在servlet的继承体系中,Servlet接口、GenericServlet类

void service(ServletRequest var1, ServletResponse var2)

但是在HttpServlet的doGet和doPost方法中

void doGet(HttpServletRequest req, HttpServletResponse resp) void doPost(HttpServletRequest req, HttpServletResponse resp)

我的理解是更好的处理HTTP请求和响应

获取参数

查看HttpServletRequest中的常用的方法:

法名描述String getParameter(String name)获得指定参数名对应的值。如果没有则返回null,如果有多个获得第一个。 例如:username=jack。(有弊端存在,比如说checkbox中的数据)_String[] getParameterValues(String name)获得指定参数名对应的所有的值。此方法专业为复选框提供的。 例如:hobby=抽烟&hobby=喝酒&hobby=敲代码Map<String,String[]> getParameterMap()获得所有的请求参数。key为参数名,value为key对应的所有的值。(常用)String getQueryString()直接获取得到所有的请求参数的字符串(post请求为null)

创建一个新的servlet来进行测试:

public class OneServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 先将解析方式改还成utf-8来进行解析 // 获取得到请求参数 String queryString = req.getQueryString(); System.out.println(queryString); } }

在web.xml中进行配置

<servlet> <servlet-name>oneservlet</servlet-name> <servlet-class>guang.servlet.OneServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>oneservlet</servlet-name> <url-pattern>/one</url-pattern> </servlet-mapping>

第一种:

String getQueryString()方法(做做测试玩玩还是可以的)

测试一:在浏览器的地址栏中输入:

http://localhost:8080/test/one

在控制台中显示的信息:

null

因为没有什么参数

测试二:在浏览器中的地址栏中输入:

http://localhost:8080/test/one?username=guang

在控制台显示的是:

username=guang

测试三:使用表单来进行提交

使用get方式

<p>使用get方式提交</p> <form action="./one" method="get"> 姓名:<input type="text name="username"/><br> 密码:<input type="password" name="password"/><br> 性别:<input type="radio" name="sex" value="man"/><input type="radio" name="sex" value="famale"/><br> 爱好:<input type="checkbox" name="hobby" value="sing"><input type="checkbox" name="hobby" value="skip"><input type="checkbox" name="bobby" value="rap">rap<br> <input type="submit" value="提交" /> </form>

控制台显示信息:

username=%E5%B9%BF%E5%9C%BA%E8%88%9E&password=guangchangwu&sex=famale&hobby=sing&hobby=skip

这里的username我输入的是一个中文。在这边是无法进行显示中文。

使用post方式

<p>使用post方式提交</p> <form action="./one" method="post"> 姓名:<input type="text name="username"/><br> 密码:<input type="password" name="password"/><br> 性别:<input type="radio" name="sex" value="man"/><input type="radio" name="sex" value="famale"/><br> 爱好:<input type="checkbox" name="hobby" value="sing"><input type="checkbox" name="hobby" value="skip"><input type="checkbox" name="bobby" value="rap">rap<br> <input type="submit" value="提交" /> </form>

控制台信息:

null

小结:对于getQueryString方法来说,如果是get的请求方式,可以获取得到请求参数;如果是post的请求方式,那么获取得到的结果是null。

第二种

String getParameter(String name)

测试代码如下:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 先设置解析数据的方式 request.setCharacterEncoding("utf-8"); // 根据参数名字来获取得到参数 String value = request.getParameter("username"); System.out.println(value); }

在地址栏中输入的信息:

http://localhost:8080/test/two?username=guang

在控制台中的信息显示:

guang

第三种

String[] getParameterValues(String name)

根据参数和方法名称发现,这里应该使用表单中的数据来进行提交的

测试代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取得到参数值 String[] hobbies = request.getParameterValues("hobby"); for (String hobby : hobbies) { System.out.println(hobby); } }

表单方式提交:

<form action="./three" method="get"> 姓名:<input type="text" name="username" /><br> 密码:<input type="password" name="password"/><br> 性别:<input type="radio" name="sex" value="man"/><input type="radio" name="sex" value="famale"/><br> 爱好:<input type="checkbox" name="hobby" value="sing"><input type="checkbox" name="hobby" value="skip"><input type="checkbox" name="hobby" value="rap">rap<br> <input type="submit" value="提交" /> </form> </body>

控制台信息:

sing skip rap

第四种

Map<String,String[]> getParameterMap()

同上,这里采用的是map集合而已

测试代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 根据参数名字来获取得到参数值 Map<String, String[]> parameterMap = request.getParameterMap(); Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet(); for (Map.Entry<String, String[]> entry : entries) { String key = entry.getKey(); // 获取得到的是一个数组 String[] value = entry.getValue(); System.out.print(key+"="); // 循环遍历数组中的内容 for (int i = 0; i < value.length; i++) { System.out.print(" "+value[i]); } System.out.println(); } }

表单方式提交:

<p>使用get方式提交</p> <form action="./four" method="get"> 姓名:<input type="text" name="username" /><br> 密码:<input type="password" name="password"/><br> 性别:<input type="radio" name="sex" value="man"/><input type="radio" name="sex" value="famale"/><br> 爱好:<input type="checkbox" name="hobby" value="sing"><input type="checkbox" name="hobby" value="skip"><input type="checkbox" name="hobby" value="rap">rap<br> <input type="submit" value="提交" /> </form>

控制台信息:

username= 光 password= fdsafds sex= man hobby= sing skip rap

使用post方式进行测试:

username= 光 password= guang sex= man hobby= sing skip rap

其他方法:

String getContextPath():获取得到当前的项目路径Cookie[] getCookie():获取所有的cookie,可以实现循环遍历String getMethod():获取得到请求的方式StringBuffer getRequestURL():获取得到URL。【返回值类型是StringBuffer】String getRequestURI():获取得到的是URI。获取的是请求的资源路径String getServletPath(); 得到servlet的路径Session getSession():获取得到session

演示一下:

代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /** * - String getContextPath():获取得到当前的项目路径 * - Cookie[] getCookie():获取所有的cookie,可以实现循环遍历 * - String getMethod():获取得到请求的方式 * - StringBuffer getRequestURL():获取得到URL。【返回值类型是StringBuffer】 * - String getRequestURI():获取得到的是URI。获取的是请求的资源路径 * - String getServletPath(); 得到servlet的路径 * - Session getSession():获取得到session */ String contextPath = request.getContextPath(); System.out.println("contextPath:"+contextPath); System.out.println("------------------"); Cookie[] cookies = request.getCookies(); for (int i = 0; i < cookies.length; i++) { System.out.println("cookie["+i+"]:"+cookies[i]); } System.out.println("------------------"); String method = request.getMethod(); System.out.println("method:"+method); System.out.println("------------------"); StringBuffer requestURL = request.getRequestURL(); String requestURI = request.getRequestURI(); System.out.println("requestURL:"+requestURL); System.out.println("requestURI:"+requestURI); System.out.println("------------------------"); String servletPath = request.getServletPath(); System.out.println("servletPath:" + servletPath); HttpSession session = request.getSession(); System.out.println("session:" + session); }

演示效果:

contextPath:/test // 项目名字,也就是当前context项目的路径 ------------------ cookie[0]:javax.servlet.http.Cookie@1302b6a cookie[1]:javax.servlet.http.Cookie@ff7c53c cookie[2]:javax.servlet.http.Cookie@bc8401a ------------------ method:GET // 请求的方式 ------------------ requestURL:http://localhost:8080/test/five //统一资源定位符,计算机中的唯一标志。这里当然不是,在本机 requestURI:/test/five // 当前资源在当前计算机中的路径 ------------------------ servletPath:/five // 也就是我们配置的servlet的别名,这里是servlet的路径 session:org.apache.catalina.session.StandardSessionFacade@4ecacf07

请求转发

首先需要明白的是请求转发是什么意思?

请求:向Tomcat进行申请,想要访问的资源。

转发:将要访问的资源返回到客户端去。

示例:

requset.getRequestDispatcher("/WEB-INF/register.html").forward(requset,response);

为什么使用的是request来记性请求转发呢?为什么后面又要使用到了request和response?

向Tomcat申请资源,那么申请的动作,根据字面上的理解,当然是由request来进行请求完成的。

对于转发来讲,那么就是需要由response将申请的资源打包(响应协议包),让Tomcat推送到前端去。

请求转发静态资源原理分析:

请求转发动态资源原理分析:

首先说明两点:

第一:

在测试动态资源请求转发的时候,发现了一点!就是在Tomcat接收到请求重新创建了一个对象之后,新的request对象和之前的request中的数据都是一样的(基本类型是数据,引用类型是地址)。所以在一次动态资源的请求转发过程中,多个request对象保留着的有着相同的数据!称之为request对象的数据共享

第二:

发现在进行动态资源的请求转发中,response的的地址值一直没有发生改变!说明了在对于一次请求中,request的对象的值是可以发生变化的,但是对于response来说,是不会发生改变的。非常容易理解!因为在请求转发中,请求中根本没有用到response,只有在转发的时候才用到了response。

相信到了这里也应该明白了重定向和请求转发的区别了。

总结:请求转发共享数据适用在servlet之间!jsp也是servlet!

可以来看一下,我的电脑中

C:\Users\guang\.IntelliJIdea2018.2\system\tomcat\Unnamed_Javaweb\work\Catalina\localhost\test\org\apache\jsp

对应的文件:

查看下里面的关键性代码:

public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; try { response.setContentType("text/html;charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("\r\n"); out.write("\r\n"); out.write("<html>\r\n"); out.write("<head>\r\n"); out.write(" <title>首页</title>\r\n"); out.write("</head>\r\n"); out.write("<body>\r\n"); out.write(" <form action=\"./myservlet\" method=\"post\">\r\n"); out.write(" 姓名:<input type=\"text\" name=\"name\"><br>\r\n"); out.write(" 年龄:<input type=\"text\" name=\"age\"><br>\r\n"); out.write(" 性别:<input type=\"radio\" name=\"sex\" value=\"man\">男<input type=\"radio\" name=\"sex\" value=\"woman\">女<br>\r\n"); out.write(" 爱好: <input type=\"checkbox\" name=\"hobby\" value=\"抽烟\">抽烟<br>\r\n"); out.write(" <input type=\"checkbox\" name=\"hobby\" value=\"唱歌\">唱歌<br>\r\n"); out.write(" <input type=\"checkbox\" name=\"hobby\" value=\"烫头\">烫头<br>\r\n"); out.write(" <input type=\"checkbox\" name=\"hobby\" value=\"喝酒\">喝酒<br>\r\n"); out.write(" <input type=\"submit\" value=\"提交\">\r\n"); out.write(" </form>\r\n"); out.write("</body>\r\n"); out.write("</html>\r\n"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { if (response.isCommitted()) { out.flush(); } else { out.clearBuffer(); } } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else throw new ServletException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } }

将上面的代码拆分:

final javax.servlet.jsp.PageContext pageContext; // javax.servlet.http.HttpSession session = null; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; try中的 _jspx_page_context = pageContext;

输入数据中就是一个个的将HTML中的语句进行输出,这也是jsp后来不火的原因了!

说明: 这里的推导,是我偶然之间进行测试得到的结果。请教了不少大佬,然后经过自己的猜测,推理出来最后的答案。 如果有问题,请及时联系我

request共享数据域

根据我的理解,我认为是这样的一套流程

共享数据的方法:

Object getAttribute(String name) ; 取数据

void setAttribute(String name,Object object) ; 存数据

void removeAttribute(String name) ; 移除request中的数据

request存值的时候,可以存任何类型的值。

key是String value是Object

这里就类似于HashMap了

HashMap<String,Object> map = new HashMap<>(); map.put(name1,Object);------------request.setAttribute(String,Ojbect); Object obj = map.get(name1); ---------------request.getAttribute(String);

所以这里也就是为什么需要进行强制转换的原因了!!

HttpServletResponse

见名知意,http协议的servlet的响应处理

Response作用

操作的响应行、响应头、响应体

1、操作响应行

状态码。(但是意义不怎么大)

2、操作响应头

重定向问题

response.sendRedirect("重定向的路径")

这里的路径可以是context内部中的资源,也可以是外部的资源。

用的比较的少。

3、操作响应体

告知浏览器用什么方式来进行解析响应包中的二进制数据

​ 第一种:text/html;charset=utf=8【text/html的格式解析】

​ 第二种:application/json 【json格式的数据解析】

response.setContentType("text/html;charset=utf-8"); response.setContentType("application/json");

何类型的值。

key是String value是Object

这里就类似于HashMap了

HashMap<String,Object> map = new HashMap<>(); map.put(name1,Object);------------request.setAttribute(String,Ojbect); Object obj = map.get(name1); ---------------request.getAttribute(String);

所以这里也就是为什么需要进行强制转换的原因了!!

HttpServletResponse

见名知意,http协议的servlet的响应处理

Response作用

操作的响应行、响应头、响应体

1、操作响应行

状态码。(但是意义不怎么大)

2、操作响应头

重定向问题

response.sendRedirect("重定向的路径")

这里的路径可以是context内部中的资源,也可以是外部的资源。

用的比较的少。

3、操作响应体

告知浏览器用什么方式来进行解析响应包中的二进制数据

​ 第一种:text/html;charset=utf=8【text/html的格式解析】

​ 第二种:application/json 【json格式的数据解析】

response.setContentType("text/html;charset=utf-8"); response.setContentType("application/json");
最新回复(0)