我的重构哪里不规范?讨论第2页

Posted on

我的重构哪里不规范?讨论第2页

您还未登录 ! 我的应用 登录 注册

JavaEye-最棒的软件开发交流社区

论坛首页软件开发和项目管理版软件测试

我的重构哪里不规范?

全部 项目管理 敏捷开发 软件测试 配置管理 UseCase UML 单元测试 XP TDD UP CMM « 上一页 1 2 3 4 5 下一页 »

浏览 17393 次 锁定老贴子 主题:我的重构哪里不规范?

精华帖 (3) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (1) 作者 正文 * gigix

  • 等级: 资深会员资深会员
  • gigix的博客
  • 文章: 4810
  • 积分: 2991
  • 来自: 北京
  • 发表时间:2007-06-15

< > 猎头职位: 北京: Java搜索工程师

ojava 写道 公司新加代码规范条目:所定义的方法尽量不要超过100行。 某一方面来说,可以避免这种流水账式的代码吧! 并且强制我们进行Xiaohanne所说的面向接口不要面向实现的编程。 TDD is THE solution of your problem: you just can't write a test for a hundred-lines-long method. Actually, in normal cases, methods should not be longer than 10 lines. (I'd say 5 lines indeed.) 返回顶楼 回帖地址

0 0 请登录后投票 * 诺铁

  • 等级: 四星会员
  • 诺铁的博客
  • 文章: 277
  • 积分: 398
  • 发表时间:2007-06-15

因为要后续使用而把局部变量提到成员变量是最差的作法。 你需要的不是重构,是重设计。 返回顶楼 回帖地址

0 0 请登录后投票 * gigix

  • 等级: 资深会员资深会员
  • gigix的博客
  • 文章: 4810
  • 积分: 2991
  • 来自: 北京
  • 发表时间:2007-06-15

诺铁 写道

因为要后续使用而把局部变量提到成员变量是最差的作法。 你需要的不是重构,是重设计。 please man ... sigh 返回顶楼 回帖地址

0 0 请登录后投票 * xly_971223

  • 等级: 五星会员
  • xly_971223的博客
  • 文章: 1048
  • 积分: 650
  • 来自: 北京
  • 发表时间:2007-06-15

ojava 写道

公司新加代码规范条目:所定义的方法尽量不要超过100行。 某一方面来说,可以避免这种流水账式的代码吧! 并且强制我们进行Xiaohanne所说的面向接口不要面向实现的编程。 100行?太长了吧 我一般情况保持在20行左右 返回顶楼 回帖地址

0 0 请登录后投票 * gigix

  • 等级: 资深会员资深会员
  • gigix的博客
  • 文章: 4810
  • 积分: 2991
  • 来自: 北京
  • 发表时间:2007-06-15

xly_971223 写道

ojava 写道

公司新加代码规范条目:所定义的方法尽量不要超过100行。 某一方面来说,可以避免这种流水账式的代码吧! 并且强制我们进行Xiaohanne所说的面向接口不要面向实现的编程。 100行?太长了吧 我一般情况保持在20行左右 3.5 lines in average 返回顶楼 回帖地址

0 0 请登录后投票 * xly_971223

  • 等级: 五星会员
  • xly_971223的博客
  • 文章: 1048
  • 积分: 650
  • 来自: 北京
  • 发表时间:2007-06-15

诺铁 写道

因为要后续使用而把局部变量提到成员变量是最差的作法。 你需要的不是重构,是重设计。 重构跟重新设计是冲突的吗 在功能不变的情况下,我们可以通过重新设计完成重构 返回顶楼 回帖地址

0 0 请登录后投票 * xly_971223

  • 等级: 五星会员
  • xly_971223的博客
  • 文章: 1048
  • 积分: 650
  • 来自: 北京
  • 发表时间:2007-06-15

gigix 写道

xly_971223 写道

ojava 写道

公司新加代码规范条目:所定义的方法尽量不要超过100行。 某一方面来说,可以避免这种流水账式的代码吧! 并且强制我们进行Xiaohanne所说的面向接口不要面向实现的编程。 100行?太长了吧 我一般情况保持在20行左右 3.5 lines in average 这个。。。。 有点难度 。。。 返回顶楼 回帖地址

0 0 请登录后投票 * 抛出异常的爱

  • 等级: 五钻会员
  • 抛出异常的爱的博客
  • 文章: 12053
  • 积分: 2782
  • 来自: 北京
  • 发表时间:2007-06-15

javastudy 写道

ojava 写道

公司新加代码规范条目:所定义的方法尽量不要超过100行。 某一方面来说,可以避免这种流水账式的代码吧! 并且强制我们进行Xiaohanne所说的面向接口不要面向实现的编程。 得在设计时就得想到拉 我只能说呸。。。。只有日本人能想的到。。。 返回顶楼 回帖地址

0 0 请登录后投票 * sg552

  • 等级: 一星会员
  • sg552的博客
  • 文章: 566
  • 积分: 141
  • 来自: 北京
  • 发表时间:2007-06-15

重构—— 改善现有代码的设计。 看看这本书吧。LZ 另外,多测试,常测试,保证每个重构都是成功的。 至于具体细节,就要看经验了。 返回顶楼 回帖地址

0 0 请登录后投票 * gigix

  • 等级: 资深会员资深会员
  • gigix的博客
  • 文章: 4810
  • 积分: 2991
  • 来自: 北京
  • 发表时间:2007-06-15

javastudy 写道

gigix 写道

xly_971223 写道

ojava 写道

公司新加代码规范条目:所定义的方法尽量不要超过100行。 某一方面来说,可以避免这种流水账式的代码吧! 并且强制我们进行Xiaohanne所说的面向接口不要面向实现的编程。 100行?太长了吧 我一般情况保持在20行左右 3.5 lines in average 有点太短了吧 that's our stat in previous project you can try to show me an example: why do you need a method longer than 5 lines? (some complex algorithm implementations are exceptions.) 返回顶楼 回帖地址

0 0 请登录后投票

« 上一页 1 2 3 4 5 下一页 » 论坛首页软件开发和项目管理版软件测试 跳转论坛:Java编程和Java企业应用 Web前端技术 移动编程和手机应用开发 C/C++编程 Ruby编程 Python编程 PHP编程 Flash编程和RIA Microsoft .Net 综合技术 软件开发和项目管理 行业应用 入门讨论 招聘求职 海阔天空

© 2003-2010 JavaEye.com. 上海炯耐计算机软件有限公司版权所有 [ 沪ICP备05023328号 ]

华山论session和cookie机制

Posted on

华山论session和cookie机制

会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。

一.cookie和session机制之间的区别和联系

 具体来说cookie机制采用的是在客户端保持状态的方案。它是在用户端的会话状态的存贮机制,他需要用户打开客户端的cookie支持。cookie的作用就是为了解决HTTP协议无状态的缺陷所作的努力.而session机制采用的是一种在客户端与服务器之间保持状态的解决方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的。而session提供了方便管理全局变量的方式
  session是针对每一个用户的,变量的值保存在服务器上,用一个sessionID来区分是哪个用户session变量,这个值是通过用户的浏览器在访问的时候返回给服务器,当客户禁用cookie时,这个值也可能设置为由get来返回给服务器。就安全性来说:当你访问一个使用session 的站点,同时在自己机子上建立一个cookie,建议在服务器端的SESSION机制更安全些.因为它不会任意读取客户存储的信息。
    正统的cookie分发是通过扩展HTTP协议来实现的,服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。从网络服务器观点看所有HTTP请求都独立于先前请求。就是说每一个HTTP响应完全依赖于相应请求中包含的信息。状态管理机制克服了HTTP的一些限制并允许网络客户端及服务器端维护请求间的关系。在这种关系维持的期间叫做会话(session)。
    Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器。IETF RFC 2965 HTTP State Management Mechanism 是通用cookie规范。网络服务器用HTTP头向客户端发送cookies,在客户终端,浏览器解析这些cookies并将它们保存为一个本地文件,它会自动将同一服务器的任何请求缚上这些cookies

