`

java 通过反射转发请求

 
阅读更多

     在某些场景下,我们需要早service成拦截下服务请求,然后转发到相应的服务下;

     要实现这样的场景我们首先需要拦截下service层的请求,然后在获取相应的请求参数,转发下去;

     以下例子是将服务通过dubbo发布成webService然后调用;

     可以通过有storm测试;

     

     参考代码如下:

         1、简单实现版本,该版本只支持基础类型

package com.xmm.webserver.service.impl;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.xmm.module.utils.SpdEsbQueryParam;
import com.xmm.web.share.interfaces.SpdEsbForwardService;
import com.xmm.webserver.base.GenericService;
import com.xmm.webserver.util.SpringUtil;

@Service("spdEsbForwardService")
public class SpdEsbForwardServiceImpl extends GenericService implements SpdEsbForwardService {
    Logger logger = LoggerFactory.getLogger(this.getClass());
    
    /**
     * 转发方法
     * @param params 封装好的请求数据(json格式)
     * **********属性说明:
     * *************targetName          请求类全路径
     * *************methodName          请求方法
     * *************queryParamsList     请求参数
     * *************returnType          返回类型全路径
     */
    @SuppressWarnings({ "rawtypes", "unchecked", "unused" })
    public Object spdEsbForward(String params) {
        try {
            Map<String, String> paramMap = JSON.parseObject(params, new TypeReference<Map<String, String>>() {}); 
            //获取调用类全路径
            String targetName = paramMap.get("targetName");
            //获取调用方法名
            String methodName = paramMap.get("methodName");
            //获取返回数据类型
            String returnType = paramMap.get("returnType");
            //获取查询请求参数
            String queryParams = paramMap.get("queryParamsList");   
            //将请求类型转换为list
            List<SpdEsbQueryParam> list = JSON.parseObject(queryParams, new TypeReference<List<SpdEsbQueryParam>>() {});
            
            // 调用方法的请求数据类型集合
            Class classNum[] = new Class[list.size()]; 
            // 调用方法的请求数据值集合
            Object objectNum[] = new Object[list.size()]; 
            int i = 0;
            for (SpdEsbQueryParam spdEsbQueryParam : list) {
                //获取请求数据类型
                Class paramCalss = Class.forName(spdEsbQueryParam.getPueryParamType());
                //获取请求数据值
                String paramValue=spdEsbQueryParam.getPueryParamValue().toString();
                
                classNum[i] = paramCalss;
                objectNum[i] = JSON.parseObject(paramValue, paramCalss);
                i++;
            }
            
            // 实例化调用类
            Object obj = SpringUtil.getBean(Class.forName(targetName));
            // 装载方法
            Method method = obj.getClass().getMethod(methodName, classNum);
            // 调用方法
            Object object =  method.invoke(obj, objectNum);
            return object;
        } catch (Exception e) {
            logger.error("",e);
        }
        return null;
    }
}

 

     请求参数:

{
    "methodName": "queryRouteInfoList",//请求方法
    "targetName": "com.xmm.web.share.interfaces.RouteInfoService",//请求完整路劲
    "queryParamsList": [  //查询参数集合
        {
            "pueryParamValue": {  // 查询参数值
                "flag": true,
                "pageSize": 20,
                "pageNum": 1,
                "routeName": "路由"
            },
            "pueryParamName": "query", //参数名称
            "pueryParamType": "com.xmm.web.share.query.RouteInfoQuery" //查询参数类型
        }
    ],
    "returnType": "com.xmm.module.commons.SingleResult<RouteInfoDTO>"  // 返回只类型
}

 

        2、复杂类型,该类型支持枚举、集合、类中包含集合.....数据类型,其他有没有不支持的有带验证

package com.xmm.webserver.service.impl;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.xmm.module.utils.SpdEsbQueryParam;
import com.xmm.web.share.interfaces.SpdEsbForwardService;
import com.xmm.webserver.base.GenericService;
import com.xmm.webserver.util.SpringUtil;

@Service("spdEsbForwardService")
public class SpdEsbForwardServiceImpl extends GenericService implements SpdEsbForwardService {
    Logger logger = LoggerFactory.getLogger(this.getClass());
    
    /**
     * 转发方法
     * @param params 封装好的请求数据(json格式)
     * **********属性说明:
     * *************targetName          请求类全路径
     * *************methodName          请求方法
     * *************queryParamsList     请求参数
     * *************returnType          返回类型全路径
     */
    @SuppressWarnings({ "rawtypes", "unused", "unchecked" })
    public String spdEsbForward(String params) {
        try {
            Map<String, String> paramMap = JSON.parseObject(params, new TypeReference<Map<String, String>>() {}); 
            //获取调用类全路径
            String targetName = paramMap.get("targetName");
            //获取调用方法名
            String methodName = paramMap.get("methodName");
            //获取返回数据类型
            String returnType = paramMap.get("returnType");
            //获取查询请求参数
            String queryParams = paramMap.get("queryParamsList");   
            //将请求类型转换为list
            List<SpdEsbQueryParam> list = JSON.parseObject(queryParams, new TypeReference<List<SpdEsbQueryParam>>() {});
            
            int length = list.size();
            // 调用方法的请求数据类型集合
            Class classNum[] = new Class[length]; 
            // 调用方法的请求数据值
            String classValue[] = new String[length];
            // 调用方法的请求数据值集合
            Object objectNum[] = new Object[length]; 
            
            for (int i=0; i < length; i++) {
                SpdEsbQueryParam spdEsbQueryParam = list.get(i);
                //获取请求数据类型
                classNum[i] = Class.forName(spdEsbQueryParam.getPueryParamType());
                //获取请求数据值
                classValue[i] = spdEsbQueryParam.getPueryParamValue().toString();
            }
            
            // 实例化调用类
            Object obj = SpringUtil.getBean(Class.forName(targetName));
            // 装载方法
            Method method = Class.forName(targetName).getMethod(methodName,classNum);
            // 获取参数,可能是多个,所以是数组
            Type[] types = method.getGenericParameterTypes();   
            for (int i=0; i < length; i++) {
                Type queryType = types[i];
                
                // 判断此类型是否是Type对象的数组
                if (!(queryType instanceof ParameterizedType)){
                    //获取对象
                    Class paramCalss = Class.forName(queryType.getTypeName());
                    //判断对象是否是枚举
                    if(paramCalss.isEnum()){
                        objectNum[i] = tresolveEnumValue(classValue[i], paramCalss); 
                    }else{
                        objectNum[i] = JSON.parseObject(classValue[i],queryType);
                    }
                } else {
                    objectNum[i] = JSON.parseObject(classValue[i],queryType);
                }
            }
            
            // 调用方法
            Object object =  method.invoke(obj, objectNum);
            return JSON.toJSONString(object);
        } catch (Exception e) {
            logger.error("",e);
        }
        return null;
    }
    
    private <T> T tresolveEnumValue(String value, Class<T> type) {  
        for (T constant : type.getEnumConstants()){  
            if (constant.toString().equalsIgnoreCase(value)) {  
                return constant;  
            }  
        }     
        return null;  
    }
}

   

    请求参数1-带集合:

{
    "methodName": "enumberOut",
    "targetName": "com.xmm.web.share.interfaces.EnumberService",
    "queryParamsList": [
        {
            "pueryParamValue": {
                "modifyBy": "admin",
                "batchNo": "120598",
                "notOutQuantity": 96,
                "outQuantity": 4
            },
            "pueryParamName": "enumber",
            "pueryParamType": "com.xmm.web.share.dto.EnumberDto"
        },
        {
            "pueryParamValue": [
                {
                    "eCode": "201705160006162"
                },
                {
                    "eCode": "20170000006163"
                },
                {
                    "eCode": "2017000006164"
                },
                {
                    "eCode": "2017516006165"
                }
            ],
            "pueryParamName": "enumberListDetail",
            "pueryParamType": "java.util.List"
        },
        {
            "pueryParamValue": {
                "agent": true,
                "userName": "admin",
                "accountId": "4607"
            },
            "pueryParamName": "user",
            "pueryParamType": "com.xmm.web.share.dto.UserDTO"
        },
        {
            "pueryParamValue": {
                "batchNo": "120598",
                "flag": true,
                "outQuantity": 4,
                "pageSize": 20,
                "remark": "你妹",
                "pageNum": 1
            },
            "pueryParamName": "query",
            "pueryParamType": "com.xmm.web.share.query.EnumberQuery"
        }
    ],
    "returnType": "com.xmm.module.commons.Result"
}

    请求参数2-带枚举:

{
    "methodName": "createNewAccount",
    "targetName": "com.xmm.share.interfaces.AccountManagerService",
    "queryParamsList": [
        {
            "pueryParamValue": "11010512",
            "pueryParamName": "agentId",
            "pueryParamType": "java.lang.Integer"
        },
        {
            "pueryParamValue": "AGENT",
            "pueryParamName": "AGENT",
            "pueryParamType": "com.xmm.module.enums.ACCOUNT_TYPE"
        }
    ],
    "returnType": "com.xmm.share.dto.AccountDto"
}

 

 

分享到:
评论

相关推荐

    Java实现的Http服务器

    基于Http协议,java语言实现的Http服务器和客户端,其中包含了反射,以及对XML文件的详细解析步骤,能够基本实现Http的请求与响应,包括其中的解析

    利用反射 实现一个自制的struts

    此资源是通过java反射,实现了struts的拦截器和转发请求的功能,实现简单,易懂。

    JAVA面试题最全集

    9.Jsp和Servlet中的请求转发分别如何实现。 三、J2EE相关知识 1.介绍J2EE、J2SE、J2SE的区别。 2.J2EE是一种技术还是一种平台,他提供了那些技术。 3.什么是Application Server,它有什么功能和优点。 4.简单...

    Java面试宝典2020修订版V1.0.1.doc

    41、什么是java反射机制? 84 42、hashmap的底层实现 85 43、什么是java内存泄漏,怎么预防? 85 七、框架部分 85 1、谈谈你对Struts2的理解。 85 2、谈谈你对Hibernate的理解。 86 3、你对Spring的理解。 87 4、...

    Java典型模块

    27.2.3 浏览器所请求的页面 27.3 知识点扩展——HTTP协议知识 27.3.1 HTTP协议原理 27.3.2 实现HTTP协议服务器的原理 27.4 小结 28.1 QQ聊天工具原理 28.1.1 项目结构框架分析 28.1.2 项目功能业务分析 28.2 QQ项目...

    student-score:基于jsp+servlet技术的简单选课小项目

    java基础;​简单注解和反射​mysql基础;​xml;javaweb:EL表达式,EL函数,jsp技术,servlet;​mvc模式​ 数据库持久层用到:org.apache.commons.dbutils封装数据库数据到对象。连接池使用了c3p0。参数可以在c3p...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【反射】反射中,Class.forName和classloader的区别 42 【JVM】JAVA编译原理和JVM原理 42 【JVM】Java内存模型 44 【JVM】jvm内存模型 45 主内存与工作内存 45 内存间交互操作 46 重排序 48 【JVM】内存泄漏 49 ...

    Java基础练习-使用基础知识编写一个服务器

    构建一个实现简单功能的服务器知识基础实现功能实现思路项目结构图效果展示用默认端口、默认错误页面、默认欢迎页面、无Servlet的服务使用配置...获取测试简单登录功能测试参数获取、根据请求方式的转发功能代码获取...

    AisMVC.zip

    * String返回类型方法转发请求 * @ResponseBody注解实现ajax接口 * 增加config.ini配置文件,实现定向动态扫描项目中的@Controller 类 * 增加注解参数RequestMethod 默认http请求类型,请求类型不合法返回405状态码 #...

    Java学习笔记-个人整理的

    {10}反射}{141}{chapter.10} {10.1}Class}{141}{section.10.1} {10.1.1}Field}{145}{subsection.10.1.1} {10.1.2}Method}{145}{subsection.10.1.2} {10.1.3}Constructor}{145}{subsection.10.1.3} {10.2}其他...

    simple-framework:基于Servlet的轻量级JavaWeb框架的实现

    Email:简介​Simple-Framework是基于原生Servlet实现的一种轻量级Java Web框架,它具有目前市面上流行的Java Web框架(如Spring、SpringMVC)所具备的核心功能:Bean容器,依赖注入,请求转发控制器,IOC和AOP功能,...

    Spring面试题

    3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。 4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。 2. ...

    Web安全深度剖析(张柄帅)

    《Web安全深度剖析》总结了当前流行的高危漏洞的形成原因、攻击手段及解决方案,并通过大量的示例代码复现漏洞原型,制作模拟环境,更好地帮助读者深入了解Web应用程序中存在的漏洞,防患于未然。 《Web安全深度剖析...

    asp.net知识库

    通过反射调用類的方法,屬性,字段,索引器(2種方法) ASP.NET: State Server Gems 完整的动态加载/卸载程序集的解决方案 从NUnit中理解.NET自定义属性的应用(转载) 如何在.NET中实现脚本引擎 (CodeDom篇) .NET的插件...

Global site tag (gtag.js) - Google Analytics