`

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服务器

    服务器端通过创建ServerSocket实例来监听指定端口,当客户端请求到达时,ServerSocket会创建一个Socket实例,代表了与客户端的连接。 其次,HTTP协议的理解至关重要。HTTP是超文本传输协议,用于从Web服务器向...

    java反射之模拟struts中央控制器

    Java反射是Java编程语言中的一个强大...通过这样的模拟,我们可以更好地理解和应用Java反射机制,同时也能深入理解Struts框架的核心工作流程。这对于开发自己的MVC框架或者在没有框架的情况下实现类似功能非常有帮助。

    用Java反射机制简化Struts框架逻辑控制.pdf

    综上所述,通过将Java反射机制和XML技术融入Struts框架,潘彬斌和王成良提出的改进框架模型有效地简化了逻辑控制,提升了软件架构的可组装性和开发效率。这种创新性思路为基于J2EE平台的应用开发提供了一种新的视角...

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

    这样的实践项目对于理解Struts的工作原理和Java反射的应用非常有帮助,同时也可以锻炼开发者在没有现成框架支持的情况下解决问题的能力。通过自制Struts,你可以深入理解MVC模式以及Java动态调用的机制,这对于提升...

    java_JAVA_WEB基本教程

    学习Java Web开发,需要理解HTTP协议、会话管理、请求转发与重定向等概念。 #### 十一、Java数据库连接(JDBC) JDBC是Java访问数据库的标准API,通过JDBC,Java程序可以与各种关系型数据库交互,执行SQL查询,处理...

    java_proxy_end

    这个代理服务可能被设计为一个灵活且安全的解决方案,允许开发者通过Java代码来控制网络通信,比如转发请求,进行数据过滤或者添加额外的安全层。以下是关于Java中实现代理服务的一些关键知识点: 1. **Java Proxy ...

    java编程深入研究

    理解Servlet生命周期,包括初始化、服务、销毁三个阶段,以及Servlet的多线程处理和请求转发与重定向,是服务器端开发的基础。JSP则是一种动态网页技术,它将HTML代码与Java代码结合,简化了视图层的开发。 深入...

    java编程百例

    12. **反射机制**:Java反射允许运行时动态地获取类的信息并调用其方法,是许多高级功能(如插件系统、序列化、动态代理)的基础。 13. **泛型**:泛型引入了类型参数,增强了代码的类型安全性和复用性,实例会展示...

    史上最强的java面试题 corejava javaWeb SSH框架

    Struts作为MVC框架,负责处理用户请求和转发到相应的业务逻辑。Spring框架提供依赖注入和面向切面编程,简化了对象的管理和事务控制。Hibernate是ORM(对象关系映射)框架,使得Java对象可以直接操作数据库,降低了...

    nginx反射例子,亲测可用!

    关于标签中的"weblogic",WebLogic是Oracle公司的一款Java EE应用服务器,通常与Nginx配合使用,Nginx作为反向代理,将来自互联网的请求转发到WebLogic服务器处理,提高系统性能和安全性。在企业环境中,这种架构很...

    java练习之模拟SPRING IOC,我的SUMMER

    例如,我们可以通过反射机制创建Bean的实例,并根据XML中的`&lt;property&gt;`标签注入依赖。这样,当需要使用Bean时,只需从容器中获取即可,无需关心其内部构造。 **3. 模拟Struts** Struts是一个基于MVC(Model-View-...

    JAVA教程 安卓教程

    你将学习到JSP基本语法、EL表达式、JSTL标签库、自定义标签、会话管理、请求转发与包含等,以及如何与数据库进行交互,打造功能丰富的Web应用。 最后,HTML、CSS和JavaScript是构建现代网页的三大基础。徐彤教程-...

    java手写SpringMvc框架

    我们需要重写doDispatch方法,这里会涉及到请求的拦截、匹配、转发等操作。同时,需要设计一个简单的注解系统,如@Controller、@RequestMapping等,用于标记Controller类和处理方法。 接下来是包扫描过程。在Spring...

    java技术笔试题

    4. **Java反射**:反射允许运行时动态访问类的信息,如构造函数、方法、字段,以及调用私有成员,增强程序的灵活性和可扩展性。 5. **AJAX与传统WEB应用**:AJAX(异步JavaScript和XML)实现了局部刷新,提高了用户...

    java代理源码

    描述中的“web代理程序”可能是指一个HTTP代理服务器,它能接收客户端的HTTP请求,并转发到目标服务器,同时可能对请求或响应进行处理,如缓存、过滤、身份验证等。在Java中,可以使用Java的Socket编程或者HTTP协议...

    2018JAVA最新框架面试题

    IOC 通过反射机制生成对象注入,AOP 通过动态代理实现。 SpringMvc 1. SpringMvc 的控制器是不是单例模式 如果是,有什么问题,怎么解决? SpringMvc 的控制器可以是单例模式,但这将导致线程安全问题,可以通过...

    java面试重点总结

    **反射机制**是Java中一项非常重要的技术,它允许程序在运行时动态地获取类的信息并直接操作这些信息。这对于框架开发和扩展性要求高的系统非常重要。 - **应用场景**: - 动态创建对象。 - 获取类的所有属性和...

    java-Reflection:java 反射与工厂模式

    静态代理是代理模式的一种,它在目标对象和客户端之间创建一个代理对象,代理对象处理客户端的请求并转发给目标对象。静态代理的实现需要为每个目标类创建一个对应的代理类,这可能导致代码量的增加。然而,它提供了...

    自己模拟实现struts的dispatcherAction

    这个过程不仅加深了对Struts工作原理的理解,也锻炼了Java反射和XML解析的能力。不过,实际开发中,使用成熟的Struts框架能提供更多的便利和优化,如AOP(面向切面编程)支持、更丰富的插件等。

    Java精华(bbs.nju.edu.cn)(南大小百合Java版精华)

    理解请求响应模型、会话管理、转发与重定向,以及MVC设计模式,能够帮助开发者构建强大的Web应用程序。 Spring框架是Java企业级应用开发的主流选择,其依赖注入(DI)和面向切面编程(AOP)理念,极大地简化了复杂...

Global site tag (gtag.js) - Google Analytics