Обработка множества одновременных запросов AJAX с помощью действия struts2 - PullRequest
0 голосов
/ 25 июня 2009

У меня есть действие struts2, которое отвечает на запрос AJAX, принимая некоторые параметры запроса, вызывая удаленную службу, которая возвращает данные XML, затем преобразовывая данные через XSL и возвращая полученный XHTML через Stream Result. Ответ зависит от заданных параметров.

Вот класс действий с кучей вещей, взятых:

public class ServiceHandler extends ActionSupport {
    private ByteArrayInputStream inputStream;

    public String execute(){

        String response = "";

        // Get request parameters
        // Make a request to a remote server via an http connection
        // Transform result via XSL

        //uses dom4j for XML/XSL stuff
        //this should never be empty
        response = resultDoc.asXML();

        inputStream = new ByteArrayInputStream(response.getBytes()); 
        return "success";
    }

    public ByteArrayInputStream getInputStream(){
        return inputStream;
    }
}

А вот важные биты struts.xml:

<action name="sh" class="ServiceHandler">
    <result name="success" type="stream">
        <param name="contentType">text/html</param>
        <param name="contentDisposition">inline;filename="response.html"</param>
        <param name="bufferSize">1024</param>
        <param name="allowCaching">false</param>
    </result>
</action>

Моя проблема в том, что когда у меня несколько запросов, идущих одновременно, все они вызывают действие ServiceHandler, иногда ответ полностью пустой (никогда не должен происходить), иногда ответ обрезается в начале или в конце случайным образом количество, а иногда ответы переключаются, так что запросчик AJAX получает неправильный ответ.

Я знаю, что это проблема безопасности потока, и я переместил все важные определения переменных в метод execute (), чтобы они не были переменными экземпляра (и, следовательно, общими для всех). Единственная интересная переменная, которая является переменной экземпляра, является inputStream, и я рассматриваю это как причину моих проблем.

Есть ли способ сделать переменную inputStream потоко-безопасной? Или я не вижу другого решения?

Ответы [ 3 ]

0 голосов
/ 26 июня 2009

Я вообще не в Struts 2, но если вам действительно нужно вернуть результат "успеха" и у вас нет возможности напрямую записать в вывод, это выглядит как хорошее место для использования ThreadLocal, чтобы сохранить ваш поток локальным по отношению к текущему потоку. (Также см. Статью Википедии о локальном хранилище потоков для получения дополнительной информации о шаблоне.)

0 голосов
/ 26 июня 2009

Спасибо за Хеннинга за то, что он привел меня в правильном направлении. Я не думал о прямой записи в поток вывода ответа, поскольку это нигде не упоминается в документации Struts2.

Преимущество записи ответа непосредственно в выходной поток состоит в том, что вам не нужно создавать объект экземпляра для inputStream. Это сохраняет все данные в методе execute (), который защищен от других потоков.

Вот модифицированный класс действия, который записывает непосредственно в выходной поток и возвращает нулевой результат.

import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;

public class ServiceHandler extends ActionSupport {
    public String execute(){

        String response = "";

        // Get request parameters
        // Make a request to a remote server via an http connection
        // Transform result via XSL

        //uses dom4j for XML/XSL stuff
        //this should never be empty
        response = resultDoc.asXML();

        HttpServletResponse httpResponse = ServletActionContext.getResponse();
        try{
            httpResponse.getOutputStream().print(response);
        }
        catch(IOException e){
            return "failure";
        }

        return null;
    }
}

Это, похоже, исправило проблемы, которые у меня были.

0 голосов
/ 26 июня 2009

Я знаком только с Struts 1, но взгляну на DonwloadAction. Или просто используйте простое действие Action, запишите результат непосредственно в объект ответа и верните null как forward.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...