Java匹马行天下之JavaWeb核心技术——JSP(续)
十二、JSP表单处理
我们在浏览网页的时候,经常需要向服务器提交信息,并让后台程序处理。浏览器中使用 GET 和 POST 方法向服务器提交数据。
GET 方法
GET方法将请求的编码信息添加在网址后面,网址与编码信息通过"?"号分隔。如下所示:
http://www.runoob.com/hello?key1=value1&key2=value2
GET方法是浏览器默认传递参数的方法,一些敏感信息,如密码等建议不使用GET方法。
用get时,传输数据的大小有限制 (注意不是参数的个数有限制),最大为1024字节。
POST 方法
一些敏感信息,如密码等我们可以通过POST方法传递,POST提交数据是隐式的。
POST提交数据是不可见的,GET是通过在url里面传递的(可以看一下你浏览器的地址栏)。
JSP使用getParameter()来获得传递的参数,getInputStream()方法用来处理客户端的二进制数据流的请求。
JSP 读取表单数据
- getParameter(): 使用 request.getParameter() 方法来获取表单参数的值。
- getParameterValues(): 获得如checkbox类(名字相同,但值有多个)的数据。 接收数组变量 ,如checkbox类型
- getParameterNames():该方法可以取得所有变量的名称,该方法返回一个 Enumeration。
- getInputStream():调用此方法来读取来自客户端的二进制数据流。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <%@ page contentType= "text/html;charset=UTF-8" language= "java" pageEncoding= "UTF-8" %> <!DOCTYPE html> <html> <head> <title>表单信息</title> </head> <body> <form action= "Demo1.jsp" method= "post" > <input type= "text" name= "name" /><br> <input type= "text" name= "url" /><br> <input type= "checkbox" name= "mao" checked= "checked" />猫<br> <input type= "checkbox" name= "gou" />狗<br> <input type= "checkbox" name= "ji" checked= "checked" />鸡<br> <input type= "checkbox" name= "ya" />鸭<br> <input type= "submit" value= "提交" > </form> </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <%@ page import = "java.util.Enumeration" %> <%@ page contentType= "text/html;charset=UTF-8" language= "java" pageEncoding= "UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset= "utf-8" > <title>JSP</title> </head> <body> <h1>读取参数信息</h1> <table align= "center" border= "1" width= "100%" > <tr bgcolor= "#f0f8ff" > <th>参数名</th> <th>对应值</th> </tr> <% Enumeration<String> parameterNames = request.getParameterNames(); request.setCharacterEncoding( "utf-8" ); while (parameterNames.hasMoreElements()){ String name = parameterNames.nextElement(); out.println( "<tr><td>" +name+ "</td>\n" ); String url = request.getParameter(name); out.println( "<td>" +url+ "</td></tr>\n" ); } %> </table> <% %> </body> </html> |
十三、四大域对象:实际开发如何用?
PageContext:pageConext 存放的数据仅在当前页面有效。开发时使用较少。当前页面存放数据用表单标签中的 <input type="hidden" />,且该存值方式用户看不到。
ServletRequest: request 存放的数据在一次请求(转发:可以传数据)内有效。使用非常多。
HttpSession: session 存放的数据在一次会话(多次请求)中有效。使用的比较多。例如:存放用户的登录信息、购物车功能。
ServletContext: application 存放的数据在整个应用范围内都有效。因为范围太大,应尽量少用。用于统计在线人数。
十四、会话跟踪
-
会话概述
1、什么是会话?如同打电话。
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
2、会话过程要解决的问题是什么?保持各个客户端自己的数据。
每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,程序要想办法为每个用户保存这些数据。
例如:用户点击超链接通过一个servlet购买了一个商品,程序应该想办法保存用户购买的商品,以便于用户点结帐servlet时,结帐servlet可以得到用户购买的商品为用户结帐。
思考:用户购买的商品保存在request或servletContext中行不行?答:不行。
保存会话数据的两种技术:
Cookie:是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。
当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。
这样,web资源处理的就是用户各自的数据了。
HttpSession:Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的HttpSession对象,
由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,
当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
-
http协议的无状态性
无状态是指,当浏览器发送请求给服务器时,服务器响应客户端请求。但是当同一个浏览器再次发送请求给服务器时,服务器并不知道它就是刚才那个浏览器。简单来说,就是服务器不会去记得你,所以就是无状态协议。
-
JSP Cookie 处理
Cookie是存储在客户机的文本文件,它们保存了大量轨迹信息。在servlet技术基础上,JSP显然能够提供对HTTP cookie的支持。
通常有三个步骤来识别回头客:
- 服务器脚本发送一系列cookie至浏览器。比如名字,年龄,ID号码等等。
- 浏览器在本地机中存储这些信息,以备不时之需。
- 当下一次浏览器发送任何请求至服务器时,它会同时将这些cookie信息发送给服务器,然后服务器使用这些信息来识别用户或者干些其它事情。
JSP Cookie 处理需要对中文进行编码与解码,方法如下:
1 2 | String str = java.net.URLEncoder.encode( "中文" , "UTF-8" ); //编码 String str = java.net.URLDecoder.decode( "编码后的字符串" , "UTF-8" ); // 解码 |
-
Servlet Cookie 方法
-
使用JSP设置Cookie
使用JSP设置cookie包含三个步骤:
(1)创建一个Cookie对象: 调用Cookie的构造函数,使用一个cookie名称和值做参数,它们都是字符串。
1 | Cookie cookie = new Cookie( "key" , "value" ); |
请务必牢记,名称和值中都不能包含空格或者如下的字符:
1 | [ ] ( ) = , " / ? @ : ; |
(2) 设置有效期:调用setMaxAge()函数表明cookie在多长时间(以秒为单位)内有效。下面的操作将有效期设为了24小时。
1 | cookie.setMaxAge( 60 * 60 * 24 ); |
(3) 将cookie发送至HTTP响应头中:调用response.addCookie()函数来向HTTP响应头中添加cookie。
1 | response.addCookie(cookie); |
-
实例说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <%@ page contentType= "text/html;charset=UTF-8" language= "java" %> <!DOCTYPE html> <html> <head> <meta charset= "utf-8" > <title>表单提交</title> </head> <body> <form action= "CookieDemo.jsp" method=GET> 站点名: <input type= "text" name= "name" > <br /> 网址: <input type= "text" name= "url" /> <input type= "submit" value= "提交" /> </form> </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <%@ page import = "java.net.URLEncoder" %> <%@ page contentType= "text/html;charset=UTF-8" language= "java" pageEncoding= "UTF-8" %> <% // 编码,解决中文乱码 String str = URLEncoder.encode(request.getParameter( "name" ), "utf-8" ); // 设置 name 和 url cookie Cookie name = new Cookie( "name" , str); Cookie url = new Cookie( "url" , request.getParameter( "url" )); // 设置cookie过期时间为24小时。 name.setMaxAge( 60 * 60 * 24 ); url.setMaxAge( 60 * 60 * 24 ); // 在响应头部添加cookie response.addCookie( name ); response.addCookie( url ); %> <html> <head> <title>设置 Cookie</title> </head> <body> <h1>设置 Cookie</h1> <ul> <li><p><b>网站名:</b> <%= request.getParameter( "name" )%> </p></li> <li><p><b>网址:</b> <%= request.getParameter( "url" )%> </p></li> </ul> </body> </html> |
-
使用 JSP 读取 Cookie
想要读取cookie,您就需要调用request.getCookies()方法来获得一个javax.servlet.http.Cookie对象的数组,然后遍历这个数组,使用getName()方法和getValue()方法来获取每一个cookie的名称和值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <%@ page contentType= "text/html;charset=UTF-8" language= "java" %> <%@ page import = "java.net.*" %> <!DOCTYPE html> <html> <head> <meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" > <title>获取 Cookie</title> </head> <body> <% Cookie cookie = null ; Cookie[] cookies = null ; // 获取cookies的数据,是一个数组 cookies = request.getCookies(); if ( cookies != null ){ out.println( "<h2> 查找 Cookie 名与值</h2>" ); for ( int i = 0 ; i < cookies.length; i++){ cookie = cookies[i]; out.print( "参数名 : " + cookie.getName()); out.print( "<br>" ); out.print( "参数值: " + URLDecoder.decode(cookie.getValue(), "utf-8" ) + " <br>" ); out.print( "------------------------------------<br>" ); } } else { out.println( "<h2>没有发现 Cookie</h2>" ); } %> </body> </html> |
-
使用JSP删除Cookie
删除cookie非常简单。如果您想要删除一个cookie,按照下面给的步骤来做就行了:
- 获取一个已经存在的cookie然后存储在Cookie对象中。
- 将cookie的有效期设置为0。
- 将这个cookie重新添加进响应头中。
-
实例演示
下面的程序删除一个名为"name"的cookie,当您第二次运行CookieDemo2.jsp时,name 将会为 null。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <%@ page contentType= "text/html;charset=UTF-8" language= "java" %> <%@ page import = "java.net.*" %> <!DOCTYPE html> <html> <head> <meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" > <title>获取 Cookie</title> </head> <body> <% Cookie cookie = null ; Cookie[] cookies = null ; // 获取当前域名下的cookies,是一个数组 cookies = request.getCookies(); if ( cookies != null ){ out.println( "<h2> 查找 Cookie 名与值</h2>" ); for ( int i = 0 ; i < cookies.length; i++){ cookie = cookies[i]; if ((cookie.getName( )).compareTo( "name" ) == 0 ){ cookie.setMaxAge( 0 ); response.addCookie(cookie); out.print( "删除 Cookie: " + cookie.getName( ) + "<br/>" ); } out.print( "参数名 : " + cookie.getName()); out.print( "<br>" ); out.print( "参数值: " + URLDecoder.decode(cookie.getValue(), "utf-8" ) + " <br>" ); out.print( "------------------------------------<br>" ); } } else { out.println( "<h2>没有发现 Cookie</h2>" ); } %> </body> </html> |
-
图解分析
-
Session
-
HttpSession概述
HttpSession是有JavaWeb提供的,用来会话跟踪的类,session是服务器对象,保存在服务器端;
HttpSession是Servlet三大域对象之一(request、session、application),所以它也有setAttribute()、getAttribute()、removeAttribute()方法;
HttpSession底层依赖Cookie,或是URL重写。
-
HttpSession的作用
- 会话范围:会话范围是某个用户从首次访问服务器开始,到该用户关闭浏览器结束;
会话:一个用户对服务器的多次连贯性请求,所谓连贯性请求,就是该用户多次请求中间没有关闭浏览器。
- 服务器会为每个客户端创建一个session对象,session就好比客户在服务器端的账户,它们被服务器保存到一个Map中,这个Map被称为session缓存。
Servlet中得到session对象:HttpSession session = request.getSession();
JSP中得到session对象:session是jsp内置对象之下,不用创建就可以直接使用。
-
session域相关方法
1 2 3 4 5 | void setAttribute(String name,Object val); Object getAttribute(String name); void removeAttribute(String name); |
-
session保存用户登录信息
- 案例相关页面和Servlet:
login.jsp 登录页面
LoginSuccess.jsp 只有登录成功才能访问的页面
LoginServlet:校验用户是否登录成功
- 各页面和Servlet内容:
login.jsp 提供登录表单,提交表单请求LoginServlet
LoginServlet 获取请求参数,校验用户是否登录成功
失败:保存错误信息到request域,转发到login.jsp,在login.jsp中显示request域中的错误信息;
成功:保存用户信息到session域中,重定向到LoginSuccess.jsp页面,显示session域中的用户信息。
LoginSuccess.jsp 从session域获取用户信息,如果不存在,显示“您还没有登录”,存在则显示用户信息;
只要用户没有关闭浏览器,session就一直存在,那么保存在session中的用户信息也就一起存在,那么用户访问LoginSuccess.jsp就会通过
login.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <%@ page contentType= "text/html;charset=UTF-8" language= "java" %> <!DOCTYPE html> <html> <head> <title>登录页面</title> </head> <body> <% //获取cookie的值 String name = "" ; String pwd = "" ; Cookie[] cs = request.getCookies(); if (cs!= null ){ for (Cookie c : cs){ if ( "username" .equals(c.getName())){ name = c.getValue(); } if ( "pwd" .equals(c.getName())){ pwd = c.getValue(); } } } %> <% //获取request信息 String message= "" ; String mess = (String)request.getAttribute( "message" ); if (mess!= null ){ message = mess; } %> <h1>用户登录</h1> <span color= "red" ><%=message %></span> <form action= "/LoginServlet" method= "post" > <p> 账号:<input type= "text" name= "username" value= "<%=name %>" /> </p> <p> 密码:<input type= "password" name= "pwd" value= "<%=pwd %>" /> </p> <p> <input type= "submit" value= "登录" > </p> </form> </body> </html> |
LoginServlet.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | package com.demo.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException; @WebServlet ( "/LoginServlet" ) public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置请求的字符编码 request.setCharacterEncoding( "utf-8" ); //接收客户端请求 String username = request.getParameter( "username" ); String pwd = request.getParameter( "pwd" ); //判断是否登录成功 if ( "admin" .equals(username) && "1234" .equals(pwd)){ //登录成功,把信息保存到cookie中 Cookie c1 = new Cookie( "username" ,username); Cookie c2 = new Cookie( "pwd" ,pwd); c1.setMaxAge( 60 * 60 * 24 ); c2.setMaxAge( 60 * 60 * 24 ); response.addCookie(c1); response.addCookie(c2); //登录成功,保存用户名到session中,并重定向到LoginSuccess.jsp HttpSession session = request.getSession(); session.setAttribute( "username" , username); response.sendRedirect( "/LoginSuccess.jsp" ); } else { //转发给客户端“登录失败” request.setAttribute( "message" , "用户信息错误,请重新登录" ); request.getRequestDispatcher( "/login.jsp" ).forward(request, response); } } } |
LoginSuccess.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <%@ page contentType= "text/html;charset=UTF-8" language= "java" %> <!DOCTYPE html> <html> <head> <title>登录成功</title> </head> <body> <% //获取session信息 String name = (String)session.getAttribute( "username" ); if (name== null ){ //session不存在,转发到登录页面,并提示信息 request.setAttribute( "message" , "您还没有登录,不能访问页面" ); request.getRequestDispatcher( "/login.jsp" ).forward(request, response); //重定向到login.jsp,不会显示request提示的信息 //response.sendRedirect("/login/login.jsp"); return ; } %> <h1>登录成功</h1> 你好<%=name %>,欢迎登录! </body> </html> |
-
隐藏表单域
一个网络服务器可以发送一个隐藏的HTML表单域和一个唯一的session ID,就像下面这样:
1 | <input type= "hidden" name= "sessionid" value= "12345" > |
这个条目意味着,当表单被提交时,指定的名称和值将会自动包含在GET或POST数据中。每当浏览器发送一个请求,session_id的值就可以用来保存不同浏览器的轨迹。
这种方式可能是一种有效的方式,但点击<A HREF>标签中的超链接时不会产生表单提交事件,因此隐藏表单域也不支持通用会话跟踪。
-
重写URL
您可以在每个URL后面添加一些额外的数据来区分会话,服务器能够根据这些数据来关联session标识符。
举例来说,http://w3cschool.cc/file.htm;sessionid=12345, session标识符为sessionid=12345,服务器可以用这个数据来识别客户端。
相比而言,重写URL是更好的方式来,就算浏览器不支持cookies也能工作,但缺点是您必须为每个URL动态指定session ID,就算这是个简单的HTML页面。
- session依赖Cookie,目的是让客户端发出请求时归还sessionID,这样才能找到对应的session;
- 如果客户端禁用了Cookie,那么就无法得到sessionID,那么session也就无用了;
- 也可以使用URL重写来替代Cookie
- 让网站的所有超链接、表单中都添加一个特殊的请求参数,即sessionID;
- 这样服务器可以通过获取请求参数得到sessionID,从而找到session对象;
- response.encodeURL(String url)该方法会对url进行智能的重写,当请求中没有归还session这个Cookie,那么该方法会重写URL,否则不重写,当然url必须是指向本站的url。
-
session对象
除了以上几种方法外,JSP利用servlet提供的HttpSession接口来识别一个用户,存储这个用户的所有访问信息。
默认情况下,JSP允许会话跟踪,一个新的HttpSession对象将会自动地为新的客户端实例化。禁止会话跟踪需要显式地关掉它,通过将page指令中session属性值设为false来实现,就像下面这样:
1 | <%@ page session= "false" %> |
JSP引擎将隐含的session对象暴露给开发者。由于提供了session对象,开发者就可以方便地存储或检索数据。
下表列出了session对象的一些重要方法:
-
Session与Cookie的对比
-
HttpSession原理
服务器不会马上给你创建session,在第一次获取session时,即reques.getSession()方法执行时,才会创建session。
获取Cookie中的JSESSIONID:
- 如果sessionID不存在,创建session,把session保存起来,把新创建的sessionID保存到Cookie中;
- 如果sessionID存在,创建sessionID查找session对象,如果没有查找到,创建session,把session保存起来,把新创建的sessionID保存到Cookie中;
- 如果sessionID存在,通过sessionID查找到了session对象,那么就不会再创建session对象了;
- 如果创建新的session,浏览器会得到一个包含了sessionID的Cookie,这个Cookie的生命为-1,即只在浏览器内存中存在,如果不关闭浏览器,那么Cookie就会一直存在;
- 下次请求时,再执行request.getSession()方法时,因为可以通过Cookie中的sessionID找到session对象,所以与上一次请求使用的是同一个session对象。
- request.getSession(false):如果Cookie不存在,session也不存在,那么返回NULL,而不会创建session对象;
- request.getSession(true)/request.getSession():两个方法一样,当session对象不存在时,创建session对象
- String getId() 获取sessionID;
- int getMaxInactiveInterval() 获取session最大的不活动时间(秒),默认为30分钟,当session在30分钟内没有使用,那么Tomcat就会在session池中移除;
- void invalidate() 让session失效,调用这个方法会让session失效,当session失效后,客户端再次请求,服务器会给客户端一个新的session;
- boolean isNew() 查看session是否为新的,判断是新创建的,还是从Cookie获取的;
此篇是我在学习过程中参考菜鸟教程以及笔记和别人博客(黑泽君)完成
Java匹马行天下依旧在更新中,欢迎大家关注,感觉可以的可以点击一下推荐,若如有误,感谢指正,谢谢!

作者:泰斗贤若如
微信公众号:去有风的地方飞翔
Github:https://github.com/zyx110
有事微信:zyxt1637039050
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。

我不能保证我所说的都是对的,但我能保证每一篇都是用心去写的,我始终认同: “分享的越多,你的价值增值越大”,我们一同在分享中进步,在分享中成长,越努力越幸运。再分享一句话“十年前你是谁,一年前你是谁,甚至昨天你是谁,都不重要。重要的是,今天你是谁,以及明天你将成为谁。”
人生赢在转折处,改变从现在开始!
支持我的朋友们记得点波推荐哦,您的肯定就是我前进的动力。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?