Servlet会话管理一(URL重写和表单隐藏域)
会话可以简单的理解为客户端用户打开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器的整个过程称为一个会话。即一个客户端用户和服务器端进行通讯的过程,也是客户端和服务器端之间的数据传输过程。
HTTP协议的无状态性导致web服务器无法区分一个HTTP请求是否为第一次访问,因此需要程序必须能管理会话,并为每个用户保存其与服务器交互过程中产生的数据。
会话管理就是管理浏览器客户端和服务器端之间会话过程中产生的数据。
Servlet有4中不同的状态保持技术:
-- URL重写(token-based会话跟踪技术)
-- 表单隐藏域(仅当网页中有表单时使用) <input type="hidden" name="field_name" value="value">
-- cookies(客户端技术,数据保存在客户端)
-- HTTPSession(服务器端技术,数据保存在服务器端)
URL重写 (token-based会话跟踪技术)
将一个或多个token添加到URL的查询字符串中,每个token通常为 key=value 的形式。其中,URL和token之间用 ? 分隔,token之间用 & 分隔。
URL重写仅适合于信息仅在少量页面间传递,且信息本身不敏感的情况
数据通过URL后面的token传递到下一个页面,在下一个页面(即下一个http请求)中,通过获取request.getParameter(name)获取tonken的值,从而保证了数据在不同页面间的传递 。
请表单的提交方式为get时,表单中的参数也会显示的出现在URL后面



