首页 > 解决方案 > Struts2 动作设置方法不是线程安全的?

问题描述

我有一个非常奇怪的问题。我有一个用 Struts2、两个动作文件和一个 jsp 文件构建的网络应用程序。功能是提交表单并从 UI 中获取 csId。但是,我发现如果我打开两个窗口单击表单以提交不同的 csId,我可以看到 csId 在操作的循环中发生了变化。

我认为操作是线程安全的,但其他用户的操作如何更改我操作中的 csId?请帮忙。

有两个动作文件:

public abstract class CustomerSegmentCrudBaseAction extends BaseAction {
    protected String csId;
    public String execute() throws PromotionException{
        return ActionSupport.SUCCESS;
    }

    public String getCsId() {
        return csId;
    }

    public void setCsId(String csId) {
        this.csId = csId;
    }
}

public class CustomerSegmentAddCustomerIdAction extends CustomerSegmentCrudBaseAction {

    public String execute(){ 
       for(int i = 0;i<10000;i++){
          log.info(java.lang.Thread.currentThread().getId() + " csId: " + csId);
       }
    }
}

jsp文件:

<s:form action="add-ids-customer-segment" method="post" enctype="multipart/form-data" onsubmit="var customerCount = getCustomerIdCount(); return confirm('Are you sure to upload ' + customerCount +' customers?');">
       <table><tbody><tr>
       <td class="cell">
           <s:textarea label="Customer ID" labelposition="false" id="csCustomerIds" name="csCustomerIds" value="" rows="2" cssClass="wide" theme="css_xhtml"/>
       </td>
       <td class="cell">
           <s:submit value="Add" theme="css_xhtml"/>
       </td>
       </tbody></table>
       <s:hidden name="csId" value="%{getCsId()}" />
   </s:form>

我还打印了线程 ID,我可以看到有两个不同的线程。一个线程中的 csId 更改为另一个线程中的另一个 csId。

格林威治标准时间 2018 年 8 月 29 日星期三 10:55:40 (http-bio-8663-exec-8) customersegment.ui.html.actions.edit.CustomerSegmentAddCustomerIdAction:线程 ID 为:44 csId:8787

格林威治标准时间 2018 年 8 月 29 日星期三 10:55:40 (http-bio-8663-exec-8) customersegment.ui.html.actions.edit.CustomerSegmentAddCustomerIdAction:线程 ID 为:44 csId:8787

格林威治标准时间 2018 年 8 月 29 日星期三 10:55:40 (http-bio-8663-exec-8) customersegment.ui.html.actions.edit.CustomerSegmentAddCustomerIdAction:线程 ID 为:44 csId:28475

标签: jspstruts2

解决方案


我找到了使用 Spring 创建默认范围是单例的动作 bean 的根本原因。将范围更改为原型。


推荐阅读