在前几篇博客中介绍了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综合比较而言,我们更常用的是获取得到请求的参数!!!
所以下面着重来讲解这个地方。
来啦老弟!
见名知意,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在控制台中的信息显示:
guangString[] 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集合而已
测试代码:
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后来不火的原因了!
说明: 这里的推导,是我偶然之间进行测试得到的结果。请教了不少大佬,然后经过自己的猜测,推理出来最后的答案。 如果有问题,请及时联系我根据我的理解,我认为是这样的一套流程
共享数据的方法:
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);所以这里也就是为什么需要进行强制转换的原因了!!
见名知意,http协议的servlet的响应处理
操作的响应行、响应头、响应体
状态码。(但是意义不怎么大)
重定向问题
response.sendRedirect("重定向的路径")这里的路径可以是context内部中的资源,也可以是外部的资源。
用的比较的少。
告知浏览器用什么方式来进行解析响应包中的二进制数据
第一种: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);所以这里也就是为什么需要进行强制转换的原因了!!
见名知意,http协议的servlet的响应处理
操作的响应行、响应头、响应体
状态码。(但是意义不怎么大)
重定向问题
response.sendRedirect("重定向的路径")这里的路径可以是context内部中的资源,也可以是外部的资源。
用的比较的少。
告知浏览器用什么方式来进行解析响应包中的二进制数据
第一种:text/html;charset=utf=8【text/html的格式解析】
第二种:application/json 【json格式的数据解析】
response.setContentType("text/html;charset=utf-8"); response.setContentType("application/json");