二.理解session机制 session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识—— 称为 session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个 session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个 session id将被在本次响应中返回给客户端保存。 保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于SEEESIONID,而。比如weblogic对于web应用程序生成的cookie,JSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是 JSESSIONID。由于cookie可以被人为的禁止,必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面,附加方式也有两种,一种是作为URL路径的附加信息,表现形式为http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764 另一种是作为查询字符串附加在URL后面,表现形式为http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764 这两种方式对于用户来说是没有区别的,只是服务器在解析的时候处理的方式不同,采用第一种方式也有利于把session id的信息和正常程序参数区分开来。为了在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。 另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。这种技术现在已较少应用,笔者接触过的很古老的iPlanet6(SunONE应用服务器的前身)就使用了这种技术。实际上这种技术可以简单的用对action应用URL重写来代替。 在谈论session机制的时候,常常听到这样一种误解“只要关闭浏览器,session就消失了”。其实可以想象一下会员卡的例子,除非顾客主动对店家提出销卡,否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的,除非程序通知服务器删除一个session,否则服务器会一直保留,程序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分session机制都使用会话cookie来保存session id,而关闭浏览器后这个 session id就消失了,再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求头,把原来的session id发送给服务器,则再次打开浏览器仍然能够找到原来的session。 恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。

由JSESSIONID谈cookie与SESSION的区别和联系

       在一些投票之类的场合,我们往往因为公平的原则要求每人只能投一票,在一些WEB开发中也有类似的情况,这时候我们通常会使用COOKIE来实现,例如如下的代码:

[html] view plaincopyprint?

  1. < % cookie[]cookies = request.getCookies();
  2. if (cookies.lenght == 0 || cookies == null)
  3. doStuffForNewbie();
  4. //没有访问过
  5. }else
  6. {
  7. doStuffForReturnVisitor(); //已经访问过了
  8. }% >

这是很浅显易懂的道理,检测COOKIE的存在,如果存在说明已经运行过写入COOKIE的代码了,然而运行以上的代码后,无论何时结果都是执行doStuffForReturnVisitor(),通过控制面板-Internet选项-设置-察看文件却始终看不到生成的cookie文件,奇怪,代码明明没有问题,不过既然有cookie,那就显示出来看看。 [html] view plaincopyprint?

  1. cookie[]cookies = request.getCookies();
  2. if (cookies.lenght == 0 || cookies == null)
  3. out.println("Has not visited this website");
  4. }else{
  5. for (int i = 0; i < cookie.length; i++){
  6. out.println("cookie name:" + cookies[i].getName() + "cookie value:" +
  7. cookie[i].getValue());}}

运行结果: cookie name:JSESSIONID cookie value:KWJHUG6JJM65HS2K6 为什么会有cookie呢,大家都知道,http是无状态的协议,客户每次读取web页面时,服务器都打开新的会话,而且服务器也不会自动维护客户的上下文信息,那么要怎么才能实现网上商店中的购物车呢,session就是一种保存上下文信息的机制,它是针对每一个用户的,变量的值保存在服务器端,通过SessionID来区分不同的客户,session是以cookie或URL重写为基础的,默认使用cookie来实现,系统会创造一个名为JSESSIONID的输出cookie,我们叫做session cookie,以区别persistent cookies,也就是我们通常所说的cookie,注意session cookie是存储于浏览器内存中的,并不是写到硬盘上的,这也就是我们刚才看到的JSESSIONID,我们通常情是看不到JSESSIONID的,但是当我们把浏览器的cookie禁止后,web服务器会采用URL重写的方式传递Sessionid,我们就可以在地址栏看到sessionid=KWJHUG6JJM65HS2K6之类的字符串。 明白了原理,我们就可以很容易的分辨出persistent cookies和session cookie的区别了,网上那些关于两者安全性的讨论也就一目了然了,session cookie针对某一次会话而言,会话结束session cookie也就随着消失了,而persistent cookie只是存在于客户端硬盘上的一段文本(通常是加密的),而且可能会遭到cookie欺骗以及针对cookie的跨站脚本攻击,自然不如session cookie安全了。 通常session cookie是不能跨窗口使用的,当你新开了一个浏览器窗口进入相同页面时,系统会赋予你一个新的sessionid,这样我们信息共享的目的就达不到了,此时我们可以先把sessionid保存在persistent cookie中,然后在新窗口中读出来,就可以得到上一个窗口SessionID了,这样通过session cookie和persistent cookie的结合我们就实现了跨窗口的session tracking(会话跟踪)。 在一些web开发的书中,往往只是简单的把Session和cookie作为两种并列的http传送信息的方式,session cookies位于服务器端,persistent cookie位于客户端,可是session又是以cookie为基础的,明白的两者之间的联系和区别,我们就不难选择合适的技术来开发web service了。

