指定されたのは、受信したクライアント ソース コード (Java で記述) を実行し、その出力を返す Spring MVC ベースの Web アプリです。
jsp には、クライアント コードをサーバーに送信する jquery 関数があります。
$.post(contextPath('/submit/run'), {
className: className, // somewhere blah blah
source: code,
args: args,
stdin: stdin
}, function(data) {
log(data);
});
受信者:
@RequestMapping(value = "/run", method = RequestMethod.POST)
public @ResponseBody String run(@RequestParam("className") String className,
@RequestParam("source") String source,
@RequestParam("args") String args,
@RequestParam("stdin") String stdin){
final CodeRunner runner = ...; // Compiles, Executes..
return runner.run(); // Then returns output from StdOut
}
それでも、すべて正常に動作します。ランナーは定義された時間内にコードを実行できます。つまり、n
秒を超えるとスレッドを強制終了します。ただし、クライアント コードが次のようなループを含むコードを実行する場合<~n sec
:
for(int i = 0; i < 200000; i++)
System.out.println("Not so infinite loop.");// runs 0.87 second, but prints a lot
応答を待っているように見えるため、ブラウザが遅れます。
私は当初、ランナー内の文字列ビルダーに出力を追加する私の方法はおそらくループだと思っていました。だから私はこれを変更しました:
String line;
while((line = reader.readline()) != null){
output.append(line).append("\r\n"); // output = StringBuilder, reader = BufferedReader
}
ここで見たように、これに:
output.append(IOUtils.toString(proc.getInputStream(), "UTF-8"));
ブラウザはラグからより速く回復しました。
明らかに、まだ十分ではありません。でコードの実行が許可されていてn=5 seconds
、 で実行される<n seconds
場合、ブラウザも同様に遅延し<n seconds
ます。
質問:これを回避するには、どのような方法を使用できますか? ページがすぐに応答を受け取り、残りの出力が続くように、出力チャンクを部分的に送信することを考えています。これが良いアプローチである場合、jquery とスプリング コントローラーでどのように構成すればよいですか?
またはもっと重要なことに、より良いアプローチはありますか?
PS:行をコメントアウトするとラグがなくなるため、InputStream の追加が問題であると確信しています。