Gevlet 源码分享之业务处理
业务处理过程的代码主要在 core下。有 ServerRequestHolder 、ServerContainer、ServerHandler、HttpRestServerHandler、ServiceWrapper、ClassLoaderFactory。
执行顺序为 ServerRequestHolder =》ServerContainer=》HttpRestServerHandler
以下是详细的代码实现
ServerRequestHolder 的作用主要是为了适配不同的网络协议
import com.gevlet.coop.connector.protocol.NetMessagetProtocol;
import java.util.concurrent.ConcurrentHashMap;
public class ServerRequestHolder {
private static volatile ServerRequestHolder serverRequestHolder;
private ConcurrentHashMap<String, ServerHandler> serverHandlers = new ConcurrentHashMap<>();
private ServerRequestHolder() {
}
public synchronized static ServerRequestHolder newInstance() {
if (null == serverRequestHolder) {
serverRequestHolder = new ServerRequestHolder();
}
return serverRequestHolder;
}
public void holdRequest(NetMessagetProtocol message) {
if (null != message) {
if ("HTTP".equals(message.getProtocolType())) {
//处理请求
ServerHandler serverHandler = ServerContainer.getServerContainer().getServerHandler(message.getApplication());
serverHandler.handleRequest(message);
} else if ("TCP/IP".equals(message.getProtocolType())) {
// UN-DO
} else if ("JMX".equals(message.getProtocolType())) {
//UN-DO
}
}
}
}
ServerContainer 作为核心的类,其作用是维护URL有 ServerHandler 的关系,并提供相应的处理方法
import com.gevlet.coop.connector.NetServerConnector;
import com.gevlet.coop.exceptions.ServerInitException;
import com.gevlet.coop.exceptions.ServerLoadeException;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
public class ServerContainer {
private static volatile ServerContainer serverContainer;
private ConcurrentHashMap<String, ServerHandler> serverHandlers = new ConcurrentHashMap<>();
private ServerContainer() {
}
public static synchronized ServerContainer getServerContainer() {
if (null == serverContainer) {
throw new ServerLoadeException("获取应用容器失败,容器为null");
}
return serverContainer;
}
public static synchronized ServerContainer getServerContainer(ClassLoader parentClassloader, String baseLocation) {
if (null == serverContainer) {
serverContainer = new ServerContainer();
serverContainer.loadServers(parentClassloader, baseLocation);
}
return serverContainer;
}
public ServerHandler getServerHandler(String application) {
return serverHandlers.get(application);
}
/**
* 启动所有的服务
*/
public void startServers() {
NetServerConnector.main(new String[]{});
for (;;){
try {
Thread.sleep(1);
}catch (Exception ex){
ex.printStackTrace();
}
}
}
/**
* 加载所有的应用服务
*
* @param parentClassloader
* @param baseLocation
*/
private void loadServers(ClassLoader parentClassloader, String baseLocation) {
for (Repository repository : locadRepositorys(baseLocation)) {
//处理每一个应用
List<Repository> applicationRepositorys = getApplicationRepositorys(repository);
ClassLoader serverClassLoader = ClassLoaderFactory.createClassLoader(applicationRepositorys, parentClassloader);
ServerHandler serverHandler = HttpRestServerHandler.getServer(serverClassLoader);
serverHandlers.put(repository.getApplication(), serverHandler);
}
}
private List<Repository> getApplicationRepositorys(Repository repository) {
List<Repository> repositories = new ArrayList<>();
String location = repository.getLocation();
File appLocation = new File(location);
if (appLocation.exists() && appLocation.isDirectory()) {
//处理 lib
String libJarLocation = location + File.separator + "lib";
File libJarsFile = new File(libJarLocation);
if (libJarsFile.exists() && libJarsFile.isDirectory()) {
File[] jarFiles = libJarsFile.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".jar");
}
});
for (int i = 0; i < jarFiles.length; i++) {
File jarFile = jarFiles[i];
Repository libJarRepository = new Repository(jarFile.getAbsolutePath(), jarFile, repository.application);
repositories.add(libJarRepository);
}
}
//处理 app jar
File packageFile = repository.getPackageFile();
try {
Repository appJar = new Repository(packageFile.getAbsolutePath(), packageFile, repository.application);
repositories.add(appJar);
} catch (Exception ex) {
ex.printStackTrace();
}
}
return repositories;
}
private List<Repository> locadRepositorys(String base) {
File appHomeBaseFile = new File(base);
List<Repository> packageFiles = new ArrayList<>();
if (appHomeBaseFile.exists() && appHomeBaseFile.isDirectory()) {
List<File> applicationsPaths = Arrays.asList(appHomeBaseFile.listFiles());
for (File path : applicationsPaths) {
String application = path.getName();
String applicationPath =
appHomeBaseFile.getAbsolutePath()
+ File.separator + application;
String applicationPackagePath = applicationPath + File.separator + application + ".jar";
File applicationPackageFile = new File(applicationPackagePath);
if (!applicationPackageFile.exists()) {
throw new ServerInitException("找不到应用的jar包");
}
Repository repository = new Repository(applicationPath, applicationPackageFile, application);
packageFiles.add(repository);
}
}
return packageFiles;
}
public class Repository {
private String location;
private File packageFile;
private String application;
public Repository(String location, File packageFile, String application) {
this.location = location;
this.packageFile = packageFile;
this.application = application;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public File getPackageFile() {
return packageFile;
}
public void setPackageFile(File packageFile) {
this.packageFile = packageFile;
}
public String getApplication() {
return application;
}
public void setApplication(String application) {
this.application = application;
}
@Override
public String toString() {
return "Repository{" +
"location='" + location + '\'' +
", packageFile=" + packageFile +
", application='" + application + '\'' +
'}';
}
}
}
ServerHandler 是一个接口,同样可以通过集成来实现不同的 ServerHandler。
public interface ServerHandler {
void start(ClassLoader classLoader);
void handleRequest(NetMessagetProtocol message);
}
以下是HTTP 服务 HttpRestServerHandler 的详细代码实现
import com.alibaba.fastjson.JSON;
import com.gevlet.coop.connector.protocol.NetMessagetProtocol;
import com.gevlet.coop.executor.ServerThreadPoolExecutor;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderValues;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static com.google.common.net.HttpHeaders.*;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
public class HttpRestServerHandler implements ServerHandler {
// 本应用的类加载器
private ClassLoader serverClassLoader;
private static volatile ServerHandler serverHandler;
private Class<?> applicationContextClass;
private Object conextInstance;
private ConcurrentHashMap<String, ServiceWrapper> serviceWrapperMapping = new ConcurrentHashMap<>();
private HttpRestServerHandler() {
}
public static synchronized ServerHandler getServer(ClassLoader classLoader) {
if (null == serverHandler) {
serverHandler = new HttpRestServerHandler();
serverHandler.start(classLoader);
}
return serverHandler;
}
/**
* 处理业务请求
*
* @param message
*/
@Override
public void handleRequest(NetMessagetProtocol message) {
Thread requestHandlerThread = new Thread(new Runnable() {
@Override
public void run() {
boolean isFail = false;
String errorMsg = "";
String requestPath = "/" + message.getPathUrl() + "/" + message.getHandlerUrl();
ServiceWrapper serviceWrapper = serviceWrapperMapping.get(requestPath);
if (null == serviceWrapper) {
isFail = true;
errorMsg = "未找到可用的服务!";
}
String responseStr = "";
FullHttpResponse response = null;
try {
Object service = serviceWrapper.getService();
Method serviceMethod = serviceWrapper.getServiceMethod();
Class<?>[] parameterTypes = serviceMethod.getParameterTypes();
if (null != parameterTypes && parameterTypes.length == 1) {
Class<?> parameterType = parameterTypes[0];
Object requestBody = message.getBody();
String jsonString = JSON.toJSONString(requestBody);
Object parameter = JSON.parseObject(jsonString, parameterType);
Object invokeResult = serviceMethod.invoke(service, parameter);
responseStr = JSON.toJSONString(invokeResult);
}
} catch (Exception ex) {
isFail = true;
errorMsg = ex.getCause().getMessage();
} finally {
if (!isFail) {
response = getResponse(responseStr);
} else {
StringBuilder builder = new StringBuilder();
builder.append("{\"success\":false,\"error\":\"").append(errorMsg).append("\"}");
response = getResponse(builder.toString());
}
ChannelHandlerContext handlerContext = message.getHandlerContext();
handlerContext.write(response);
handlerContext.flush();
}
}
});
ServerThreadPoolExecutor.getExecutor().execute(requestHandlerThread);
}
/**
* 应用服务启动方法
*
* @param classLoader
*/
@Override
public void start(ClassLoader classLoader) {
this.serverClassLoader = classLoader;
Thread serverHandlerThrad = new Thread(new Runnable() {
@Override
public void run() {
Thread.currentThread().setContextClassLoader(serverClassLoader);
try {
Class<?> applicationContextClass = classLoader.loadClass("org.springframework.context.support.ClassPathXmlApplicationContext");
//设置spring 上下文class
setApplicationContextClass(applicationContextClass);
Constructor<?> constructor = applicationContextClass.getConstructor(String.class);
constructor.setAccessible(true);
Object conextInstance = constructor.newInstance("application.xml");
//设置spring 上下文实例
setConextInstance(conextInstance);
//启动spring
Method startMethod = applicationContextClass.getMethod("start");
startMethod.invoke(conextInstance);
Thread.sleep(5);
loadServiceMappingWrapper();
for (; ; ) {
Thread.sleep(1);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
//启动应用服务
serverHandlerThrad.start();
}
private void loadServiceMappingWrapper() {
Class mappingAntClass = getTypeRequestMappingAntClass();
if (null != mappingAntClass) {
try {
Method getBeansWithAnnotation = applicationContextClass.getMethod("getBeansWithAnnotation", Class.class);
getBeansWithAnnotation.setAccessible(true);
Map<String, Object> requestMapping = (Map<String, Object>) getBeansWithAnnotation.invoke(conextInstance, mappingAntClass);
//获取到的 requestMapping
for (Map.Entry<String, Object> entry : requestMapping.entrySet()) {
//服务名称
String serviceName = entry.getKey();
//服务实例
Object service = entry.getValue();
Annotation requestMappingAnnotation = service.getClass().getAnnotation(mappingAntClass);
Method valueMethod = requestMappingAnnotation.getClass().getMethod("value");
valueMethod.setAccessible(true);
// 类型 RequestMapping 注解值
String[] invokeResult = (String[]) valueMethod.invoke(requestMappingAnnotation);
Map<String, ServiceWrapper> serviceWrapperMap = getMethodMapping(serviceName, invokeResult[0], service);
serviceWrapperMapping.putAll(serviceWrapperMap);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
private Map<String, ServiceWrapper> getMethodMapping(String serviceName, String antValueResult, Object service) throws Exception {
Map<String, ServiceWrapper> methodMapping = new HashMap<>();
if (null != service) {
Method[] methods = service.getClass().getMethods();
Class methodRequestMappingAnt = getMethodRequestMappingAntClass();
for (Method method : methods) {
Annotation methodAnnotation = method.getAnnotation(methodRequestMappingAnt);
if (null != methodAnnotation) {
Method valueMethod = methodAnnotation.getClass().getMethod("value");
valueMethod.setAccessible(true);
String[] invokeResult = (String[]) valueMethod.invoke(methodAnnotation);
ServiceWrapper wrapper = new ServiceWrapper();
wrapper.setPath(antValueResult + invokeResult[0]);
wrapper.setService(service);
wrapper.setServiceMethod(method);
wrapper.setServiceName(serviceName);
methodMapping.put(antValueResult + invokeResult[0], wrapper);
}
}
}
return methodMapping;
}
private Class<?> getTypeRequestMappingAntClass() {
try {
Class<?> aClass = serverClassLoader.loadClass("org.springframework.web.bind.annotation.RequestMapping");
return aClass;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
private Class<?> getMethodRequestMappingAntClass() {
try {
Class<?> aClass = serverClassLoader.loadClass("org.springframework.web.bind.annotation.RequestMapping");
return aClass;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
private void setApplicationContextClass(Class<?> contextClass) {
applicationContextClass = contextClass;
}
private void setConextInstance(Object instance) {
conextInstance = instance;
}
private FullHttpResponse getResponse(String resultJson) {
FullHttpResponse response = new DefaultFullHttpResponse(
HTTP_1_1, OK, Unpooled.wrappedBuffer(resultJson
.getBytes()));
response.headers().set(CONTENT_TYPE, "text/json");
response.headers().set(CONTENT_LENGTH,
response.content().readableBytes());
response.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE);
return response;
}
}
ServiceWrapper 是一个包装类,用于包装应用中每个提供服务的方法
public class ServiceWrapper {
private String serviceName;
private String path;
private Object service;
private Method serviceMethod;
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Object getService() {
return service;
}
public void setService(Object service) {
this.service = service;
}
public Method getServiceMethod() {
return serviceMethod;
}
public void setServiceMethod(Method serviceMethod) {
this.serviceMethod = serviceMethod;
}
}