package app02a.urlrewriting; import java.io.IOException;
import java.io.PrintWriter;
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; /**
* Servlet implementation class Top10Servlet
*/
@WebServlet(name = "Top10Servlet", urlPatterns = { "/top10" })
public class Top10Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private List<String> londonAttractions;
private List<String> parisAttractions; public Top10Servlet() {
super();
}
@Override
public void init() throws ServletException { // 用户第一次访问时,Tomcat初始化Servlet,init()方法被调用。
londonAttractions = new ArrayList<String>(10); // 赋值类的成员变量
londonAttractions.add("1.Buckingham Palace");
londonAttractions.add("2.Lodon Eye");
londonAttractions.add("3.British Museum");
londonAttractions.add("4.National Gallery");
londonAttractions.add("5.Big Ben");
londonAttractions.add("6.Tower of London");
londonAttractions.add("7.Natural History Museum");
londonAttractions.add("8.Canary Wharf");
londonAttractions.add("9.2012 Olympic Park");
londonAttractions.add("10.ST Paul's Cathedral"); parisAttractions = new ArrayList<String>(10); // 赋值类的成员变量
parisAttractions.add("1.Eiffel Tower");
parisAttractions.add("2.Notre Dame");
parisAttractions.add("3.The Louver");
parisAttractions.add("4.Champs Elysees");
parisAttractions.add("5.Arc de Triomphe");
parisAttractions.add("6.Sainte Chapelle Church");
parisAttractions.add("7.Les Invalides");
parisAttractions.add("8.Muess d'Orsay");
parisAttractions.add("9.Montmarte");
parisAttractions.add("10.Sacre Couer Basilica");
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String city = request.getParameter("city"); // 获取token的值,该token随URL传递过来
if (city != null && (city.equals("london") || city.equals("paris"))) {
showAttractions(request, response, city);
} else {
showMainPage(request, response);
}
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
private void showMainPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter writer = response.getWriter(); // 向客户端发送信息
writer.println("<html>");
writer.println("<head>");
writer.println("<title>Top10 Tourist Atrractions</title>");
writer.println("</head>");
writer.println("<body>");
writer.println("Please select a city:<br />");
writer.println("<a href='?city=london'>London</a><br />"); // 相对url,由 http://localhost:8080/top10/top10
writer.println("<a href='?city=paris'>Paris</a><br />"); // 变为 http://localhost:8080/top10/top10?city=london
writer.println("</body>"); // 并将后者发送到服务器
writer.println("</html>");
}
private void showAttractions(HttpServletRequest request, HttpServletResponse response, String city) throws ServletException, IOException {
int page = 1;
String pageParameter = request.getParameter("page"); // 获取token的值
if (pageParameter != null) {
try {
page = Integer.parseInt(pageParameter);
}catch(NumberFormatException e) {
e.printStackTrace();
}
if (page > 2) {
page = 1;
}
}
List<String> attractions = null;
if (city.equals("london")) {
attractions = londonAttractions;
} else {
attractions = parisAttractions;
}
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
writer.println("<html>");
writer.println("<head>");
writer.println("<title>Top 10 Tourist Attractions</title>");
writer.println("</head>");
writer.println("<body>");
writer.println("<a href='top10'>Select City</a>"); // 相对url 由 http://localhost:8080/top10/top10?city=london
writer.println("<hr />"); // 变为 http://localhost:8080/top10/top10
writer.println("Page " + page);
writer.println("<hr />");
int start = page * 5 -5;
for (int i = start; i < start + 5; i++) {
writer.println(attractions.get(i) + "<br />");
}
writer.print("<hr style='color:blue' />");
writer.println("<a href='?city=" + city + "&page=1'>Page 1</a>"); // 由 localhost:8080/top10/top10?city=london 变为 localhost:8080/top10/top10?city=london&page=1
writer.println(" <a href='?city=" + city + "&page=2'>Page 2</a>"); // 由 localhost:8080/top10/top10?city=london 变为 localhost:8080/top10/top10?city=london&page=2
writer.println("</body>");
writer.println("</html>");
}
}
表单隐藏域(仅当网页中有表单时有效)
使用隐藏域来保存会话过程中的数据是将值放到HTML表单的隐藏域中。当表单提交时,隐藏域的值也同时提交到服务器端。
<input type="hidden" name="field_name" value="value">
该技术较URL重写相比,没有字符的限制,同时无需额外编码,但也不适合跨越多个页面。
package app02a.hiddenfields; import java.io.IOException;
import java.io.PrintWriter;
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; @WebServlet(name = "CustomerServlet", urlPatterns = { "/customer", "/editCustomer", "/updateCustomer" })
public class CustomerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private List<Customer> customers = new ArrayList<Customer>(); // 类的成员变量 public CustomerServlet() {
super();
} @Override
public void init() throws ServletException { // 初始化两个数据,正常情况下,这些数据应该存储在数据库中
Customer customer1 = new Customer();
customer1.setId(1);
customer1.setName("Donal D.");
customer1.setCity("Miami");
customers.add(customer1); Customer customer2 = new Customer();
customer2.setId(2);
customer2.setName("Micky M.");
customer2.setCity("Orlando");
customers.add(customer2);
} private void sendCustomerList(HttpServletResponse response) throws IOException {
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
writer.println("<html>");
writer.println("<head>");
writer.println("<title>Customers</title>");
writer.println("</head>");
writer.println("<body>");
writer.println("<h2>Customers</h2>");
writer.println("<ul>");
for (Customer customer : customers) {
writer.println("<li>" + customer.getName() + " (" + customer.getCity() + ") (<a href='editCustomer?id=" + customer.getId() + "'>edit</a>)</li>"); // URL重写方式
}
writer.println("</ul>");
writer.println("</body>");
writer.println("</html>");
} private Customer getCustomer(int customerId) {
for (Customer customer : customers) {
if (customer.getId() == customerId) {
return customer;
}
}
return null;
} private void sendEditCustomerForm(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
int customerId = 0;
try {
customerId = Integer.parseInt(request.getParameter("id")); // 将String类型装换成int类型
} catch (NumberFormatException e) {
e.printStackTrace();
}
Customer customer = getCustomer(customerId);
if (customer != null) {
writer.println("<html>");
writer.println("<head>");
writer.println("<title>Edit Customer</title>");
writer.println("</head>");
writer.println("<body>");
writer.println("<h2>Edit Customer</h2>");
writer.println("<form method='post' action='updateCustomer'>");
writer.println("<input type='hidden' name='id' value='" + customerId + "' />"); // 隐藏域 用于传递数据
writer.println("<table>");
writer.println("<tr>");
writer.println("<td>Name:</td>");
writer.println("<td><input name='name' value='" + customer.getName().replaceAll("'", "'") + "' /></td>"); //'编码单引号
writer.println("</tr>");
writer.println("<tr>");
writer.println("<td>City:</td>");
writer.println("<td><input name='city' value='" +customer.getCity().replaceAll("'", "'") + "' /></td>");
writer.println("</tr>");
writer.println("<tr>");
writer.println("<td colspan='2' style='text-align:right'><input type='submit' value='Update' /></td>");
writer.println("</tr>");
writer.println("<tr>");
writer.println("<td colspan='2'><a href='customer'>Customer List</a></td>");
writer.println("</tr>");
writer.println("</table>");
writer.println("</form>");
writer.println("</body>");
writer.println("</html>");
} else {
writer.println("No customer found!");
}
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String uri = request.getRequestURI();
if (uri.endsWith("/customer")) {
sendCustomerList(response);
} else if (uri.endsWith("/editCustomer")) {
sendEditCustomerForm(request, response);
}
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int customerId = 0;
try {
customerId = Integer.parseInt(request.getParameter("id")); // 获取隐藏域中的值
} catch (NumberFormatException e) {
e.printStackTrace();
}
Customer customer = getCustomer(customerId);
if (customer != null) {
customer.setName(request.getParameter("name"));
customer.setCity(request.getParameter("city"));
}
sendCustomerList(response);
}
}



