配置
consumer的xml 如下:
privoder配置如下:
privoder 端暂时不看, 当consumer 端在xml 中将需要调用的类配置进去的时候,dubboNamespaceSupport 会解析这些标签并且将之注入spring容器中 具体源码解析可以看此处
使用xml 文件 在类中@Autowired 获取代理对象
例如UserService 我们就可以在consumer 端用@Autowired 按类型方式注入然后直接调用。需要注意的是不是在xml 中配置一下 然后就可以autowired 进来的, 一定要在consumer的pom中将privoide 暴露的接口依赖进来
不使用xml 利用纯注解方式
@Reference(check = false, cluster = "failover", retries = 3, loadbalance = "random")
AnnotationService annotationService;
这边reference就是获取远程privoder 的实例。
我们可以进reference 注解中去看一看,对其中的一些属性本人做了一下注释
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface Reference {
Class<?> interfaceClass() default void.class;
String interfaceName() default "";
// 添加版本号,比如同一个Service 机器上跑的是1.0版本,然后公司又开发了1.1 版本,这个时候你不知道放生产上行不行,于是你可以将一部分机器上的代码布成1.1 版本的 ,看看效果, 可以的换,在夜里 你懂得再将其他的代码换掉。
String version() default "";
// 当两个服务继承的同一个接口,可以用这个区分
String group() default "";
// 这个代表直连某个privoder
String url() default "";
String client() default "";
boolean generic() default false;
// 优先走本地jvm
boolean injvm() default false;
// 是否检查有没有这个服务
boolean check() default false;
boolean init() default false;
// 是否懒加载
boolean lazy() default false;
boolean stubevent() default false;
String reconnect() default "";
boolean sticky() default false;
String proxy() default "";
String stub() default "";
String cluster() default "";
int connections() default 0;
int callbacks() default 0;
String onconnect() default "";
String ondisconnect() default "";
String owner() default "";
String layer() default "";
int retries() default 0;
String loadbalance() default "";
boolean async() default false;
int actives() default 0;
boolean sent() default false;
String mock() default "";
String validation() default "";
int timeout() default 0;
String cache() default "";
String[] filter() default {};
String[] listener() default {};
String[] parameters() default {};
String application() default "";
String module() default "";
String consumer() default "";
String monitor() default "";
String[] registry() default {};
}
根据版本号调用:
privoder:
@Service(group = "groupImpl1", version = "1.0.1")
public class GroupImpl1 implements Group {
public String doSomething(String param) {
System.out.println("=====================groupImpl1.doSomething");
return "groupImpl1.doSomething";
}
}
consumer:
@Reference(group = "groupImpl1", check = false,version="1.0.1" )
Group group1;
如果privoder 填了版本号 consumer 出不填版本号 则报错。
groupImpl1 和groupImpl2 继承同一个接口 consumer 端如何调用
privoder:
@Service(group = "groupImpl1")
public class GroupImpl1 implements Group {
public String doSomething(String param) {
System.out.println("=====================groupImpl1.doSomething");
return "groupImpl1.doSomething";
}
}
@Service(group = "groupImpl2")
public class GroupImpl2 implements Group {
public String doSomething(String param) {
System.out.println("=====================GroupImpl2.doSomething");
return "GroupImpl2.doSomething";
}
}
consumer 端
@Reference(group = "groupImpl1", check = false)
Group group1;
@Reference(group = "groupImpl2", check = false)
Group group2;
校验参数,不符合要求不通过
privoder:
可以将需要校验的参数放到一个实体类中
public class ValidationParamter implements Serializable {
/**
* @Fields serialVersionUID TODO
*/
private static final long serialVersionUID = 32544321432L;
@NotNull
@Size(min = 2, max = 20)
private String name;
@Min(18)
@Max(100)
private int age;
@Past
private Date loginDate;
@Future
private Date expiryDate;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getLoginDate() {
return loginDate;
}
public void setLoginDate(Date loginDate) {
this.loginDate = loginDate;
}
public Date getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(Date expiryDate) {
this.expiryDate = expiryDate;
}
}
// 也可用注解
public interface ValidationService {
void save(ValidationParamter parameter);
void update(ValidationParamter parameter);
void delete(@Min(1) long id,
@NotNull @Size(min = 2, max = 16) String operation);
}
@Service
public class ValidationServiceImpl implements ValidationService {
public void save(ValidationParamter parameter) {
System.out.println("==================save");
}
public void update(ValidationParamter parameter) {
System.out.println("==================update");
}
public void delete(long id, String operation) {
System.out.println("==================delete");
}
}
consumer 端:
//开启validation
@Reference(check = false, validation = "true")
ValidationService validationService;
@RequestMapping("/validation")
public @ResponseBody String validation() {
try {
ValidationParamter parameter = new ValidationParamter();
parameter.setName("jack");
parameter.setAge(101);
parameter.setLoginDate(new Date(
System.currentTimeMillis() - 10000000));
parameter.setExpiryDate(new Date(
System.currentTimeMillis() + 10000000));
validationService.save(parameter);
System.out.println("validation save ok");
// validationService.delete(2, "1");
return "OK";
}
catch (RpcException e) {
e.printStackTrace();
// 获取错误信息
ConstraintViolationException ve = (ConstraintViolationException)e.getCause();
Set<ConstraintViolation<?>> constraintViolations = ve.getConstraintViolations();
System.out.println(constraintViolations);
}
return "OK";
}
泛化调用
dubbo 中每个service 实际上都是继承genericService的
privoder:
@Service
public class AreaManagerImpl implements AreaManager {
public String queryArea(String id) {
System.out.println("====================" + id);
return "====================" + id;
}
}
consumer:
@RequestMapping("/generictestshiyong")
public @ResponseBody String generictestshiyong() {
GenericService genericService = (GenericService)application.getBean("areaManagerxxxx");
Object result = genericService.$invoke("queryArea",
new String[] {"java.lang.String"},
new Object[] {"jackid"});
return result.toString();
}
consumer xml:
<dubbo:reference id="areaManagerxxxx" interface="com.zhuguang.jack.shiyong.AreaManager" check="false" generic="true"/>
最后本人猜测一下实现, 实际上感觉和手撸dubbo 差不多的实现(纯属猜测):
public Object $invoke(String method, String[] parameterTypes, Object[] args)
throws GenericException {
try {
Method me=this.getClass().getMethod(method, Class.forName(parameterTypes[0]).getClass());
me.invoke(args);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
};
}