本节书摘来自异步社区《Servlet、JSP和Spring MVC初学指南》一书中的第2章,第2.1节,作者:【加】Budi Kurniawan(克尼亚万) , 【美】Paul Deck著,更多章节内容可以访问云栖社区“异步社区”公众号查看

第2章 会话管理

由于HTTP的无状态性,使得会话管理或会话跟踪成为Web应用开发一个无可避免的主题。默认下,一个Web服务器无法区分一个HTTP请求是否为第一次访问。

例如,一个Web邮件应用要求用户登录后才能查看邮件,因此,当用户输入了相应的用户名和密码后,应用不应该再次提示需要用户登录,应用必须记住哪些用户已经登录。换句话说,应用必须能管理用户的会话。

本章将阐述4种不同的状态保持技术:URL重写、隐藏域、cookies和HTTPSession对象。本章的示例代码为app02a。

2.1 URL重写

URL重写是一种会话跟踪技术,它将一个或多个token添加到URL的查询字符串中,每个token通常为key=value形式,如下:

url?key-1=value-1&key-2=value-2 ... &key-n=value-n
注意,URL和tokens间用问号(?)分割,token间用与号(&)。

URL重写适合于tokens无须在太多URL间传递的情况下,然而它有如下限制:

URL在某些浏览器上最大长度为2000字符;
若要传递值到下一个资源,需要将值插入到链接中,换句话说,静态页面很难传值;
URL重写需要在服务端上完成,所有的链接都必须带值,因此当一个页面存在很多链接时,处理过程会是一个不小的挑战;
某些字符,例如空格、与和问号等必须用base64编码;
所有的信息都是可见的,某些情况下不合适。
因为存在如上限制,URL重写仅适合于信息仅在少量页面间传递,且信息本身不敏感。

清单2.1中的Top10Servlet类会显示最受游客青睐的10个伦敦和巴黎的景点。信息分成两页展示,第一页展示指定城市的5个景点,第二页展示另外5个。该Servlet使用URL重写来记录所选择的城市和页数。该类扩展自HttpServlet,并通过/top10访问。

清单2.1 Top10Servlet类

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;@WebServlet(name = "Top10Servlet", urlPatterns = { "/top10" })
public class Top10Servlet extends HttpServlet {private static final long serialVersionUID = 987654321L;private List<String> londonAttractions;private List<String> parisAttractions;@Overridepublic void init() throws ServletException {londonAttractions = new ArrayList<String>(10);londonAttractions.add("Buckingham Palace");londonAttractions.add("London Eye");londonAttractions.add("British Museum");londonAttractions.add("National Gallery");londonAttractions.add("Big Ben");londonAttractions.add("Tower of London");londonAttractions.add("Natural History Museum");londonAttractions.add("Canary Wharf");londonAttractions.add("2012 Olympic Park");londonAttractions.add("St Paul's Cathedral");parisAttractions = new ArrayList<String>(10);parisAttractions.add("Eiffel Tower");parisAttractions.add("Notre Dame");parisAttractions.add("The Louvre");parisAttractions.add("Champs Elysees");parisAttractions.add("Arc de Triomphe");parisAttractions.add("Sainte Chapelle Church");parisAttractions.add("Les Invalides");parisAttractions.add("Musee d'Orsay");parisAttractions.add("Montmarte");parisAttractions.add("Sacre Couer Basilica");}@Overridepublic void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {String city = request.getParameter("city");if (city != null &&(city.equals("london") || city.equals("paris"))) {// show attractionsshowAttractions(request, response, city);} else {// show main pageshowMainPage(request, response);}}private void showMainPage(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {response.setContentType("text/html");PrintWriter writer = response.getWriter();writer.print("<html><head>" +"<title>Top 10 Tourist Attractions</title>" +"</head><body>" +"Please select a city:" +"<br/><a href='?city=london'>London</a>" +"<br/><a href='?city=paris'>Paris</a>" +"</body></html>");}private void showAttractions(HttpServletRequest request,HttpServletResponse response, String city)throws ServletException, IOException {int page = 1;String pageParameter = request.getParameter("page");if (pageParameter != null) {try {page = Integer.parseInt(pageParameter);} catch (NumberFormatException e) {// do nothing and retain default value for page}if (page > 2) {page = 1;}            }List<String> attractions = null;if (city.equals("london")) {attractions = londonAttractions;} else if (city.equals("paris")) {attractions = parisAttractions;}response.setContentType("text/html");PrintWriter writer = response.getWriter();writer.println("<html><head>" +"<title>Top 10 Tourist Attractions</title>" +"</head><body>");writer.println("<a href='top10'>Select City</a> ");writer.println("<hr/>Page " + page + "<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'/>" +"<a href='?city=" + city +"&page=1'>Page 1</a>");writer.println("&nbsp; <a href='?city=" + city +"&page=2'>Page 2</a>");writer.println("</body></html>");}
}

init方法,仅当该servlet第一次被用户访问时调用,构造两个类级别的列表,londonAttractions和parisAttractions,每个列表有10个景点。

doGet方法,该方法每次请求时被调用,检查URL中是否包括请求参数city,并且其值是否为“london”或“paris”,方法据此决定是调用showAttractions方法还是showMainPage方法:

String city = request.getParameter("city");if (city != null &&(city.equals("london") || city.equals("paris"))) {// show attractionsshowAttractions(request, response, city);} else {// show main pageshowMainPage(request, response);}

用户一开始访问该servlet时不带任何请求参数,此时调用showMainPage,该方法发送两个链接到浏览器,每个链接都包含token:city=cityName。用户所见如图2.1所示,现在用户可以选择一个城市。

图2.1 Top10Servlet的初始页面

如果你查看网页源代码,你会看见如下HTML:

Please select a city:<br/>
<a href='?city=london'>London</a><br/>
<a href='?city=paris'>Paris</a>

请注意a元素中的href属性,该属性值包括一个问号加token city=london或city=paris. 注意,此处为相对URL,即URL中没有协议部分,相对于当前页面。因此,若你点击了任一链接,则会提交

http://localhost:8080/app02a/top10?city=london

http://localhost:8080/app02a/top10?city=paris
到服务器上。

根据用户所点击的链接,doGet方法识别请求参数的city值并传递给showAttractions方法,该方法会检查URL中是否包含page参数,如果没有该参数或该参数值无法转换为数字,则该方法设定page参数值为1,并将头5个景点发给客户端。图2.2为选择伦敦时的界面。

showAttractions方法还发送了3个链接到客户端:Select City、Page 1和Page 2。Select City 是无参数访问servlet,Page 1和Page 2链接包括两个tokens,即city和page:

http://localhost:8080/app02a/top10?city=cityName&page=pageNumber
若选择了伦敦,并点击了Page 2,则将以下URL发送给服务端:

http://localhost:8080/app02a/top10?city=london&page=2

图2.2 伦敦前十景点,第一页

此时系统会展示伦敦的另外5个景点,如图2.3所示。

图2.3 伦敦前十景点,第二页

本例展示了如何用URL重写技术来传递参数——city到服务端以便服务端能正确展示。

《Servlet、JSP和Spring MVC初学指南》——第2章 会话管理 2.1URL重写相关推荐

  1. Servlet JSP和Spring MVC初学指南 PDF

    下载地址:网盘下载 Servlet和JSP是开发Java Web应用程序的两种基本技术.Spring MVC是Spring框架中用于Web应用快速开发的一个模块,是当今流行的Web开发框架之一. 本书 ...

  2. Spring MVC学习指南(11-12章总结)

    11:上传文件 将介绍如何在SpringMVC中使用Commons FileUpload和Servlet 3上传文件. 在填写表单的html中,必须将html的enctype属性值设置为multipa ...

  3. Spring MVC学习指南(1-4章总结)

    Spring 框架 1.0 前言 依赖注入: 构造器(构造注入) set方法(设值注入) filed方式 (必须引入org......anntation.Autowired) 如何配置依赖注入: XM ...

  4. Spring MVC学习指南(5-7章总结)

    列表内容 5:数据绑定和表单标签 数据绑定是指将用户输入绑定到领域模型(domain). 表单标签库包含了 可以在JSP页面中渲染HTML元素的标签. 典型的有form.input.options等. ...

  5. server.servlet.contextPath 和 spring.mvc.servlet.path 对比

    @RestController @RequestMapping("/v1") class Controller {} 更通用的方法 spring.mvc.servlet.path= ...

  6. Spring MVC 入门指南(二):@RequestMapping用法详解

    为什么80%的码农都做不了架构师?>>>    一.@RequestMapping 简介 在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指 ...

  7. MyBatis+Spring MVC开发指南(一)

    前言 MyBatis+Spring MVC这套组合,在实际互联网项目中非常流行,博主工作中也涉及过,打算由浅入深.系统的写出来!这个系列将会涵盖MyBatis开发详解.Spring MVC开发详解,以 ...

  8. MVC框架详解--Servlet+JSP+JavaBean模式(MVC)开发复杂的web应用

    孤傲苍狼 javaweb学习总结(二十二)--基于Servlet+JSP+JavaBean开发模式的用户登录注册 转载于:https://www.cnblogs.com/yangjj08/p/1015 ...

  9. Spring MVC 中使用AOP 进行统一日志管理--XML配置实现

    1.介绍 上一篇博客写了使用AOP进行统一日志管理的注解版实现,今天写一下使用XML配置实现版本,与上篇不同的是上次我们记录的Controller层日志,这次我们记录的是Service层的日志.使用的 ...

最新文章

  1. CPL DPL RPL的区别 一致性代码段和非一致性代码段
  2. QTableview 获取鼠标坐标的item(QModelIndex)
  3. 《大话数据结构》第9章 排序 9.3 冒泡排序(下)
  4. 【CV】综述:基于深度学习的视觉跟踪方法进展
  5. Android开发之判断任意View上拉的方法
  6. oracle数据库删除百万级数据库,数据库SQL优化大总结之 百万级数据库优化方案...
  7. JDK source 之 ArrayList 需要注意事项
  8. rpgmvp图片怎么看_拼多多商城图片和视频下载不了怎么办,看这里。。。。
  9. String、StringBuilder和StringBuffer的区别和用法
  10. php pc_base,phpcms二次开发之base.php的桥梁作用_PHP教程
  11. Java数组在内存中的分配
  12. JAVA基础--toString, equals方法
  13. 产品出口到沙特要做SGS或BV的清关SASO证书,请问哪里办理最迅速?
  14. c语言recy未定义标识符,求解这个C语言子程序什么意思
  15. UVa OJ 126 - The Errant Physicist (粗心的物理学家)
  16. win10切换视图快捷键and其他
  17. CCF 20180916 买菜 JAVA版本
  18. Dockerflie概述
  19. 银联在线Java接口开发
  20. 三大模块推动畜牧业绿色发展,HaaS构建智慧养鹿综合解决方案

热门文章

  1. 达芬奇密码 第九十二章
  2. 关于编程学习的七点思索
  3. win10固态硬盘分区 整数_送给“毒奶粉”以及win7党!win10如何重装win7?
  4. Python学习笔记—第二章—IPython
  5. 高中毕业,要选专业,有什么好的专业推荐吗?
  6. EBS系统安全性校验
  7. Python源码剖析pdf
  8. 图神经网络相关论文整理
  9. 机器学习模型的数据预处理和可视化
  10. word实用操作:几个关于录入和排版的小妙招