Java多重提交处理分析

huangyi023

huangyi023

2016-02-19 15:36

给自己一点时间接受自己,爱自己,趁着下午茶的时间来学习图老师推荐的Java多重提交处理分析,过去的都会过去,迎接崭新的开始,释放更美好的自己。

  现代网络站点(web site)的主要任务是显示动态内容。从某些角度看,就是指用户将输入信息发送给网络应用(web application)进行处理之后网络应用再将处理结果发送回用户。某些特别情况下,从用户角度看后端操作运行足够快并且一切正常。但是在有些时候,后端的处理往往会因为出现较多的时间消耗而引起延迟。这种延迟有可能过长而最终使用户认为是其自己的操作错误,他们也许会放弃当前的操作或重新提交请求。

  处理操作运行周期的事件过长并不是一个新问题。Java提供的健壮的线程机制能够建立起后台的任务分配。另外,随着EJB 2.0规范的出现,基于消息的EJB(简称MDB)能够被用来执行后台操作。不过请记住,这些机制是为了处理异步操作而设计的。从你启动了一个线程或后台处理,到某段时间之后你被通知或者是需要查看结果,整个过程完全是异步的。

  对于轻型的长时间运行的一般同步应用仍然会引起大量处理的问题你有何看法?想象一下,一个音乐爱好者登陆她喜欢的网站为一场刚开始售票的演出订票(我想起了最近Bruce Springsteen的演唱会)。在通常情况下,网站会很好的执行并且我们的音乐爱好者能够以她自己的方式买到票。可是,当负载很大时,服务器便会慢下来,使该用户的操作不能顺利进行(用户会以为自己的订购操作失败了),因此她会接二连三的点击"提交"按钮。不幸的是,每一次点击"提交"都把之前的订票操作中止了。

  有很多方法处理这种情况。最显而易见的方法是防止用户重复提交相同请求。另外也可以跟踪用户先前提交的请求并回复先前的提交动作。下图显示了一个简单的服务端小程序(servlet)的输出数据,该程序处理每一个收到的请求,为每一个请求分配一个票号。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  处理简单的提交任务

  图1:简单提交任务处理

  最主要和最有效解决多重提交问题的方法就是防止这种情况发生。下面列出的HTML程序ConcertTickets.html是一个简单的表单,用于获取由用户输入的音乐会名字并提交给服务端小程序(servlet)订票。当网站相应迅速时处理执行的很好。但是,如果网站处于性能很低的状态并且提交的任务处理不够快,用户认为失败后会重新提交。处理过程在表1下的图2中显示。

  表1:ConcertTickets.html

  

01: <html>
02: <head><title>Online Concert Tickets</title></head>
03:
04: <center><h1>Order Tickets</h1></center>
05:
06: <form name="Order" action="./SimpleOrder" method="GET">
07: <table border="2" width="50%" align="center" bgcolor="CCCCCC">
08: <tr><td align="right" width="40%">Concert: </td>
09: <td width="60%"><input type="text" name="Concert" value=""></td></tr>
10:
11: <tr><td colspan="2" align="center">
12: <input type="submit" name="btnSubmit"
13: value="Do Submit"></td></tr>
14: </table>
15: </form>
16: </body>
17: </html>

  图2:重复的任务提交

  防止多重提交

  最简单的解决多重提交问题的方法是防止这种情况发生。下面是我们表1中表单程序的一个修改,加入了少量的javascript脚本。内嵌的javascript脚本记录以前提交按钮被点击的次数。在用户再次提交时,将会弹出报警窗口并且表单不会再被提交。我们能够通过给提交按钮加入onClick事件属性来缩短普通提交处理过程的周期。每次提交按钮被点击时,onClick的代码就会执行。在我们这个例子中,会引起javascript脚本函数checksubmitcount()被调用。但仅仅调用一个函数并不会真正起到作用。如果我们只是加入onClick,每次提交按钮被点击时我们会收到弹出的警报,而任务提交也会立即发生。用户会被警告她操作错误,但是请求还是会被提交。这样做仅仅对用户端有了一定的改善。而在服务端结果是一样的:多重提交。

  表2:Concert2.html

  

