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请求 ...
随机推荐
- node.js fs、http使用
学习node核心模块http.fs;的使用 首先在server.js文件中require两个模块http.fs; let fs = require('fs')let http = require (' ...
- SVM参数解析
一.Opencv中的核函数定义(4种): 1.CvSVM::LINEAR : 线性内核,没有任何向映射至高维空间,线性区分(或回归)在原始特点空间中被完成,这是最快的选择. 2.CvSVM::POLY ...
- mui-webview-子页面调用父页面的js方法
子页面// 获取当前webviewvar self = plus.webview.currentWebview();var opener = self.opener();//此句调用父页面jsopen ...
- create-react-app之proxy
[create-react-app之proxy] create-react-app可以用于一键创建web_client环境,默认使用webpack-dev-server.但在开发过程中,往往需要cli ...
- Link & Redirect
[Link] Link标签,用于实现React-Router功能的跳转.(意思是就不要使用a标签了) 1)to:string,指明要跳转的path. import { Link } from 'rea ...
- 齐博CMS:最常用的一些变量名,方便二次开发.必须要熟悉的
ROOT_PATH程序所在硬盘目录的绝对地址,等同于以前的PHP168_PATH$webdb网站的全局变量,模块的全局变量也是这个$onlineip当前用户的IP$timestamp当前时间$WEBU ...
- 关于cdh 5.X 的agent 客户端镜像安装注意事项
当把客户端镜像安装时,每个客户端程序会生成UUID作为唯一标识,重新 安装时要删除 rm -rf /var/lib/cloudera-scm-agent 如果不删除会造成主机列表中IP一直在变的情况.
- MySQL千万级数据分区存储及查询优化
作为传统的关系型数据库,MySQL因其体积小.速度快.总体拥有成本低受到中小企业的热捧,但是对于大数据量(百万级以上)的操作显得有些力不从心,这里我结合之前开发的一个web系统来介绍一下MySQL数据 ...
- SQL SERVER数据库性能优化之SQL语句篇
(引用自重明鸟的博客,方便学习和查看) 1. 按需索取字段,跟“SELECT *”说拜拜 字段的提取一定要按照“用多少提多少”的原则,避免使用“SELECT *”这样的操作.做了这样一个实验,表tbl ...
- Specified key was too long; max key length is 767 bytes
MySQL) )); Database changed ERROR (): Specified bytes drop table if exists test; ) primary key)chars ...