推荐:Java程序员从笨鸟到菜鸟之(二十四)Xml基础详解和DTD验证 来源: [http://blog.csdn.net/csh624366188/article/details/7425770](http://blog.csdn.net/csh624366188/article/details/7425770)

sessionId产生方法参考

Posted on

sessionId产生方法参考 - balaschen - JavaEye技术网站

首页 新闻 论坛 问答 博客 招聘 更多 ▼

专栏 文摘 圈子 搜索

您还未登录 ! 我的应用 登录 注册

balaschen

永久域名 http://balaschen.javaeye.com/

rad rail plugin | Spring Hibernate SessionFactory配置

2007-05-28

sessionId产生方法参考

tomcat java 代码

  1. protected synchronized String generateSessionId() {
  2. byte random[] = new byte[16];
  3. // Render the result as a String of hexadecimal digits
  4. StringBuffer result = new StringBuffer();
  5. int resultLenBytes = 0;
  6. while (resultLenBytes < this.sessionIdLength) {
  7. getRandomBytes(random);
  8. random = getDigest().digest(random);
  9. for (int j = 0;
  10. j < random.length && resultLenBytes < this.sessionIdLength;
  11. j++) {
  12. byte b1 = (byte) ((random[j] & 0xf0) >> 4);
  13. byte b2 = (byte) (random[j] & 0x0f);
  14. if (b1 < 10)
  15. result.append((char) ('0' + b1));
  16. else
  17. result.append((char) ('A' + (b1 - 10)));
  18. if (b2 < 10)
  19. result.append((char) ('0' + b2));
  20. else
  21. result.append((char) ('A' + (b2 - 10)));
  22. resultLenBytes++;
  23. }
  24. }
  25. return (result.toString());
  26. }

hibernate uuid: java 代码

  1. public abstract class AbstractUUIDGenerator implements IdentifierGenerator {
  2. private static final int IP;
  3. static {
  4. int ipadd;
  5. try {
  6. ipadd = BytesHelper.toInt( InetAddress.getLocalHost().getAddress() );
  7. }
  8. catch (Exception e) {
  9. ipadd = 0;
  10. }
  11. IP = ipadd;
  12. }
  13. private static short counter = (short) 0;
  14. private static final int JVM = (int) ( System.currentTimeMillis() >>> 8 );
  15. public AbstractUUIDGenerator() {
  16. }
  17. ///
  18. /* Unique across JVMs on this machine (unless they load this class
  19. /* in the same quater second - very unlikely)
  20. /*/
  21. protected int getJVM() {
  22. return JVM;
  23. }
  24. ///
  25. /* Unique in a millisecond for this JVM instance (unless there
  26. /* are > Short.MAX_VALUE instances created in a millisecond)
  27. /*/
  28. protected short getCount() {
  29. synchronized(AbstractUUIDGenerator.class) {
  30. if (counter<0) counter=0;
  31. return counter++;
  32. }
  33. }
  34. ///
  35. /* Unique in a local network
  36. /*/
  37. protected int getIP() {
  38. return IP;
  39. }
  40. ///
  41. /* Unique down to millisecond
  42. /*/
  43. protected short getHiTime() {
  44. return (short) ( System.currentTimeMillis() >>> 32 );
  45. }
  46. protected int getLoTime() {
  47. return (int) System.currentTimeMillis();
  48. }
  49. }
  50. public class UUIDHexGenerator extends AbstractUUIDGenerator implements Configurable {
  51. private String sep = "";
  52. protected String format(int intval) {
  53. String formatted = Integer.toHexString(intval);
  54. StringBuffer buf = new StringBuffer("00000000");
  55. buf.replace( 8-formatted.length(), 8, formatted );
  56. return buf.toString();
  57. }
  58. protected String format(short shortval) {
  59. String formatted = Integer.toHexString(shortval);
  60. StringBuffer buf = new StringBuffer("0000");
  61. buf.replace( 4-formatted.length(), 4, formatted );
  62. return buf.toString();
  63. }
  64. public Serializable generate(SessionImplementor session, Object obj) {
  65. return new StringBuffer(36)
  66. .append( format( getIP() ) ).append(sep)
  67. .append( format( getJVM() ) ).append(sep)
  68. .append( format( getHiTime() ) ).append(sep)
  69. .append( format( getLoTime() ) ).append(sep)
  70. .append( format( getCount() ) )
  71. .toString();
  72. }
  73. public void configure(Type type, Properties params, Dialect d) {
  74. sep = PropertiesHelper.getString("separator", params, "");
  75. }
  76. public static void main( String[] args ) throws Exception {
  77. Properties props = new Properties();
  78. props.setProperty("separator", "/");
  79. IdentifierGenerator gen = new UUIDHexGenerator();
  80. ( (Configurable) gen ).configure(Hibernate.STRING, props, null);
  81. IdentifierGenerator gen2 = new UUIDHexGenerator();
  82. ( (Configurable) gen2 ).configure(Hibernate.STRING, props, null);
  83. for ( int i=0; i<10; i++) {
  84. String id = (String) gen.generate(null, null);
  85. System.out.println(id);
  86. String id2 = (String) gen2.generate(null, null);
  87. System.out.println(id2);
  88. }
  89. }
  90. }
    rad rail plugin | Spring Hibernate SessionFactory配置

发表评论

您还没有登录,请登录后发表评论(快捷键 Alt+S / Ctrl+Enter)

balaschen的博客

balaschen

搜索本博客

最近访客 >>更多访客

wangzhongjie的博客

wangzhongjie

yqwan的博客

yqwan icecityman的博客

icecityman

chilongxph的博客

chilongxph

博客分类

最近加入圈子

最新评论

声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。若作者同意转载,必须以超链接形式标明文章原始出处和作者。 © 2003-2009 JavaEye.com. All rights reserved. 上海炯耐计算机软件有限公司 [ 沪ICP备05023328号 ]

jsp

Posted on

jsp-servlet技术:一篇写的详细的sessi__(1)_javanewlearner的空间百度空间

javanewlearner的空间

2012-02-25 16:24

jsp-servlet技术:一篇写的详细的sessi...(1)

摘要:虽然session机制在web应用程序中被采用已经很长时间了,但是仍然有很多人不清楚session机制的本质,以至不能正确的应用这一技术。本文将详细讨论session的工作机制并且对在Java web application中应用session机制时常见的问题作出解答。

一、术语session

在我的经验里,session这个词被滥用的程度大概仅次于transaction,更加有趣的是transaction与session在某些语境下的含义是相同的。

session,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。有时候我们可以看到这样的话“在一个浏览器会话期间,...”,这里的会话一词用的就是其本义,是指从一个浏览器窗口打开到关闭这个期间①。最混乱的是“用户(客户端)在一次会话期间”这样一句话,它可能指用户的一系列动作(一般情况下是同某个具体目的相关的一系列动作,比如从登录到选购商品到结账登出这样一个网上购物的过程,有时候也被称为一个transaction),然而有时候也可能仅仅是指一次连接,也有可能是指含义①,其中的差别只能靠上下文来推断②。

然而当session一词与网络协议相关联时,它又往往隐含了“面向连接”和/或“保持状态”这样两个含义,“面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道,比如打电话,直到对方接了电话通信才能开始,与此相对的是写信,在你把信发出去的时候你并不能确认对方的地址是否正确,通信渠道不一定能建立,但对发信人来说,通信已经开始了。“保持状态”则是指通信的一方能够把一系列的消息关联起来,使得消息之间可以互相依赖,比如一个服务员能够认出再次光临的老顾客并且记得上次这个顾客还欠店里一块钱。这一类的例子有“一个TCP session”或者“一个POP3 session”③。

而到了web服务器蓬勃发展的时代,session在web开发语境下的语义又有了新的扩展,它的含义是指一类用来在客户端与服务器之间保持状态的解决方案④。有时候session也用来指这种解决方案的存储结构,如“把xxx保存在session里”⑤。由于各种用于web开发的语言在一定程度上都提供了对这种解决方案的支持,所以在某种特定语言的语境下,session也被用来指代该语言的解决方案,比如经常把Java里提供的javax.servlet.http.HttpSession简称为session⑥。

鉴于这种混乱已不可改变,本文中session一词的运用也会根据上下文有不同的含义,请大家注意分辨。

在本文中,使用中文“浏览器会话期间”来表达含义①,使用“session机制”来表达含义④,使用“session”表达含义⑤,使用具体的“HttpSession”来表达含义⑥

二、HTTP协议与状态保持

HTTP协议本身是无状态的,这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器请求下载某些文件,无论是客户端还是服务器都没有必要纪录彼此过去的行为,每一次请求之间都是独立的,好比一个顾客和一个自动售货机或者一个普通的(非会员制)大卖场之间的关系一样。

然而聪明(或者贪心?)的人们很快发现如果能够提供一些按需生成的动态信息会使web变得更加有用,就像给有线电视加上点播功能一样。这种需求一方面迫使HTML逐步添加了表单、脚本、DOM等客户端行为,另一方面在服务器端则出现了CGI规范以响应客户端的动态请求,作为传输载体的HTTP协议也添加了文件上载、cookie这些特性。其中cookie的作用就是为了解决HTTP协议无状态的缺陷所作出的努力。至于后来出现的session机制则是又一种在客户端与服务器之间保持状态的解决方案。

让我们用几个例子来描述一下cookie和session机制之间的区别与联系。笔者曾经常去的一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠,然而一次性消费5杯咖啡的机会微乎其微,这时就需要某种方式来纪录某位顾客的消费数量。想象一下其实也无外乎下面的几种方案:

1、该店的店员很厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种做法就是协议本身支持状态。

2、发给顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。

3、发给顾客一张会员卡,除了卡号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。

由于HTTP协议是无状态的,而出于种种考虑也不希望使之成为有状态的,因此,后面两种方案就成为现实的选择。具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择。

三、理解cookie机制

cookie机制的基本原理就如上面的例子一样简单,但是还有几个问题需要解决:“会员卡”如何分发;“会员卡”的内容;以及客户如何使用“会员卡”。

正统的cookie分发是通过扩展HTTP协议来实现的,服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。然而纯粹的客户端脚本如JavaScript或者VBScript也可以生成cookie。

而cookie的使用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储的cookie,如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置,则把该cookie附在请求资源的HTTP请求头上发送给服务器。意思是麦当劳的会员卡只能在麦当劳的店里出示,如果某家分店还发行了自己的会员卡,那么进这家店的时候除了要出示麦当劳的会员卡,还要出示这家店的会员卡。

cookie的内容主要包括:名字,值,过期时间,路径和域。

其中域可以指定某一个域比如.google.com,相当于总店招牌,比如宝洁公司,也可以指定一个域下的具体某台机器比如www.google.com或者froogle.google.com,可以用飘柔来做比。

路径就是跟在域名后面的URL路径,比如/或者/foo等等,可以用某飘柔专柜做比。

路径与域合在一起就构成了cookie的作用范围。

如果不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。

存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的cookie,不同的浏览器有不同的处理方式。对于IE,在一个打开的窗口上按Ctrl-N(或者从文件菜单)打开的窗口可以与原窗口共享,而使用其他方式新开的IE进程则不能共享已经打开的窗口的内存cookie;对于Mozilla Firefox0.8,所有的进程和标签页都可以共享同样的cookie。一般来说是用javascript的window.open打开的窗口会与原窗口共享内存cookie。浏览器对于会话cookie的这种只认cookie不认人的处理方式经常给采用session机制的web应用程序开发者造成很大的困扰。

下面就是一个goolge设置cookie的响应头的例子

HTTP/1.1 302 Found Location: http://www.google.com/intl/zh-CN/ Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com Content-Type: text/html

这是使用HTTPLook这个HTTP Sniffer软件来俘获的HTTP通讯纪录的一部分

浏览器在再次访问goolge的资源时自动向外发送cookie

使用Firefox可以很容易的观察现有的cookie的值

使用HTTPLook配合Firefox可以很容易的理解cookie的工作原理。

IE也可以设置在接受cookie前询问

这是一个询问接受cookie的对话框。

四、理解session机制

session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。

当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。

保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于SEEESIONID,而。比如weblogic对于web应用程序生成的cookie,JSESSIONID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是JSESSIONID。

由于cookie可以被人为的禁止,必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面,附加方式也有两种,一种是作为URL路径的附加信息,表现形式为http://...../xxx;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764另一种是作为查询字符串附加在URL后面,表现形式为http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764 这两种方式对于用户来说是没有区别的,只是服务器在解析的时候处理的方式不同,采用第一种方式也有利于把session id的信息和正常程序参数区分开来。

为了在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。

另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。比如下面的表单

在被传递给客户端之前将被改写成

这种技术现在已较少应用,笔者接触过的很古老的iPlanet6(SunONE应用服务器的前身)就使用了这种技术。实际上这种技术可以简单的用对action应用URL重写来代替。

在谈论session机制的时候,常常听到这样一种误解“只要关闭浏览器,session就消失了”。其实可以想象一下会员卡的例子,除非顾客主动对店家提出销卡,否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的,除非程序通知服务器删除一个session,否则服务器会一直保留,程序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分session机制都使用会话cookie来保存session id,而关闭浏览器后这个session id就消失了,再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求头,把原来的session id发送给服务器,则再次打开浏览器仍然能够找到原来的session。

恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。 /#J2ee

举报浏览(45) 评论转载

评论 帮助中心 | 空间客服 | 投诉中心 | 空间协议

©2012 Baidu

java实现double的精确计算和四舍五入

Posted on

java实现double的精确计算和四舍五入

遗忘的角落

#

*

用户操作[留言] [发消息] [加为好友] 订阅我的博客XML聚合 FeedSky订阅到鲜果订阅到Google订阅到抓虾[编辑]a9529lty的公告我的QQ是297453997欢迎大家加我一起讨论问题[编辑]文章分类* (RSS)Ajax


Java中的简单浮点数类型float和double不能够进行运算。不光是Java,在其它很多编程语言中也有这样的问题。在大多数情况下,计算的结果是准确的,但是多试几次(可以做一个循环)就可以试出类似上面的错误。现在终于理解为什么要有BCD码了。 这个问题相当严重,如果你有9.999999999999元,你的计算机是不会认为你可以购买10元的商品的。 在有的编程语言中提供了专门的货币类型来处理这种情况,但是Java没有。现在让我们看看如何解决这个问题。 四舍五入 我们的第一个反应是做四舍五入。Math类中的round方法不能设置保留几位小数,我们只能象这样(保留两位): public double round(double value){ return Math.round(value/100)/100.0; } 非常不幸,上面的代码并不能正常工作,给这个方法传入4.015它将返回4.01而不是4.02,如我们在上面看到的 4.015/100=401.49999999999994 因此如果我们要做到精确的四舍五入,不能利用简单类型做任何运算 java.text.DecimalFormat也不能解决这个问题: System.out.println(new java.text.DecimalFormat("0.00").format(4.025)); 输出是4.02 **java 代码

import java.math.BigDecimal; public class Arith { private static final int DEF_DIV_SCALE = 10; private Arith() { } /// / 提供精确的加法运算。 / @param v1 被加数 / @param v2 加数 / @return 两个参数的和 // public static double add(double v1,double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); } /// / 提供精确的减法运算。 / @param v1 被减数 / @param v2 减数 / @return 两个参数的差 // public static double sub(double v1,double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.subtract(b2).doubleValue(); } /// / 提供精确的乘法运算。 / @param v1 被乘数 / @param v2 乘数 / @return 两个参数的积 // public static double mul(double v1,double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); } /// / 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 / 小数点以后10位,以后的数字四舍五入。 / @param v1 被除数 / @param v2 除数 / @return 两个参数的商 // public static double div(double v1,double v2) { return div(v1,v2,DEF_DIV_SCALE); } /// / 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 / 定精度,以后的数字四舍五入。 / @param v1 被除数 / @param v2 除数 / @param scale 表示表示需要精确到小数点以后几位。 / @return 两个参数的商 // public static double div(double v1,double v2,int scale) { if(scale<0) { throw new IllegalArgumentException("The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } /// / 提供精确的小数位四舍五入处理。 / @param v 需要四舍五入的数字 / @param scale 小数点后保留几位 / @return 四舍五入后的结果 // public static double round(double v,int scale){ if(scale<0) { throw new IllegalArgumentException("The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(Double.toString(v)); BigDecimal one = new BigDecimal("1"); return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } } *

发表于 @ 2009年05月18日 23:07:00 | 评论( loading... )| 编辑| 举报| 收藏

旧一篇:淘宝生成预览图片 | 新一篇:Oracle层次查询和分析函数

Copyright © a9529ltyPowered by CSDN Blog