新入职,上级分配了个任务,通过hessian实现rpc,服务端接口接收参数封装成实体类,我实现了一个实体类RemoteParam,包括bean名称,method名称和参数列表,我通过class.getMethod(methodName,classes)来查找方法然后invoke执行它:
public class RemoteParam implements Serializable{
/**
*
*/
private static final long serialVersionUID = 114263984568171511L;
/* bean名称 */
private String beanName;
/* 方法名称 */
private String methodName;
/* 参数列表 */
private List<? extends Serializable> list;
/* 设置连接时间*/
private Long timeout;
/* 子站地址 */
private String website;
/**
* 无参构造方法
*/
public RemoteParam(){
}
/**
* 构造方法
* @param beanName
* @param methodName
*/
public RemoteParam(String beanName,String methodName){
this.beanName=beanName;
this.methodName=methodName;
}
/**
* 构造方法
* @param beanName
* @param methodName
* @param list
*/
public RemoteParam(String beanName,String methodName,List<? extends Serializable> list){
this.beanName=beanName;
this.methodName=methodName;
if(list!=null){
if(!list.isEmpty()){
this.list=list;
}else{
this.list=null;
}
}else{
this.list=null;
}
}
/**
* 构造方法
* @param beanName
* @param methodName
* @param timeout
*/
public RemoteParam(String beanName,String methodName,Long timeout){
this.beanName=beanName;
this.methodName=methodName;
this.timeout=timeout;
}
/**
* 构造方法
* @param beanName
* @param methodName
* @param list
* @param timeout
*/
public RemoteParam(String beanName,String methodName,List<? extends Serializable> list,Long timeout){
this.beanName=beanName;
this.methodName=methodName;
if(list!=null){
if(!list.isEmpty()){
this.list=list;
}else{
this.list=null;
}
}else{
this.list=null;
}
this.timeout=timeout;
}
/**
* 构造方法
* @param beanName
* @param methodName
*/
public RemoteParam(String beanName,String methodName,String website){
this.beanName=beanName;
this.methodName=methodName;
this.website=website;
}
/**
* 构造方法
* @param beanName
* @param methodName
* @param list
*/
public RemoteParam(String beanName,String methodName,List<? extends Serializable> list,String website){
this.beanName=beanName;
this.methodName=methodName;
if(list!=null){
if(!list.isEmpty()){
this.list=list;
}else{
this.list=null;
}
}else{
this.list=null;
}
this.website=website;
}
/**
* 构造方法
* @param beanName
* @param methodName
* @param timeout
*/
public RemoteParam(String beanName,String methodName,Long timeout,String website){
this.beanName=beanName;
this.methodName=methodName;
this.timeout=timeout;
this.website=website;
}
/**
* 构造方法
* @param beanName
* @param methodName
* @param list
* @param timeout
*/
public RemoteParam(String beanName,String methodName,List<? extends Serializable> list,Long timeout,String website){
this.beanName=beanName;
this.methodName=methodName;
if(list!=null){
if(!list.isEmpty()){
this.list=list;
}else{
this.list=null;
}
}else{
this.list=null;
}
this.timeout=timeout;
this.website=website;
}
public String getBeanName() {
return beanName;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public List<? extends Serializable> getList() {
return list;
}
public void setList(List<? extends Serializable> list) {
this.list = list;
}
public Long getTimeout() {
return timeout;
}
public void setTimeout(Long timeout) {
this.timeout = timeout;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
}
public RemoteMsg getRemoteResult(RemoteParam paramObject,LoginBean loginBean){
Object result = null ;
RemoteMsg remoteMsg = new RemoteMsg();
String beanName=paramObject.getBeanName();
String methodName=paramObject.getMethodName();
Object[] objects=null;
Class<?>[] classes=null;
if(paramObject.getList()==null){
objects=new Object[]{};
classes=new Class<?>[]{};
}else{
if(paramObject.getList().isEmpty()){
objects=new Object[]{};
classes=new Class<?>[]{};
}else{
objects=paramObject.getList().toArray();
classes=(Class<?>[])ListUtil.listToClasses(paramObject.getList()).toArray(new Class[0]);
}
}
result=this.invokeMethod(beanName, methodName, objects, classes);
Object jsonResult = JSON.toJSON(result);
remoteMsg.setResult(jsonResult);
return remoteMsg;
}
@Override
public <T> T getRemoteResult(RemoteParam paramObject,LoginBean loginBean,Class<T> clazz){
Object result = null ;
String beanName=paramObject.getBeanName();
String methodName=paramObject.getMethodName();
Object[] objects=null;
Class<?>[] classes=null;
if(paramObject.getList()==null){
objects=new Object[]{};
classes=new Class<?>[]{};
}else{
if(paramObject.getList().isEmpty()){
objects=new Object[]{};
classes=new Class<?>[]{};
}else{
objects=paramObject.getList().toArray();
classes=(Class<?>[])ListUtil.listToClasses(paramObject.getList()).toArray(new Class[0]);
}
}
result=this.invokeMethod(beanName, methodName, objects, classes);
return (T)result;
}
private Object invokeMethod(String beanName, String methodName,
Object[] params, Class... type) {
Object serviceObj = null;
try {
serviceObj = this.context.getBean(beanName);
} catch (NoSuchBeanDefinitionException e) {
throw new RemoteException(RemoteMsgUtils.BEAN_ERROR_TYPE);
}
if (serviceObj == null) {
throw new RemoteException(RemoteMsgUtils.BEAN_ERROR_TYPE);
}
Method m = null;
try {
m = serviceObj.getClass().getMethod(methodName, type);
} catch (Exception e) {
throw new RemoteException(RemoteMsgUtils.METHOD_ERROR_TYPE,
e.getLocalizedMessage());
}
if (m == null) {
throw new RemoteException(RemoteMsgUtils.METHOD_ERROR_TYPE);
}
Object result;
try {
result = m.invoke(serviceObj, params);
} catch (Exception e) {
e.printStackTrace();
log.error(RemoteReceivedServiceImpl.class, e);
// e是invoke的时候抛出来的.应该找它封装的
String errorMsg = "";
try {
errorMsg = getErrorMsg(e);
} catch (Exception e1) {
// 说明没有这个属性,就不用了
}
RemoteException remoteException = null;
if (StringUtils.isNotBlank(errorMsg)) {
remoteException = new RemoteException(errorMsg);
remoteException.setErrorMsg(errorMsg);
} else {
remoteException = new RemoteException(
RemoteMsgUtils.INVOKE_ERROR_TYPE);
}
if (StringUtils.isNotBlank(errorMsg)) {
}
throw remoteException;
}
return result;
}
这里我是通过reflect获取参数类型,然后传入执行方法,但是问题来了,如果传入的是一个引用类型例如User,ArrayList...我获取到的参数类型就不是method的了,因为method作为公用方法,那么入参肯定是Object,List这些了,先前的想法是客户端传入需要转换的class,但是正常Object可以了,但是List这种复杂对象就不ok了,所幸,class里面有个方法:Class.isAssignableForm(Class clz),可以匹配它的超类或借口。
重写invokeMethod方法:
/**
* 重写invokeMethod
*/
@SuppressWarnings("rawtypes")
private Object newInvokeMethod(String beanName, String methodName,
Object[] params, Class... type) {
Object serviceObj = null;
try {
serviceObj = this.context.getBean(beanName);
} catch (NoSuchBeanDefinitionException e) {
throw new RemoteException(RemoteMsgUtils.BEAN_ERROR_TYPE);
}
if (serviceObj == null) {
throw new RemoteException(RemoteMsgUtils.BEAN_ERROR_TYPE);
}
Method m = null;
Method[] ms=serviceObj.getClass().getMethods();
for(Method method:ms){
String mName=method.getName();
if(StringUtils.equals(methodName, mName)){
boolean isThis = true;
Class<?>[] pt=method.getParameterTypes();
if(type.length==pt.length){
int plength = type.length;
if (plength == 0) {
isThis = true;
} else {
for (int i = 0; i < plength; i++) {
boolean ff = pt[i]
.isAssignableFrom(type[i]);
if (!ff) {
isThis = false;
break;
}
}
}
}else {
isThis=false;
}
if (isThis) {
m=method ;
break;
}
}
}
if (m == null) {
throw new RemoteException(RemoteMsgUtils.METHOD_ERROR_TYPE);
}
Object result;
try {
result = m.invoke(serviceObj, params);
} catch (Exception e) {
e.printStackTrace();
log.error(RemoteReceivedServiceImpl.class, e);
// e是invoke的时候抛出来的.应该找它封装的
String errorMsg = "";
try {
errorMsg = getErrorMsg(e);
} catch (Exception e1) {
// 说明没有这个属性,就不用了
}
RemoteException remoteException = null;
if (StringUtils.isNotBlank(errorMsg)) {
remoteException = new RemoteException(errorMsg);
remoteException.setErrorMsg(errorMsg);
} else {
remoteException = new RemoteException(
RemoteMsgUtils.INVOKE_ERROR_TYPE);
}
if (StringUtils.isNotBlank(errorMsg)) {
}
throw remoteException;
}
return result;
}
ok!问题解决。