四种方式:
- URL重写
- 隐藏域表单
- Cookie技术
- Session技术
目的:如果要保存某些HTTP请求过程中所产生的数据
问题:由于HTTP协议是无状态协议(虽然Socket连接是有状态的,但每次用HTTP协议进行数据传输后就关闭的Socket连接,因此,HTTP协议并不会保存上一次的状态)
解决办法:需要一种类似全局变量的机制保证数据在不同的HTTP请求之间共享。URL重写,隐藏域表单,Session和Cookie可以做到。
一:URL重写
<%@ page language="java" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>URL重写</title>
<script type="text/javascript">
function toUrl(){
var nameVal = document.getElementById("name").value;
var ageVal = document.getElementById("age").value;
//两次编码的原因为,在执行的时候浏览器会进行一次解码操作,但这次操作不一定会解码成功,所以进行两次编码操作,而在servlet中只需要进行一次解码操作(依照页面的编码格式进行编码)
// encodeURI() js中的编码
// decodeURI() js中的解码
//alert(nameVal);
nameVal = encodeURI(nameVal);
nameVal = encodeURI(nameVal);
//alert(nameVal);
location.href="url?name="+nameVal+"&age="+ageVal;
}
</script>
</head>
<body>
<!-- 第一种URL重写的方式 -->
<a href="url?name=admin&age=19&name=team">超链接1</a>
<%-- 第二种URL重写的方式
<c:redirect url="url">
<c:param name="name" value="wwwww"/>
<c:param name="name" value="ttt"/>
<c:param name="age" value="33"/>
</c:redirect>
--%>
<%-- 第三种URL重写的方式
<jsp:forward page="url">
<jsp:param value="qqqq" name="name"/>
<jsp:param value="56" name="age"/>
</jsp:forward>
--%>
<%-- 第四种URL重写的方式 --%>
<input type="text" id="name" />
<input type="text" id="age" />
<button onclick="toUrl()">提交</button>
</body>
</html>
它对应的servlet代码:
package service;
import java.io.IOException;
import java.net.URLDecoder;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/url")
public class URLServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
String age = request.getParameter("age");
System.out.println(name + "\t" + age);
name = URLDecoder.decode(name,"utf-8");// 进行解码操作
System.out.println(name + "\t" + age);
}
}
二:隐藏域表单
目标:实现一个简单的对话页面,即在a页面先输入名称。然后在b页面输入想说的话,再次到b页面,显示刚才说的话,并可以重新说话。
a页面:
<%@ page language="java" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>隐藏域表单技术</title>
</head>
<body>
<form action="b2.jsp" method="post">
<input type="text" name="name" placeholder="请输入昵称" />
<input type="submit" value="登录" />
</form>
</body>
</html>
b页面:
<%@ page language="java" pageEncoding="utf-8" isELIgnored="false"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>隐藏域表单技术</title>
</head>
<body>
<fmt:requestEncoding value="utf-8"/>
<c:if test="${!empty param.content }">
${param.name }:${param.content }
</c:if>
<hr/>
<form action="b2.jsp" method="post">
<input type="hidden" name="name" value="${param.name }" />
<input type="text" name="content" placeholder="请输入内容" />
<input type="submit" value="发送" />
</form>
</body>
</html>
servlet:
三:Cookie技术(浏览器端)
Cookie是通过将数据保存在客户端的硬盘(永久Cookie)或内存(临时Cookie)中来实现数据共享的一种机制。大小限制在4KB
如果不使用setMaxAge方法,Cookie的超时时间为-1,在这种情况下,Cookie就是临时Cookie,也就是说这种Cookie实际上并不保存在客户端硬盘上,而是保存在客户端内存中的。永久Cookie和临时Cookie在第二次向服务端发出HTTP请求时生成Cookie字段。如果第一次将Cookie写入客户端(不管是硬盘还是内存),在同一台机器上第二次访问该网站的jsp页面时,会自动将客户端的cookie作为HTTP请求头的Cookie字段值传给服务端,如果有多个Cookie,中间用";"隔开。
永久Cookie和临时Cookie的区别:
- 永久Cookie:在任意新开启的IE窗口都可以生成Cookie。
- 临时Cookie:由于只保存在当前IE窗口,因此,在新开启的IE窗口,是不能生成Cookie字段的,也就是说,新窗口和旧窗口是不能共享临时Cookie的。使用重定向机制弹出的新窗口也无法和旧窗口共享临时Cookie。但在同一个窗口可以。如在一个IE窗口输入http://localhost:8080/test/first.jsp,向内存写入一个临时Cookie后,在同一个IE窗口输入http://localhost:8080/test/second.jsp,浏览器在向服务端发送HTTP请求时,自动将当前浏览器的临时Cookie(也就是first.jsp所创建的Cookie)和永久Cookie作为HTTP请求头的Cookie字段值发送给服务端。但是如果新启一个IE窗口,由于新IE窗口没有这个临时Cookie,因时就只发送了保存在硬盘上的永久Cookie。
<%@ page language="java" pageEncoding="utf-8" isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Cookie技术</title>
</head>
<c:if test="${!empty cookie.USERNAME.value }">
<c:redirect url="cookie" />
</c:if>
<body>
<form action="cookie" method="post">
账号:<input type="text" name="name" /><br/>
密码:<input type="password" name="pass" /><br/>
记住我:<input type="checkbox" name="re" value="1" /><br/>
<input type="submit" value="登录" />
</form>
</body>
</html>
<%@ page language="java" pageEncoding="utf-8" isELIgnored="false"%>
<html>
<head>
<title>Cookie技术</title>
</head>
<body>
欢迎您,${USERNAME }
</body>
</html>
servlet:
package service;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/cookie")
public class CookieServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 能进入这个方法说明,用户登录信息已经在cookie中保存了
// 取出用户登录信息
Cookie[] cookies = request.getCookies();
String name1 ="";
String pass1 = "";
for (Cookie cookie : cookies) {
String name = cookie.getName();
if("USERNAME".equals(name)) {
name1 = cookie.getValue();
}else if("USERPASS".equals(name)) {
pass1 = cookie.getValue();
}
}
// 你的登录信息必须保存在session中
HttpSession session = request.getSession();
session.setAttribute("USERNAME", name1);
session.setAttribute("USERPASS", pass1);
response.sendRedirect("c2.jsp");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
String pass = request.getParameter("pass");
String re = request.getParameter("re");
// 如果选中了记住我,将用户信息保存到cookie中去
if(re!=null) {
// 产生cookie对象
Cookie cookie1 = new Cookie("USERNAME", name);
Cookie cookie2 = new Cookie("USERPASS", pass);
// 设置cookie的生命周期
cookie1.setMaxAge(60*60*24);
cookie2.setMaxAge(60*60*24);
// 将cookie保存到浏览器中
response.addCookie(cookie1);
response.addCookie(cookie2);
}
// 你的登录信息必须保存在session中
HttpSession session = request.getSession();
session.setAttribute("USERNAME", name);
session.setAttribute("USERPASS", pass);
response.sendRedirect("c2.jsp");
}
}
四:session技术(服务端):
实现一个简单的购物车模板,可以将货物批量添加到购物车,并在购物车显示物品,数量及其总价,还可返回物品列表继续购物。
物品列表:
<%@ page language="java" pageEncoding="utf-8" isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>商品显示</title>
<style type="text/css">
table{
width: 70%;
}
</style>
</head>
<body>
<c:if test="${empty GOODSLIST }">
<c:redirect url="goods" />
</c:if>
<form action="goods" method="post" >
<table border="1">
<tr>
<th>选中</th>
<th>名称</th>
<th>价格</th>
</tr>
<c:forEach var="gi" items="${GOODSLIST }">
<tr>
<td><input type="checkbox" name="check" value="${gi.goodsId }" /></td>
<td>${gi.goodsName }</td>
<td>${gi.goodsPrice }</td>
</tr>
</c:forEach>
<tr>
<td colspan="3">
<input type="submit" value="加入购物车" />
</td>
</tr>
</table>
</form>
<a href="d2.jsp">查看购物车</a>
</body>
</html>
购物车:
<%@ page language="java" pageEncoding="utf-8" isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>购物车显示</title>
<style type="text/css">
table{
width: 70%;
}
</style>
</head>
<body>
<c:set var="sum" value="0"/>
<table border="1">
<tr>
<th>名称</th>
<th>价格</th>
<th>数量</th>
</tr>
<c:forEach var="gi" items="${GWCLIST }">
<tr>
<td>${gi.goodsName }</td>
<td>${gi.goodsPrice }</td>
<td>${gi.goodsNum }</td>
<c:set var="sum" value="${sum+gi.goodsPrice*gi.goodsNum }"/>
</tr>
</c:forEach>
<tr>
<td colspan="3">
总价:${sum }
</td>
</tr>
</table>
<a href="d1.jsp">继续购物</a>
</body>
</html>
servlet:
package service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import bean.GoodsInfo;
import dao.GoodsInfoDAO;
@WebServlet("/goods")
public class GoodsServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
private GoodsInfoDAO gidao = new GoodsInfoDAO();
// 负责显示商品列表
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().setAttribute("GOODSLIST", gidao.findAllGoods());//将查询结果放入session容器
response.sendRedirect("d1.jsp");//重定向
}
// 负责加入购物车
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();//获取session对象
String[] ids = request.getParameterValues("check");//获取已选物品的id列表
// 将选中的商品加入到购物车中
// 首先判断购物车是否存在
List<GoodsInfo> list = null;
if(session.getAttribute("GWCLIST")==null) {//当还没有选任何物品的时候,需要新建一个浏览器接收用来显示的容器
list = new ArrayList<GoodsInfo>();
}else {//如果已经有了这个容器,并且是浏览器方利用session容器将其包含再传过来的,那就获取到这个容器
list = (List<GoodsInfo>)session.getAttribute("GWCLIST");
}
// 将选中的商品加入到购物车(GWCLIST)中
for (String id : ids) {//现在只需要将已选列表添加到显示容器中
int i = Integer.parseInt(id);
GoodsInfo gi = gidao.findById(i);
// 如果商品存在购物车,则数量+1,否则添加进入购物车
int index = list.indexOf(gi);
if(index==-1) { //不存在
gi.setGoodsNum(1);
list.add(gi);
}else { //存在
gi = list.get(index);
gi.setGoodsNum(gi.getGoodsNum()+1);
}
}
session.setAttribute("GWCLIST", list);//将显示列表添加到session并起名为GWCLIST
response.sendRedirect("d1.jsp");//重定向
}
}
总结: