我一直在尝试创建一个本地进程,它将充当我的服务器的CLI。这个想法类似于Drush对Drupal服务器的作用。
我还没有创建CLI界面(可能会使用第三方代码)但我想分享我的解决方案,以解决我在此问题上遇到的最大障碍:在本地进程之间将消息传输到运行和活动服务器而不使用REST服务,因为它们会增加某些命令的安全风险。
答案 0 :(得分:0)
注意:此代码用Scala编写,但可以转换为Java
首先,我们需要创建一个扩展HttpServlet的servlet类。对于每个GET请求,servlet类将检查我们的线程(稍后解释)是否打开,如果没有尝试启动它。请注意,我们正在使用带有start方法的try catch,因为如果线程的状态是TERMINATED,则isAlive将返回true(我不知道为什么)。
如果servlet死掉,我也正在实现destroy方法来杀死我们的线程。我不确定如果servlet死了会运行线程会发生什么,但以防万一...
<强> Servlet.scala:强>
package com.example
import javax.servlet.http.HttpServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
class Servlet extends HttpServlet {
override def doGet(req: HttpServletRequest, resp: HttpServletResponse) = {
if (!CLIThread.isAlive) {
try {
CLIThread.start
}
catch {
case _ => resp.getOutputStream().println("Error: thread state is, " + CLIThread.getState)
}
}
resp.getOutputStream().println(CLIThread.pool)
}
override def destroy(): Unit = {
super.destroy()
CLIThread.shutdown
}
}
我们的主题(CLIThread)是scala object扩展Thread类。
CLIThread有2种方法,pool&amp; shutdown,并将它们都传递给我们的Runnable实现。
CLIRunnable是传递给Thread构造函数的Runnable实现对象。
CLIRunnable有一个无效的ServerSocket(监听器),Socket(socket)&amp; InputStream(in),一个真正的布尔值(keepAlive)和一个空字符串(_pool)作为变量。
运行方法:
池方法:
关机方法:
<强> CLIThread.scala 强>
package com.example
import java.io.InputStream
import java.net.ServerSocket
import java.net.Socket
object CLIThread extends Thread(CLIRunner) {
def pool: String = CLIRunner.pool
def shutdown() = CLIRunner.shutdown()
}
protected final object CLIRunner extends Runnable {
var listener: ServerSocket = null
var socket: Socket = null
var in: InputStream = null
private var keepAlive = true
private var _pool = ""
def run: Unit = {
var ok = false
while (!ok) {
try {
listener = new ServerSocket((math.random * 10000).toInt)
ok = true;
}
catch {
case _ => {}
}
}
socket = listener.accept()
in = socket.getInputStream
while (keepAlive) {
while (in.available() > 0) _pool += in.read().toChar
}
}
def pool: String = if (in != null) {
val temp = _pool
_pool = ""
return temp
}
else if (listener != null) (listener.getInetAddress, listener.getLocalPort).toString
else "listener == null..."
def shutdown() {
keepAlive = false
if (listener != null) {
if (socket == null)
(new Socket(listener.getInetAddress, listener.getLocalPort)).close()
if (socket != null)
socket.close()
listener.close()
}
}
}
<强> CLI.scala 强>
package com.example
import java.net.Socket
import java.net.URL
object CLI extends App {
val addr = args(0) // The server address (example.com:8080)
val addrUrl = new URL("http://" + addr + "/~cli/addr")
var con = addrUrl.openConnection()
var in = con.getInputStream()
var cliAddr = ""
while (in.available() > 0)
cliAddr += in.read.toChar
val portUrl = new URL("http://" + addr + "/~cli/port")
con = portUrl.openConnection()
in = con.getInputStream()
var cliPort = ""
while (in.available() > 0)
cliPort += in.read.toChar
val socket = new Socket(cliAddr, Integer.valueOf(cliPort))
implicit def stringToByteArray(s: String) = s.toCharArray.map(c => c.toByte)
socket.getOutputStream().write("Hellllo from CLI process")
}
<强> CliAddr.scala 强>
package org.sdms
import javax.servlet.http.HttpServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
class CliAddr extends HttpServlet {
override def doGet(req: HttpServletRequest, resp: HttpServletResponse) {
resp.getWriter.print(CLIRunner.listener.getInetAddress.getHostAddress)
}
}
<强> CliPort.scala 强>
package com.example
import javax.servlet.http.HttpServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
class CliPort extends HttpServlet {
override def doGet(req: HttpServletRequest, resp: HttpServletResponse) {
resp.getWriter.print(CLIRunner.listener.getLocalPort)
}
}