转载地址:http://blog.csdn.net/m_vptr/article/details/9163319
相对于客户端,服务器端工作就比较多了。服务器端需要load jar包,利用fliter实现方法级的权限控制
- // load service config
- logger.info("load service config...");
- ServiceConfig sc = loadServiceConfig(gaeaConfigDefaultPath, gaeaConfigPath);
- // init class loader
- logger.info("-----------------loading global jars------------------");
- DynamicClassLoader classLoader = new DynamicClassLoader();
- classLoader.addFolder(
- rootPath + "service/deploy/" + sc.getString("gaea.service.name") + "/",
- rootPath + "service/lib/",
- rootPath + "lib"
- );
- //通过反射调用URLClassLoader的addURL方法
- GlobalClassLoader.addSystemClassPathFolder(
- rootPath + "service/deploy/" + sc.getString("gaea.service.name") + "/",
- rootPath + "service/lib/",
- rootPath + "lib"
- );
- logger.info("-------------------------end-------------------------\n");
- if(new File(serviceFolderPath).isDirectory() || serviceName valid) {
- // load proxy factory
- logger.info("--------------------loading proxys-------------------");
- IProxyFactory proxyFactory = ProxyFactoryLoader.loadProxyFactory(classLoader);
- Global.getSingleton().setProxyFactory(proxyFactory);
- logger.info("-------------------------end-------------------------\n");
- // load init beans
- logger.info("-----------------loading init beans------------------");
- loadInitBeans(classLoader, sc);
- logger.info("-------------------------end-------------------------\n");
- }
- // load global request-filters
- logger.info("-----------loading global request filters------------");
- List<IFilter> requestFilters = loadFilters(classLoader, sc, "gaea.filter.global.request");
- for(IFilter filter : requestFilters) {
- Global.getSingleton().addGlobalRequestFilter(filter);
- }
- logger.info("-------------------------end-------------------------\n");
- // load global response-filters
- logger.info("-----------loading global response filters-----------");
- List<IFilter> responseFilters = loadFilters(classLoader, sc, "gaea.filter.global.response");
- for(IFilter filter : responseFilters) {
- Global.getSingleton().addGlobalResponseFilter(filter);
- }
- logger.info("-------------------------end-------------------------\n");
- // load connection filters
- logger.info("-----------loading connection filters-----------");
- List<IFilter> connFilters = loadFilters(classLoader, sc, "gaea.filter.connection");
- for(IFilter filter : connFilters) {
- Global.getSingleton().addConnectionFilter(filter);
- }
- logger.info("-------------------------end-------------------------\n");
- // load secureKey 当gaea.secure不为true时不启动权限认证
- logger.info("------------------load secureKey start---------------------");
- if(sc.getString("gaea.secure") != null && "true".equalsIgnoreCase(sc.getString("gaea.secure"))) {
- logger.info("gaea.secure:" + sc.getString("gaea.secure"));
- loadSecureKey(sc,serviceFolderPath);
- }
- logger.info("------------------load secureKey end----------------------\n");
- // load servers
- logger.info("------------------ starting servers -----------------");
- loadServers(classLoader, sc);
- logger.info("-------------------------end-------------------------\n");
- // add current service file to monitor
- if(sc.getBoolean("gaea.hotdeploy")) {
- logger.info("------------------init file monitor-----------------");
- addFileMonitor(rootPath, sc.getString("gaea.service.name"));
- logger.info("-------------------------end-------------------------\n");
- }
//load proxy factory
- //ProxyFactoryLoader.loadProxyFactory
- CreateManager cm = new CreateManager();
- return cm.careteProxy(Global.getSingleton().getRootPath()
- + "service/deploy/"
- + ("gaea.service.name"),
- classLoader);
- // CreateManager.createProxy
- //ContractInfo
- if (file != null && file.exists()) {
- //如果存在Serviceframe.xml
- serviceContract = ContractConfig.loadContractInfo(configPath, classLoader);
- } else {
- //只扫描deploy/{serviceName}目录下的jar包
- serviceContract = ScanClass.getContractInfo(serviceRootPath + "/", classLoader);
- }
ServerContract是SessionBean的列表,SessionBean包括接口名,接口->实例Map,类信息。在Serviceframe.xml中可配置.
如果存在Serviceframe.xml,则扫描Serviceframe.xml,否则直接扫描jar包。
Serviceframe.xml的格式为:
- <interface>
- <class></class>
- <lookup></lookup>
- </interface>
// ScanClass.getContractInfo
- //扫描注解,分别解析contract(接口),behavior(实现)
- ServiceBehaviorbehavior = cls.getAnnotation(ServiceBehavior.class);
- ServiceContract contract= cls.getAnnotation(ServiceContract.class);
- if(behavior==null && contract == null) {
- continue;
- }
- if(contract !=null) {
- ClassInfo ci = contract(cls);
- if(ci !=null) {
- contractClassInfos.add(ci);
- }
- } elseif(behavior!= null) {
- ClassInfo ci = behavior(cls);
- if(ci !=null) {
- behaviorClassInfos.add(ci);
- }
- }
- //ScanClass.Contract()
- //获取该类所有接口
- List<Class<?>>interfaceList = getInterfaces(cls);
- List<ClassInfo.MethodInfo>methodInfos = newArrayList<ClassInfo.MethodInfo>();
- for(Class<?>interfaceCls : interfaceList) {
- //接口所有方法
- Method[]methods = interfaceCls.getDeclaredMethods();
- if(contractAnn!=null && contractAnn.defaultAll()){
- for(Methodm : methods) {
- if(Modifier.isPublic(m.getModifiers())|| Modifier.isProtected(m.getModifiers())) {
- ClassInfo.MethodInfo mi =newClassInfo.MethodInfo();
- mi.setMethod(m);
- methodInfos.add(mi);
- }
- }
- }else {
- //没有@ServiceContract注解则默认扫Public并OperationContract注解了的方法
- for(Methodm : methods) {
- if(Modifier.isPublic(m.getModifiers())|| Modifier.isProtected(m.getModifiers())) {
- OperationContract oc =m.getAnnotation(OperationContract.class);
- if(oc !=null) {
- ClassInfo.MethodInfo mi =newClassInfo.MethodInfo();
- mi.setMethod(m);
- methodInfos.add(mi);
- }
- }
- }
- }
- }
- //ScanClass.behavior()
- //扫描Method,如果发现HttpPathParameter注解,则加载RequestMapping。
//构造ContractInfo
- //根据以上两步结果,构造ContractInfo
- contractInfo =createContractInfo(contractClassInfos,behaviorClassInfos);
- //构造过程
- ContractInfocontractInfo = new ContractInfo();
- List<SessionBean>sessionBeanList = newArrayList<SessionBean>();
- for(ClassInfoc : contracts) {
- SessionBeanbean = new SessionBean();
- bean.setInterfaceClass(c);
- bean.setInterfaceName(c.getCls().getName());
- Map<String,String> implMap = newHashMap<String, String>();
- //扫描和接口匹配的实现
- for(ClassInfob : behaviors) {
- Class<?>[]interfaceAry = b.getCls().getInterfaces();
- for(Class<?>item : interfaceAry) {
- if(item ==c.getCls()) {
- implMap.put(b.getLookUP(),b.getCls().getName());
- break;
- }
- }
- }
- bean.setInstanceMap(implMap);
- sessionBeanList.add(bean);
- }
- contractInfo.setSessionBeanList(sessionBeanList);
- return contractInfo;
//创建ProxyClass
- List<ClassFile> localProxyList = new ProxyClassCreater().createProxy(classLoader, serviceContract, time);
- //ProxyClassCreater.createProxy()
- String proxyClassName = lookup + "ProxyStub" + time;
- CtClass ctProxyClass = pool.makeClass(proxyClassName, null);
- ctProxyClass.addInterface(localProxy); // IProxyStub接口
- CtField proxyField = CtField.make( //构造实例
- "private static " +sessionBean.getInterfaceName() +" serviceProxy = new " +implClassName +"();", ctProxyClass);
- ctProxyClass.addField(proxyField);
- //创建 method
- for(Method m : uniqueMethodList) {
- logger.debug("create method:" + m.getName());
- String methodStr = createMethods(proxyClassName, m.getName(), allMethodList, uniqueNameList);
- CtMethod methodItem = CtMethod.make(methodStr, ctProxyClass);
- ctProxyClass.addMethod(methodItem);
- }
- //创建invoke方法
- String invokeMethod = createInvoke(proxyClassName, uniqueNameList);
- logger.debug("create invoke method:" + invokeMethod);
- CtMethod invoke = CtMethod.make(invokeMethod, ctProxyClass);
- ctProxyClass.addMethod(invoke);
- clsList.add(new ClassFile(proxyClassName, ctProxyClass.toBytecode()));
- }
- //Invoke方法体,使用到了GaeaResponse和GaeaContext
- private String createInvoke(String className, List<String> uniqueNameList) {
- StringBuilder sb = new StringBuilder();
- sb.append("public " + Constant.GAEARESPONSE_CLASS_NAME + " invoke(" + Constant.GAEACONTEXT_CLASS_NAME + " context) throws " + Constant.SERVICEFRAMEEXCEPTION_CLASS_NAME + " {");
- sb.append("String methodName = ((" + Constant.REQUEST_PROTOCOL_CLASS_NAME + ")context.getGaeaRequest().getProtocol().getSdpEntity()).getMethodName();");
- for (String methodName : uniqueNameList) {
- sb.append("if(methodName.equalsIgnoreCase(\"");
- sb.append(methodName);
- sb.append("\")){return ");
- sb.append(methodName);
- sb.append("(context);}");
- }
- sb.append("throw new " + Constant.SERVICEFRAMEEXCEPTION_CLASS_NAME + "(\"method:" + className + ".invoke--msg:not found method (\"+methodName+\")\", context.getChannel().getRemoteIP(), context.getChannel().getLocalIP(), context.getGaeaRequest().getProtocol().getSdpEntity(), " + Constant.ERRORSTATE_CLASS_NAME + ".NotFoundMethodException, null);");
- sb.append("}");
- return sb.toString();
- }
- ClassFile cfProxyFactory = new ProxyFactoryCreater().createProxy(classLoader, serviceContract, time);
- IProxyFactory pfInstance = (IProxyFactory)constructor.newInstance(localProxyAry);
- //constructor为ProxyFactory实例,里面初始化所有实例
//gaea.init的init方法
- // load init beans
- loadInitBeans(classLoader, sc);
//loadSecureKey 最终将配置文件中 //secure 信息添加到 Global.secureMap
- loadSecureKey(sc,serviceFolderPath);
// load servers
- loadServers(classLoader, sc);
- //建立gaea.servers[].implement实例并调用start
主要工作总结如下:
解析gaea配置文件gaea_config.xml
添加jar包到系统Classloader
扫描deploy/{serviceName}下的jar包,根据@ServiceContract等注解建立实现类(SessionBean)和该实现类对应接口的映射关系。
创建SessionBean对应的代理ProxyStub,该代理类负责将调用转交给实现类,并在接口上对参数做一层包装。分别使用GaeaResponse和GaeaContext为返回、参数类型。
创建Proxy工厂类,包含了SessionBean实例。
加载Filter
加载SecureKey配置
调用配置文件gaea.init的方法
加载Server
Proxy工厂类其实是以后请求处理的入口,客户端请求经过包装后发送到服务器端,服务器端解析消息,Proxy工厂根据消息调用对应SessionBean的某个方法。