كيف يمكنك الأنابيب وOutputStream إلى StreamingDataHandler؟

StackOverflow https://stackoverflow.com/questions/866051

  •  21-08-2019
  •  | 
  •  

سؤال

ولقد حصلت على خدمة الإنترنت جافا في JAX-WS يقوم بإرجاع OutputStream من طريقة أخرى. أنا لا يمكن أن يبدو لمعرفة كيفية تيار OutputStream في DataHandler عاد أي وسيلة أخرى من إنشاء ملف مؤقت، الكتابة إليه، ثم فتح إعادته مرة أخرى باعتبارها InputStream. وإليك مثال:

@MTOM
@WebService
class Example {
    @WebMethod
    public @XmlMimeType("application/octet-stream") DataHandler service() {
        // Create a temporary file to write to
        File fTemp = File.createTempFile("my", "tmp");
        OutputStream out = new FileOutputStream(fTemp);

        // Method takes an output stream and writes to it
        writeToOut(out);
        out.close();

        // Create a data source and data handler based on that temporary file
        DataSource ds = new FileDataSource(fTemp);
        DataHandler dh = new DataHandler(ds);
        return dh;
    }
}

والقضية الرئيسية هي أن طريقة writeToOut () يمكن إرجاع البيانات التي هي أكبر بكثير من ذاكرة الكمبيوتر. هذا هو السبب في أسلوب يستخدم MTOM في المقام الأول - لدفق البيانات. أنا لا يمكن أن يبدو للالتفاف رأسي حول كيفية تيار البيانات مباشرة من OutputStream أنني بحاجة إلى تزويد DataHandler عاد (والعميل في نهاية المطاف، الذي يحصل على StreamingDataHandler).

ولقد حاولت اللعب حولها مع PipedInputStream وPipedOutputStream، ولكن هذه لا يبدو أن يكون تماما ما تحتاجه، لسيحتاج DataHandler يتم إرجاعها بعد كتابة PipedOutputStream ل.

وأي أفكار؟

هل كانت مفيدة؟

المحلول

وأنا أحسب الجواب، على غرار ذلك المسيحي كان يتحدث عن (خلق ترابط جديد لتنفيذ writeToOut ()):

@MTOM
@WebService
class Example {
    @WebMethod
    public @XmlMimeType("application/octet-stream") DataHandler service() {
        // Create piped output stream, wrap it in a final array so that the
        // OutputStream doesn't need to be finalized before sending to new Thread.
        PipedOutputStream out = new PipedOutputStream();
        InputStream in = new PipedInputStream(out);
        final Object[] args = { out };

        // Create a new thread which writes to out.
        new Thread(
            new Runnable(){
                public void run() {
                    writeToOut(args);
                    ((OutputStream)args[0]).close();
                }
            }
        ).start();

        // Return the InputStream to the client.
        DataSource ds = new ByteArrayDataSource(in, "application/octet-stream");
        DataHandler dh = new DataHandler(ds);
        return dh;
    }
}

وهو صبي أكثر تعقيدا بسبب final المتغيرات، ولكن بقدر ما استطيع ان اقول هذا هو الصحيح. عند بدء تشغيل موضوع، فإنه بحظر عندما كان يحاول أول من دعا out.write(). في نفس الوقت، يتم إرجاع دفق الإدخال إلى العميل، الذين يفرج الكتابة من خلال قراءة البيانات. (وكانت المشكلة مع بلدي تطبيقات السابقة من هذا الحل الذي لم أكن إغلاق بشكل صحيح تيار، وبالتالي الوقوع في الأخطاء.)

نصائح أخرى

عذرا، أنا فقط فعلت ذلك لC # وليس جافا، ولكن أعتقد أن الأسلوب الخاص بك يجب إطلاق موضوع لتشغيل "writeToOut (من)؛" في متوازية. تحتاج إلى خلق تيار خاص وتمريرها إلى موضوع جديد والذي يعطي هذا الدفق إلى writeToOut. بعد بدء موضوع تعود أن تيار الكائن إلى المتصل بك.

إذا كان لديك سوى الأسلوب الذي يكتب لتيار ويعود بعد ذلك وطريقة أخرى أن يستهلك تيار ويعود بعد ذلك، لا توجد وسيلة أخرى.

ومن coure الجزء صعبة هو الحصول على عقد من مثل تيار safe- -multithreading: يجب ومنع كل جانب إذا كان المخزن المؤقت الداخلي مليء جدا

لا أعرف إذا كان جافا الأنابيب تيار يعمل لذلك.

ونمط التفاف؟ : -)

وتنفيذ javax.activation.DataSource مخصص (طرق فقط 4) أن تكون قادرة على القيام بذلك؟

return new DataHandler(new DataSource() { 
  // implement getOutputStream to return the stream used inside writeToOut() 
  ... 
});   

وأنا لم يكن لديك IDE متاح لاختبار هذا ما أفعله مجرد اقتراح. وأود أيضا بحاجة إلى writeToOut التخطيط العام :-).

في طلبي وأنا استخدم تنفيذ InputStreamDataSource التي تأخذ InputStream كوسيطة منشئ بدلا من ملف في FileDataSource. وهي تعمل حتى الآن.

public class InputStreamDataSource implements DataSource {

ByteArrayOutputStream buffer = new ByteArrayOutputStream();
private final String name;

public InputStreamDataSource(InputStream inputStream, String name) {
    this.name = name;
    try {
        int nRead;
        byte[] data = new byte[16384];
        while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, nRead);
        }

        buffer.flush();
        inputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

@Override
public String getContentType() {
    return new MimetypesFileTypeMap().getContentType(name);
}

@Override
public InputStream getInputStream() throws IOException {
    return new ByteArrayInputStream(buffer.toByteArray());
}

@Override
public String getName() {
    return name;
}

@Override
public OutputStream getOutputStream() throws IOException {
    throw new IOException("Read-only data");
}

و}

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top