cookies(客户端技术,数据保存在客户端)
Servlet会话管理一(URL重写和表单隐藏域)的更多相关文章
- jquery.validate 使用--验证表单隐藏域
jQuery validate很不错的一个jQuery表单验证插件.升级到了1.9版的后,发现隐藏表单域验证全部失效,特别是在jquery.ui.tabs.min.js构造的Tabs里的验证. 是因为 ...
- 表单隐藏域与display:none
有时候前端进行表单填写是分步骤的,每一步的时候其他步骤相关的表单视图不可见: 针对"不可见",以下有两种处理方式: ①display:none 这种方式呢,比较简单,就是将三个步骤 ...
- Servlet会话管理三(HttpSession)
Session是服务器端技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的HttpSession对象.由于Session为浏览器用户所独享,所以用户在访问服务器的web资源时,可以把各自的数 ...
- 【ASP.NET Web API教程】5.2 发送HTML表单数据:URL编码的表单数据
原文:[ASP.NET Web API教程]5.2 发送HTML表单数据:URL编码的表单数据 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内 ...
- Servlet之会话(Session)以及会话追踪技术(Cookie),(URL重写)和(隐藏表单域)
Session 什么是会话? 会话: Web应用中的会话 指的是一个客户端浏览器与Web服务器之间连续发生的一系列请求和响应的过程 会话状态: Web服务器和浏览器在会话的过程中产生的状态信息 作用: ...
- servlet 会话管理
一.URL 重写 URL 重写是一种会话跟踪技术,它将一个或多个token添加到URL的查询字符串中,每个token通常为 key=value形式,如下: url?key-1=value-1& ...
- Java Web(三) Servlet会话管理
会话跟踪 什么是会话? 可简单理解为,用户打开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭服务器,整个过程称为一个会话.从特定客户端到服务器的一系列请求称为会话.记录会话信息的技术称 ...
- Servlet会话管理二(Cookie)
Cookie是在HTTP协议下,将服务器传递给浏览器的的少量信息保存到浏览器客户端的一种技术,通过这种技术,即使在浏览器被关闭或链接中断的情况下,用户仍可以维护Cookie中的数据. Cookie是经 ...
- Java EE.Servlet.会话管理
一次会话是从客户打开浏览器开始到关闭浏览器结束.记录会话信息的技术称为会话跟踪.常见的会话跟踪技术有Cookie.URL重写和隐藏表单域. 1.Cookie Cookie是一小块可以嵌入到HTTP请求 ...
随机推荐
- Java的学习02
今天依旧记录一下今天的学习的知识. /** * 测试StringBuilder StringBuffer,可变字符序列 * String对象称为“不可变对象"指的是对象内部成员变量的值无法再 ...
- chrome 扩展 调试
开发chrome扩展,有时候需要输出console.log 通常调试的popup.html.content_script.backgroup.html等 但是有一些是没有这些的 1.推荐一个扩展: h ...
- MySQL 事务 隔离级别
前两天面试,问到了四种隔离级别,当时觉得大多数数据库都为read committed,结果没想到mysql是个例外.在此做一下隔离级别和各种数据库锁的使用. 首先说一下ACID四大特性: 四大特性 ...
- layout_weight 全解析
[layout_weight 全解析] 参考:http://www.cnblogs.com/net168/p/4227144.html
- nginx配置 解决ajax请求跨域问题
文章来源:http://to-u.xyz/2016/06/30/nginx-cors/ 背景描述 最近在研究RESTful API接口设计,使用的是Nginx,要实现本地http://127.0.0. ...
- 最完整Android Studio插件整理 (转)
转自:http://blog.csdn.net/alpha58/article/details/62881144 现在Android的开发者基本上都使用android Studio进行开发(如果你还在 ...
- php 更新array键值
$arr1 = array("loginname" => "username","psw" => "password& ...
- 有人说,即使没有JavaScript,你也可以做网页。在纯HTML
有人说,即使没有JavaScript,你也可以做网页.在纯HTML +服务器端语言理论中也可以完成所有功能,那么,为什么以及在哪里存在JavaScript? JS,全称JavaScript 在 ...
- 1. Two Sum (快速排序;有序数组的查找: 两个指针; 哈希表)
Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...
- 英文谚语:Take that with a grain of salt
take sth. with a grain of salt 这个习语的字面意思是“和一撮盐一起吃下去”,为什么要与盐一起吃呢? 据说这个习语要追溯到罗马时代,罗马将军庞培曾发现一种解毒剂,必须和着一 ...