JsonRpc源码修改(优化)

问题一:
以@JsonRpc注解的接口必须有value值,而且value值必须不能以 /开头,类似于这样:

@JsonRpcService("jsonRpc/products") 这里注意,不能以 /开头,后面修改源码解决这个问题
public interface IProductRpcService {

    /**
     * 根据请求参数,获取请求内容
     * @param req
     * @return
     */
     List findProduct(ProductRpcReq req);

    /**
     * 根据id获取产品
     * @param id
     * @return
     */
     Product findProductById(String id);
}

问题二:
调用远端接口的baseUrl必须以/ 结尾,类似于这样:

rpc:
  client:
    url: http://localhost:8081/manager
    basePackage: com.chukun.api.rpc

这两个问题,都是新手比较容易犯的错误,现在优化,@JsonRpcService不写,默认是接口的全类名,baseUrl不以 /结尾,自动添加

@JsonRpcService在服务端优化:
1.修改注解的默认值:

@Target(TYPE)
@Retention(RUNTIME)
public @interface JsonRpcService {
	
	/**
	 * The path that the service is available at.
	 *
	 * @return the service path
	 */
	String value() default ""; 添加默认值
}

2.找到AutoJsonRpcServiceImplExporter类,进入,发现这个类实现了spring的后置处理器,找到实现的方法:

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
		//此方法获取bean的定义信息
		Map servicePathToBeanName = findServiceBeanDefinitions(defaultListableBeanFactory);
		for (Entry entry : servicePathToBeanName.entrySet()) {
			registerServiceProxy(defaultListableBeanFactory, makeUrlPath(entry.getKey()), entry.getValue());
		}
	}

3.进入findServiceBeanDefinitions方法:发现在此方法中,添加注解的value值:

private static Map findServiceBeanDefinitions(ConfigurableListableBeanFactory beanFactory)
  {
    Map serviceBeanNames = new HashMap();
    String beanName;
    for (beanName : beanFactory.getBeanDefinitionNames())
    {
      AutoJsonRpcServiceImpl autoJsonRpcServiceImplAnnotation = (AutoJsonRpcServiceImpl)beanFactory.findAnnotationOnBean(beanName, AutoJsonRpcServiceImpl.class);
      JsonRpcService jsonRpcServiceAnnotation = (JsonRpcService)beanFactory.findAnnotationOnBean(beanName, JsonRpcService.class);
      if (null != autoJsonRpcServiceImplAnnotation)
      {
        if (null == jsonRpcServiceAnnotation) {
          throw new IllegalStateException("on the bean [" + beanName + "], @" + AutoJsonRpcServiceImpl.class.getSimpleName() + " was found, but not @" + JsonRpcService.class.getSimpleName() + " -- both are required");
        }
        List paths = new ArrayList();
        Collections.addAll(paths, autoJsonRpcServiceImplAnnotation.additionalPaths());
        //paths.add(jsonRpcServiceAnnotation.value());  //添加注解的value值
        修改如下:
        paths.add(getCurrentRpcServiceFullClassName((DefaultListableBeanFactory) beanFactory,beanName)); 
        for (String path : paths)
        {
          if (!PATTERN_JSONRPC_PATH.matcher(path).matches()) {
            throw new RuntimeException("the path [" + path + "] for the bean [" + beanName + "] is not valid");
          }
          logger.info("exporting bean [{}] ---> [{}]", beanName, path);
          if (isNotDuplicateService(serviceBeanNames, beanName, path)) {
            serviceBeanNames.put(path, beanName);
          }
        }
      }
    }
    collectFromParentBeans(beanFactory, serviceBeanNames);
    return serviceBeanNames;
  }

paths.add(jsonRpcServiceAnnotation.value()); 重写一个方法,让它添加类的全类名:

/**
     * 获取当前jsonRpc接口的全类名
	 * Registers the new beans with the bean factory.
	 */
	private static String getCurrentRpcServiceFullClassName(DefaultListableBeanFactory defaultListableBeanFactory, String serviceBeanName) {
		BeanDefinition serviceBeanDefinition = findBeanDefinition(defaultListableBeanFactory, serviceBeanName);
		String serviceInterface  = "";
		for (Class currentInterface : getBeanInterfaces(serviceBeanDefinition, defaultListableBeanFactory.getBeanClassLoader())) {
			if (currentInterface.isAnnotationPresent(JsonRpcService.class)) {
				serviceInterface = currentInterface.getName();
				break;
			}
		}
		return serviceInterface;
	}

这样注解就不用写value值,默认是接口的全类名

2.优化baseUrl不以 /结尾,自动添加
客户端优化,找到此类:AutoJsonRpcClientProxyCreator,此类也是实现spring的后置处理器,

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory(applicationContext);
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
		String resolvedPath = resolvePackageToScan();
		logger.debug("Scanning '{}' for JSON-RPC service interfaces.", resolvedPath);
		try {
			for (Resource resource : applicationContext.getResources(resolvedPath)) {
				if (resource.isReadable()) {
					MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
					ClassMetadata classMetadata = metadataReader.getClassMetadata();
					AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
					String jsonRpcPathAnnotation = JsonRpcService.class.getName();
					if (annotationMetadata.isAnnotated(jsonRpcPathAnnotation)) {
						String className = classMetadata.getClassName();
						String path = className;
						logger.debug("Found JSON-RPC service to proxy [{}] on path '{}'.", className, path);
						//此方法,注册调用路径
						registerJsonProxyBean(defaultListableBeanFactory, className, path);
					}
				}
			}
		} catch (IOException e) {
			throw new IllegalStateException(format("Cannot scan package '%s' for classes.", resolvedPath), e);
		}
	}

进入registerJsonProxyBean(defaultListableBeanFactory, className, path)方法,发现:

BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
				.rootBeanDefinition(JsonProxyFactoryBean.class)
				.addPropertyValue("serviceUrl", appendBasePath(path))
				.addPropertyValue("serviceInterface", className);

appendBasePath(path)添加调用路径,继续进入此方法,发现此方法的实现很简单:

 private String appendBasePath(String path)
  {
    try
    {
      return new URL(this.baseUrl, path).toString();//重写
    }
    catch (MalformedURLException e)
    {
      throw new IllegalArgumentException(String.format("Cannot combine URLs '%s' and '%s' to valid URL.", new Object[] { this.baseUrl, path }), e);
    }
  }

重写此方法:

/**
	 * 解决配置prc接口不以 /结尾报错
	 * Appends the base path to the path found in the interface.
	 */
	private String appendBasePath(String path) {
		String baseUrlStr = baseUrl.toString();
		if(!baseUrlStr.endsWith("/")){
			baseUrlStr = baseUrlStr.concat("/");
		}
		return baseUrlStr.concat(path);
	}

启动服务端,测试注解的优化:
JsonRpc源码修改(优化)_第1张图片
发现已经导出为接口的全类名

启动客户端,测试优化的baseUrl:
JsonRpc源码修改(优化)_第2张图片
JsonRpc源码修改(优化)_第3张图片
启动成功

你可能感兴趣的:(Java)