01: <html>
. . .<!?与表1 :ConcertTickets.html程序02~11相同 //-->
12: <input type="button" name="btnSubmit"
13: value="Do Submit"
14: onClick="checksubmitcount();"></td></tr>
15: </table>
16: </form>
17:
18: <script language="javascript">
19: <!--
20: var submitcount = 0;
21: function checksubmitcount()
22: {
23: submitcount++;
24: if (1 == submitcount )
25: {
26: document.Order.submit();
27: }
28: else
29: {
30: if ( 2 == submitcount)
31: alert("You have already submitted this form");
32: else
33: alert("You have submitted this form"
34: + submitcount.toString()
35: + " times already");
36: }
37: }
38: //-->
39: </script>
40: </body>
41: </html>

  我们能通过更进一步和更精细的改变我们网页的工作方式来解决问题。敏锐的读者可能会注意到对表单添加的改变。程序第12行定义的按钮类型原先为submit,现在改成了button。而网页界面是完全相同的。可是,与表单相关的默认动作(程序第6行,调用服务端小程序)不再是自动执行的了。我们现在能够通过程序控制表单向服务器端的提交,我们的问题也得到了解决,不是么?

  表2当然是一种改善,但我们还是需要一些其他方法。仍然有许多情况会导 致错误。如果用户按下了浏览器的后退键或者刷新了整个网页会怎么样?如果用户的浏览器关闭了javascript的功能或者浏览器不能处理会如何呢?我们还是可以处理这个问题的,但是为了取代防止多重提交,我们需要在后端通过表单处理的服务端小程序处理它们。

  为了理解如何解决多重提交问题,我们必须首先理解服务端小程序会话(sessions)机制。每个人都知道,HTTP协议的固有性质中并不对状态(客户端请求信息的历史记录)进行记录。为了处理状态,我们需要一些方法使浏览器能够将当前请求与其他大量请求联系起来。会话(session)程序提供给我们一个解决这个问题的方案。HttpServlet中的方法doGet()和doPost()使用了两个指定的参数:HttpServletRequest和HttpServletResponse。服务端小程序请求参数使我们能够访问会话(session)。会话为访问和存储状态提供了机制。

  什么才是会话(session)呢?会话(session)包括很多内容:

  状态集??由web服务器管理并且由特定用户所有请求所共享的详细表示描述。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  存储空间??通过HttpSession接口至少将HttpServlets所需状态数据和定义存储起来。

  在我们具体了解如何使用服务器端方案解决我们的问题之前,我们还需要了解服务端小程序会话(session)的生命周期。与EJB及其他服务端实体一样,会话在生存期中通过一个定义的状态集运行。下图显示了会话的生命周期。Servlet可在三种特定的状态中转换:不存在(does not exist),新建(new),非新建(not new/或使用中in-use)。

  图3:服务端小程序会话(session)生命周期

  [ 相关贴图 ]

  a) 会话在开始时处于不存在状态。会话从这一状态开始或者由于许多原因而返回到此状态。最主要的原因就是用户以前没有访问过这些状态或者是由于用户脱离(超时)站点或退出使会话被设置为无效。

  b) 当会话被建立时便会从不存在状态进入新建状态。新建与非新建状态的区分是非常重要的,因为HTTP协议不记录状态信息。根据servlet详细说明书描述,在客户端返回会话给服务端之前会话不能够进入非新建状态(即从预期会话转变为当前会话)。这样在客户端不知道或者还没有决定加入会话时会话处于新建状态。

  c) 当会话通过cookie或是重写URL()返回到服务器时,会话就变为使用中或非新建状态。

  d) 通过各种get与set方法继续使用会话会使其维持在使用中状态。

  e) 当会话由于长时间没有被使用而超时或显式的被设为无效则会发生图中所示的5以及6所标识的转移。不同应用服务器用不同方式处理超时。BEA公司的WebLogic使应用部署者能够通过与web应用一起打包的特殊部署描述脚本(weblogic.xml)设置会话超时的时限。

  现在我们了解了会话的生命周期,那么如何获得一个会话并有效的使用它呢?接口HttpServletRequest提供了两个关于会话的方法:

  public HttpSession getSession()返回一个新的会话或一个已存在的会话。

  如果提供一个有效的会话ID(可能是通过cookie)则返回一个存在的会话。返回新的会话可能会有许多原因:用户最初的会话(无法提供有效会话ID);会话超过有效时间(提供了会话ID);一个无效的会话(提供了会话ID);或者是明确指出会话无效(提供了会话ID)。

  public HttpSession getSession(boolean)可能返回新会话、存在的会话或者空。getSession(true)尽可能返回一个存在的会话。否则创建一个新会话。getSession(false) 尽可能返回一个存在的会话否则返回空。

  我们还是只解决了手边一半的问题。我们希望能够跳过会话新建状态并自动的转换到会话使用中状态。我们能够通过重定向浏览器到处理服务端小程序自动的实现这些。表3把服务端小程序会话逻辑和重定向用户端与有效会话到处理服务端小程序的能力结合在一起。

展开更多 50%)
分享

猜你喜欢

Java多重提交处理分析

编程语言 网络编程
Java多重提交处理分析

处理表单提交的数据

Java JAVA基础
处理表单提交的数据

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

JAVA编程中异常问题处理方式的区别和分析

编程语言 网络编程
JAVA编程中异常问题处理方式的区别和分析

关于java异常处理

编程语言 网络编程
关于java异常处理

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

Effective Java (异常处理)

编程语言 网络编程
Effective Java (异常处理)

解决Java调用BAT批处理不弹出cmd窗口的方法分析

编程语言 网络编程
解决Java调用BAT批处理不弹出cmd窗口的方法分析

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

Win8应用安装失败的解决措施

Win8应用安装失败的解决措施

详解CSS优先级的读法及优先级四个级别

详解CSS优先级的读法及优先级四个级别
下拉加载更多内容 ↓