在线等,只要点通我,马上给分,看了篇jsp安全的文章,从昨天晚上到现在没搞清楚,想骂街了都....
在线等,只要点通我,马上给分,如果是作者的文章有问题骂死他了,我看了快一天了,没明白.....,我笨?....
已经看到有人发了相同的帖子(http://topic.csdn.net/t/20021030/10/1133570.html),但是我还是没看懂,高人解释一下,暂且引用一下它的问题和我的一样:
看到一篇帖子,说了一个jsp线程不安全的问题,然后提出了一种将实例变量变成局部变量的方式,不是太明白。贴出来和大家讨论一下。
<%@ page import= "
javax.naming.*,
java.util.*,
java.sql.*,
weblogic.common.*
" %>
<%
String name
String product;
long quantity;
name=request.getParameter( "name ");
product=request.getParameter( "product ");
quantity=request.getParameter( "quantity "); /* (1)*/
savebuy();
%>
<%!
public void savebuy()
{
/*进行数据库操作,把数据保存到表中*/
try {
Properties props = new Properties();
props.put( "user ", "scott ");
props.put( "password ", "tiger ");
props.put( "server ", "DEMO ");
Driver myDriver = (Driver) Class.forName( "weblogic.jdbc.oci.Driver ").newInstance();
conn = myDriver.connect( "jdbc:weblogic:oracle ", props);
stmt = conn.createStatement();
String inssql = "insert into buy(empid, name, dept) values (?, ?, ?,?) ";
stmt = conn.prepareStatement(inssql);
stmt.setString(1, name);
stmt.setString(2, procuct);
stmt.setInt(3, quantity);
stmt.execute();
}
catch (Exception e)
{
System.out.println( "SQLException was thrown: " + e.getMessage());
}
finally //close connections and statements in a finally block
{
try {
if(stmt != null)
stmt.close();
if(conn != null)
conn.close();
} catch (SQLException sqle) {
System.out.println( "SQLException was thrown: " + sqle.getMessage());
}
}
}
%>
上面的程序模拟网上购物中的一部分,把用户在浏览器中输入的用户名,购买的物品名称,数量保存到表BUY中。在savebuy()函数中用到了实例变量,所以它不是线程安全的.因为:程序中的每一条语句都不是原子操作,如name=request.getParameter( "name ");在执行是会对应多个机器指令,在任何时候都可能因系统调度而转入睡眠状态,让其他的线程继续执行.如果线程A在执行到(1)的时候转入睡眠状态,线程B开始执行并改变QUANTITY的值,那么当又到A执行时,它会从调用savebuy()函数开始执行,这样它保存到表中的QUANTITY是被线程B改过的值,那么线程A对应的用户所实际购买的数量与保持到表中的数据不一致.这是个很严重的问题.
三、解决方法
(3)采用局部变量代替实例变量,函数savebuy()声明如下:
因为在savebuy()中使用的是传给他的形参,是在堆栈中分配的,所以是线程安全的.
public void savebuy(String name,String product, int quantity)
{
......
}
调用方式改为:
<%
String name
String product;
long quantity;
name=request.getParameter( "name ");
product=request.getParameter( "product ");
quantity=request.getParameter( "quantity "); /* (2) */
savebuy(name,product,quantity)
%>
**************************************************************************
以上为帖子的大致内容,我不明白的地方是:
如果在/* (2) */ 发生作者所说的问题,那不也是不对的吗?
[解决办法]
<%
String name
String product;
long quantity;
%>
我觉得的写的不对
上面的三个变量的定义是在 <% %> 里面的
所以这三个变量都是局部变量也就是 servlet service 方法里面的变量
不是什么所谓的实例变量 Jsp里面声明实例变量要在 <%! %> 里面才可以
可以自己写一个jsp 然后查看tomcat生成的servlet文件
就可以知道
sertvlet是以多线程的方式运行 使用文中/*1*/做法 不会造成数据混淆
所以觉得作者的看法 有带商榷 下面继续
[解决办法]
你自己写一个 简单的jsp 然后看看tomcat生成的相应的servlet 就可以了