net.gdface.facelog.BaseServiceController Maven / Gradle / Ivy
package net.gdface.facelog;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import net.gdface.utils.NetworkUtil;
/**
* 本地服务进程控制器基类
* 如果服务指定为本机服务,则尝试连接,连接不上则尝试启动
* @author guyadong
*
*/
public abstract class BaseServiceController implements ServiceConstant{
protected static final long DEFAULT_TRY_INTERVAL = 2000L;
protected static final int DEFAULT_TRY_COUNT = 10;
protected volatile Object embeddedObject;
protected volatile Process process;
protected URI location;
/** 当服务不存在时是否等待 */
protected boolean waitIfAbsent = false;
/** 尝试连接服务的次数 */
protected int tryCountLimit = DEFAULT_TRY_COUNT;
/** 尝试连接服务的时间间隔(毫秒) */
protected long tryInterval = DEFAULT_TRY_COUNT;
protected BaseServiceController() {
/** 程序结束时关闭服务 */
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run() {
try {
if(isEmbedded()){
shutdownEmbeddedServer();
}else{
shutdownLocalServer();
}
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
}
});
}
/**
* 测试服务是否可连接
* @return 可连接返回{@code true},否则返回{@code false}
*/
abstract protected boolean testConnect();
/**
* 根据配置文件返回是否有启动本地服务的条件
* @return 可以启动本地服务返回{@code true},否则返回{@code false}
*/
abstract protected boolean canStartLocal();
/**
* 本地服务是否为嵌入服务
* @return
*/
abstract protected boolean isEmbedded();
/**
* 启动本地(独立进程)服务
* {@link isEmbeddedServer}返回{@code false}时子类必须重写此方法
* @return 服务进程对象
*/
protected Process startLocalServer(){
throw new UnsupportedOperationException();
}
/**
* 启动本地嵌入服务
* {@link isEmbeddedServer}返回{@code true}时子类必须重写此方法
* @return 启动嵌入式服务对象后返回的对象,如果启动的嵌入式服务不需要显式执行关闭,则返回{@code null}
*/
protected Object startEmbeddedServer(){
throw new UnsupportedOperationException();
}
/**
* 服务连接初始化,并测试连接,如果连接异常,则尝试启动本地服务器或等待服务启动
* @return 连接参数和工厂类实例是否更新
*/
boolean init(){
int tryCount = this.tryCountLimit;
boolean selfBind = NetworkUtil.selfBind(location.getHost());
String name = serviceName();
do{
// 测试服务器连接
if(testConnect()){
return false;
}
if(selfBind){
// 如果 服务指定为本地启动则尝试启动服务器
if( canStartLocal() ){
if(isEmbedded()){
embeddedObject = startEmbeddedServer();
// 嵌入式服务启动成功后不需要调用testConnect
return false;
}else{
process = startLocalServer();
}
for(int c=0;c 0){
logger.info("waiting for activemq server...{}",tryCount);
} else {
throw new RuntimeException(String.format("cann't connect %s server(无法连接%s服务器) %s",name,name,location));
}
try {
Thread.sleep(tryInterval);
} catch (InterruptedException e) {
break;
}
}while(tryCount >0);
throw new RuntimeException(String.format("cann't connect %s server(无法连接%s服务器) %s",name,name,location));
}
/**
* 返回服务名,默认使用当前类名,类名以"Controller"结尾时去掉此结尾转小写为服务名
* @return 服务名
*/
protected String serviceName(){
String name = getClass().getSimpleName();
if(name.endsWith("Controller")){
return name.substring(0, name.lastIndexOf("Controller") ).toLowerCase();
}
return name;
}
/**
* 尝试查找{@code closeMethodNames}列表指定的close方法,如果有则执行,如果没有则输出警告信息
* @param closeMethodNames
* @return 成功执行close方法则返回{@code true},否则返回{@code false}
*/
private boolean runCloseMethod(String ...closeMethodNames){
for(String name:closeMethodNames){
try {
embeddedObject.getClass().getMethod(name).invoke(embeddedObject);
embeddedObject = null;
return true;
} catch (NoSuchMethodException e) {
continue;
} catch (IllegalAccessException | SecurityException e) {
e.printStackTrace();
return false;
}catch (InvocationTargetException e) {
e.getTargetException().printStackTrace();
return false;
}
}
return false;
}
/**
* 中止本地嵌入式服务
* 如果{@link #embeddedObject}为{@link AutoCloseable}实例,则执行close方法完成关闭,
* 否则尝试查找{@code close()}方法,如果有则执行,如果没有则输出警告信息后返回
* 子类根据需要重写此方法
*/
protected void shutdownEmbeddedServer(){
if(embeddedObject != null){
synchronized (this) {
if(embeddedObject != null){
if(embeddedObject instanceof AutoCloseable){
// 如果{@link #embeddedObject}为{@link AutoCloseable}实例,则执行close方法完成关闭
try {
((AutoCloseable)embeddedObject).close();
String name = serviceName();
logger.info("shutdown {} server(关闭{}服务)",name,name);
embeddedObject = null;
} catch (Exception e) {
e.printStackTrace();
}
}else{
// 尝试查找close 方法,如果有则执行,如果没有则输出警告信息
if(!runCloseMethod("close","stop")){
logger.warn("CAN'T run shutdown embedded server,please override this method to immplement your own logic");
}
}
}
}
}
}
/**
* 中止本地服务
* 子类根据需要重写此方法
*/
protected void shutdownLocalServer(){
if(process != null){
synchronized (this) {
if(process != null){
try {
process.exitValue();
} catch (IllegalThreadStateException e) {
String name = serviceName();
logger.info("shutdown {} server(关闭{}服务)",name,name);
process.destroy();
}
process = null;
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy