ChunkedInput не работает в майке

Может кто-нибудь помочь мне, почему проблема с кодом Java и печать всех данных за один раз вместо печати каждого куска в виде кода JavaScript

Java-код:

import org.glassfish.jersey.client.ChunkedInput;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;

public class RunClient {

    public static void main(String args[]) throws InterruptedException {
        Client client = ClientBuilder.newClient();
//2 is to increase amount of data and 3(seconds) is for time b/w chunked output  ,can be changed
        final Response response = client.target("http://jerseyexample-ravikant.rhcloud.com/rest/jws/streaming/2/3").request()
                .get();
        final ChunkedInput<String> chunkedInput = response.readEntity(new GenericType<ChunkedInput<String>>() {
        });
        String chunk;
        while ((chunk = chunkedInput.read()) != null) {
            System.err.println("Next chunk received: " );
            System.out.println(chunk);
        }


    }
}

JavaScript: (Откройте страницу http://jerseyexample-ravikant.rhcloud.com/rest/jws а затем нажмите F12 и запустите ниже в консоли, так как вызов JavaScript не разрешен из другого домена)

//2 is to increase amount of data and 3(seconds) is for time b/w chunked output  ,can be changed

var xhr = new XMLHttpRequest()
xhr.open("GET", "http://jerseyexample-ravikant.rhcloud.com/rest/jws/streaming/2/3", true)
xhr.onprogress = function () {
  console.log("PROGRESS:", xhr.responseText) ;console.log("\n");
}
xhr.send()

РЕДАКТИРОВАТЬ: Просто для справки, это также работает будет нормальное соединение Java

        String uri = "http://jerseyexample-ravikant.rhcloud.com/rest/jws/streaming/3/1";
        URL url = new URL(uri);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setDoOutput(true);
        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String line;
        while ((line = in.readLine()) != null) {
            System.out.println(line);
        }
        in.close();

Мой код веб-сервиса

@Path("streaming/{param}/{sleepTime}")
@GET
@Produces(MediaType.TEXT_PLAIN)
public ChunkedOutput<String> getChunkedStream(@PathParam("param") String loopcount,@PathParam("sleepTime") String sleepTime) throws Exception {

    final ChunkedOutput<String> output = new ChunkedOutput<>(String.class);
    final Integer val=Integer.parseInt(loopcount);
    final Integer isleepTime=Integer.parseInt(sleepTime)*1000;
    new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                StringBuffer chunk = null;

                for (int i = 0; i < 10; i++) {
                        chunk = new StringBuffer();
                    for (int j = 0; j < val; j++) {
                        chunk.append(" Message #" + i+ "#"+j);
                    }
                        output.write(chunk.toString()+"\n");
                    System.out.println("write");
                    Thread.sleep(isleepTime);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    System.out.println("output.close();");
                    output.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }).start();

    return output;
}

1 ответ

Решение

Форма Джерси Документы:

Записать чанки с помощью ChunkedOutput просто, вы вызываете только метод write(), который записывает ровно один чанк в вывод. С входным чтением это немного сложнее. ChunkedInput не знает, как различать порции в потоке байтов, если это не сказано разработчиком. Чтобы определить пользовательские границы чанков, ChunkedInput предлагает возможность зарегистрировать ChunkParser, который считывает чанки из входного потока и разделяет их. В Jersey реализовано несколько синтаксических анализаторов чанков, и вы можете реализовать свой собственный синтаксический анализатор для разделения своих чанков, если вам это нужно. В нашем примере выше используется синтаксический анализатор по умолчанию, предоставленный Jersey, который разделяет порции на основе наличия символьной последовательности \ r \ n.

Таким образом, ваш сервер должен разделять фрагменты с помощью \ r \n, или вы должны зарегистрировать ChunkParser.

Предполагая, что у вас есть постоянная финализация каждого куска, вы можете попробовать:

Client client = ClientBuilder.newClient();
//2 is to increase amount of data and 3(seconds) is for time b/w chunked output  ,can be changed
        final Response response = client.target("http://jerseyexample-ravikant.rhcloud.com/rest/jws/streaming/2/3").request()
                .get();
        final ChunkedInput<String> chunkedInput = response.readEntity(new GenericType<ChunkedInput<String>>() {
        });
        chunkedInput.setParser(ChunkedInput.createParser(BOUNDARY));
        String chunk;
        while ((chunk = chunkedInput.read()) != null) {
            System.err.println("Next chunk received: " );
            System.out.println(chunk);
        }

В то время как BOUNDARY - финализирующая строка для каждого куска. Решение in.readLine в вашем редакторе будет разбивать "чанки" на каждую новую строку, даже если один чанк состоит из \n, он будет интерпретироваться как 2 чанка.

Другие вопросы по тегам