![](/img/trans.png)
[英]Is there a Java database API which I can use exclusively from beanshell?
[英]Can I write to the Beanshell console from Java?
我在我的應用程序中使用Beanshell作為嵌入式調試工具。 這意味着我可以遠程登錄到我的應用程序並在其運行時使用其內部功能(我通常用rlwrap包裝telnet會話)。
問題是,我發現打印到Beanshell控制台的唯一方法是Beanshell中的print()方法,而不是應用程序本身的stdout。
但我想用Java編寫代碼,我可以從Beanshell調用它,它將輸出到Beanshell控制台 - 即。 它將顯示在我的telnet會話中,而不是發送到應用程序的stdout,如果您嘗試使用System.out或System.err。
這可能嗎?
編輯:為了進一步說明,我正在設置一個Beanshell服務器,如下所示:
public static void setUpBeanshell() {
try {
i.setShowResults(true);
i.eval(new InputStreamReader(Bsh.class.getResourceAsStream("init.bsh")));
i.eval("server(" + Main.globalConfig.beanShellPort + ");");
} catch (final EvalError e) {
Main.log.error("Error generated while starting BeanShell server", e);
}
}
我如何修改它,以便我可以編寫一個輸出到telnet會話的Java函數(而不是我的應用程序的System.out)
我會把它復制到那里,因為這些日子里的評論似乎被忽視了。
你可以:而不是有一個方法將調試信息打印到標准輸出返回調試信息:
class ClientList {
Integer clients = 0;
public String debugClientList() {
return clients.toString();
}
然后從beanshell調用它
print(clients.debugCientList());
會在你的telnet上給你一個輸出
或者如果你需要更多的記錄器,你需要直接與Interpreter對象進行交互
InterpreterSingleton {
public static final void Console console = new Interpreter();
}
....
class ClientList {
Integer clients = 0;
public void addClient(Client c) {
....
InterpreterSingleton.console.print("Client added, clients now are " + clients);
}
我在那里回復評論,因為它需要更多的編碼; telnet實現為每個連接使用不同的解釋器,因此您必須將該解釋器公開給對象以便打印到telnet客戶端。 最快的方法是在默認的telnet服務器中更改一些位並使用修改后的服務器啟動服務器,而不是使用server()腳本命令(它在lgpl或sun許可條款下)
請注意,這種方式為每個連接啟動了一個解釋器; 簡單快速的解決方法是維護所有正在運行的解釋器的列表,並向每個解釋器打印調試信息,因此:
class InterpreterSingletonList {
public static final void Set<Interpreter> is = new HashSet();
void printToAll(String s) {
for (Interpreter i: is) {
i.print(s);
}
}
}
package bsh.util;
import java.io.*;
import java.net.Socket;
import java.net.ServerSocket;
import bsh.*;
/**
BeanShell remote session server.
Starts instances of bsh for client connections.
Note: the sessiond effectively maps all connections to the same interpreter
(shared namespace).
*/
public class Sessiond extends Thread
{
private ServerSocket ss;
NameSpace globalNameSpace;
public Sessiond(NameSpace globalNameSpace, int port) throws IOException
{
ss = new ServerSocket(port);
this.globalNameSpace = globalNameSpace;
}
public void run()
{
try
{
while(true)
new SessiondConnection(globalNameSpace, ss.accept()).start();
}
catch(IOException e) { System.out.println(e); }
}
}
class SessiondConnection extends Thread
{
NameSpace globalNameSpace;
Socket client;
SessiondConnection(NameSpace globalNameSpace, Socket client)
{
this.client = client;
this.globalNameSpace = globalNameSpace;
}
public void run()
{
try
{
InputStream in = client.getInputStream();
PrintStream out = new PrintStream(client.getOutputStream());
/* this is the one you're looking for */
Interpreter i = new Interpreter(
new InputStreamReader(in), out, out, true, globalNameSpace);
i.setExitOnEOF( false ); // don't exit interp
/*store the interpreter on the list*/
InterpreterSingletonList.is.add(i);
i.run();
/*remove it (i.run() blocks)*/
InterpreterSingletonList.is.remove(i);
}
catch(IOException e) { System.out.println(e); }
}
}
我認為這是不可能的黑客...,抱歉,適應BSH的telnet服務器實現。
我們bsh.util.Sessiond
的類是bsh.util.Sessiond
。 一旦啟動,它將打開並維護一個telnet服務器。 當它收到命令時,它會創建一個新的工作線程,這將創建一個新的bsh.Interpreter,其中包含正確的輸入和輸出流(從套接字派生)並運行解釋器。
所以有意義的是,只有解釋命令的輸出才會發送到telnet客戶端,因為System.out
和System.err
不會被重定向。
但這正是您需要做的事情:在解釋器運行命令之前將System.out
和System.err
重定向到套接字輸出流,並在完成后重置流。
我建議你將bsh.util.Sessiond
類復制到類似mybsh.util.DebuggerSessiond
東西,將重定向代碼應用到內部類SessiondConnection的run方法,並修改bsh/commands/server.bsh
以啟動這個'new 'telnet服務器另外(或代替原來的)。 (我想,這個腳本啟動了服務器...)
源代碼可以在這里找到: beanshell存儲庫
如果所有應用程序的輸出都是使用某些日志記錄框架編寫的,那么您可以編寫一個自定義appender / handler,除了日志記錄之外還要寫一個文件會寫入beanshell控制台嗎? 執行某些beanshell命令后,可能啟用和禁用控制台日志記錄。
(我以前不知道豆殼,但它看起來很有用!)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.