基于 Netty + Spring 实现一个 HTTP REST 服务器(四)Gevlet 源码分享之业务处理

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;
    }
}

完:)

猜你喜欢

转载自blog.csdn.net/qq_38692223/article/details/80269887