《Servlet、JSP和Spring MVC初学指南》——第2章 会话管理 2.1URL重写
本节书摘来自异步社区《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; @Override public 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 Pauls 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 dOrsay"); parisAttractions.add("Montmarte"); parisAttractions.add("Sacre Couer Basilica"); @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String city = request.getParameter("city"); if (city != null (city.equals("london") || city.equals("paris"))) { // show attractions showAttractions(request, response, city); } else { // show main page showMainPage(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 / " + " 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 attractions showAttractions(request, response, city); } else { // show main page showMainPage(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注意事项 订阅专栏 Servlet输出流两种方法以及注意事项 HTTP 响应码 以及 各自对应解释 关于 Web API 技术标准的开发文档网站(https://developer.mozilla.org)
异步社区 异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。
相关文章
- Spring表达式语言 之 5.1 概述 5.2 SpEL基础(拾叁)
- 深入实践Spring Boot2.5 小结
- Spring的NamedParameterJdbcTemplate
- JSP文件管理后门工具jsp-file-browser
- Spring中bean的生命周期(最详细)
- spring batch(二):核心部分(1):配置Spring batch
- 注意:Spring Boot 2.7开始spring.factories不推荐使用了,接下来这么玩...
- Spring Cloud Alibaba基础教程:Sentinel使用Apollo存储规则
- 《Servlet、JSP和Spring MVC初学指南》——1.2 Servlet
- 《Servlet、JSP和Spring MVC初学指南》——1.10 处理HTML表单
- 《Servlet、JSP和Spring MVC初学指南》——2.2 隐藏域
- spring boot测试
- spring aop使用,spring aop注解,Spring切面编程
- spring计划任务,springMvc计划任务,Spring@Scheduled,spring定时任务
- Spring官网改版后下载
- 【转】Spring学习---为什么要用spring,springMVC
- 【spring-bean】浅谈Spring的依赖注入(基础)
- 【spring mvc】Spring MVC 的参数解析器ArgumentResolver阐述