Arquitecto, diario, escritura a mano, llamada de módulo remoto mediante protocolo HTTP

Los protocolos más populares para llamadas de módulos remotos son el protocolo RPC, el protocolo RMI y el protocolo HTTP.
Este blog le enseña cómo usar el protocolo HTTP para probar las llamadas de módulos remotos.

1. Definir la estructura

La arquitectura general sigue
Escriba la descripción de la imagen aquí
la siguiente una a una, explico su papel

2.Modelo de módulo

La función de esta clase es registrar la información de los módulos correspondientes a diferentes uuids, incluyendo ip y url remotas, etc. El código es el siguiente

/**
 * 调用远端方法的协议类
 */
public class InteractiveModel {
    
    
    /**
     * 操作类型
     */
    private String opeType;
    /**
     * 操作参数
     */
    private Map<String,Object>map=new HashMap<String ,Object>();

    public InteractiveModel(String opeType, Map<String, Object> map) {
        this.opeType = opeType;
        this.map = map;
    }

    public InteractiveModel() {
    }

    public String getOpeType() {
        return opeType;
    }

    public void setOpeType(String opeType) {
        this.opeType = opeType;
    }

    public Map<String, Object> getMap() {
        return map;
    }

    public void setMap(Map<String, Object> map) {
        this.map = map;
    }
}

3.Modelo interactivo

Se puede decir que esta clase es una clase de protocolo para llamar a métodos. Contiene tipos de operación y parámetros de operación. El código es el siguiente

/**
 * 调用远端方法的协议类
 */
public class InteractiveModel {
    
    
    /**
     * 操作类型
     */
    private String opeType;
    /**
     * 操作参数
     */
    private Map<String,Object>map=new HashMap<String ,Object>();

    public InteractiveModel(String opeType, Map<String, Object> map) {
        this.opeType = opeType;
        this.map = map;
    }

    public InteractiveModel() {
    }

    public String getOpeType() {
        return opeType;
    }

    public void setOpeType(String opeType) {
        this.opeType = opeType;
    }

    public Map<String, Object> getMap() {
        return map;
    }

    public void setMap(Map<String, Object> map) {
        this.map = map;
    }
}

4.InteractiveCallHelper

InteractiveCallHelper es el iniciador de llamadas a métodos remotos. Esta clase puede ser independiente de este proyecto. Por conveniencia, no la extraeré por separado. Puede devolver una cadena o un objeto de un tipo específico. El principal efecto de esta clase son los siguientes:
1. Un método para obtener la URL del extremo distal según diferentes UUID
2. Conversión de parámetros implementada caracteres ilegales
3. La composición y los
códigos de los parámetros de la URL de la siguiente manera

/**
 * 调用远端方法的发起者
 */
public class InteractiveCallHelper {
    
    
    /**
     *
     * @param moduleId 模块Id
     * @param opeType 需要调用的具体的业务操作类型
     * @param mapParams 调用所需要传递的参数
     * @return 服务端返回的Json数据
     */
    public String call(String moduleId, String opeType, Map<String,Object>mapParams){
        //1.根据moduleId去获取到该模块部署的信息,理论上要根据moduleId去设置,这里写死
        ModuleModel moduleModel=new ModuleModel();
        moduleModel.setDeployIP("localhost");
        moduleModel.setDeployPort("8080");
        moduleModel.setIntereractiveUrl("/goods/call");

        //2.准备要传递的数据,把Map转换为JSON
        String paramStr= JSON.toJSONString(mapParams);
        //因为#在url里有特殊含义,所以将#替换为*
        paramStr=paramStr.replace("#","*");

        //3.拼接一个远程调用的URL
        String urlStr="http://"+ moduleModel.getDeployIP()+":"+moduleModel.getDeployPort()+moduleModel.getIntereractiveUrl()
                +"?jsonParam={opeType:"+opeType+",map:"+paramStr+"}";

        //4.使用URL进行远程调用,流式操作
        BufferedReader in =null;
        String retJson="";
        try {
            URL url=new URL(urlStr);
            URLConnection urlConnection=url.openConnection();
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    urlConnection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                retJson += line;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return retJson;
    }

    /**
     *
     * @param moduleId 模块Id
     * @param opeType 需要调用的具体的业务操作类型
     * @param mapParams 调用所需要传递的参数
     * @param cls 需要转的类型
     * @return  服务器返回的对象
     */
    public <T>T call(String moduleId, String opeType, Map<String,Object>mapParams,Class<T> cls){
        String json=call(moduleId,opeType,mapParams);
        return JSON.parseObject(json,cls);
    }

    /**
     * 测试方法
     * @param args
     */
    public static void main(String[]args){
        InteractiveCallHelper interactiveCallHelper=new InteractiveCallHelper();
        Map<String,Object>map=new HashMap<String,Object>();
        String str=interactiveCallHelper.call("goods","1",map);
        System.out.println(str);
    }
}

5.InteractiveBaseController

Esta clase es la clase base del método llamado remoto. Esta clase es una clase abstracta. Cualquier controlador remoto que pueda ser llamado debe heredarlo, heredar el método de llamada e implementar su método doCall. El código es el siguiente

/**
 * 远端被调用方法的基类
 */
public abstract class InteractiveBaseController {
    
    
    /**
     * 解析参数
     * @param jsonParam
     * @return
     */
    @RequestMapping("/call")
    @ResponseBody
    public Object call(String jsonParam){
        if (jsonParam!=null&&jsonParam.contains("*")){
            //将*变回#
            jsonParam=jsonParam.replace("*","#");
        }
        InteractiveModel interactiveModel= JSON.parseObject(jsonParam,InteractiveModel.class);
        Object ret=doCall(interactiveModel.getOpeType(),interactiveModel.getMap());
        return ret;
    }
    protected  abstract Object doCall(String opetype, Map<String,Object>map);
}

6.Modelo de productos

Esta clase es JavaBean, y la clase de entidad correspondiente a la base de datos se puede reemplazar libremente, el código es el siguiente

/**
 * 要操作的实体类
 */
public class GoodsModel {
    
    
    private String uuid;
    private String name;

    public GoodsModel(String uuid, String name) {
        this.uuid = uuid;
        this.name = name;
    }

    public GoodsModel() {
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "GoodsModel{" +
                "uuid='" + uuid + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

7.Controlador de productos

Ejemplos de métodos remotos, realizar diferentes operaciones según diferentes tipos de operaciones, como insertar una entidad en la base de datos cuando el tipo de operación es 1, el código es el siguiente

@RestController
@RequestMapping(value = "goods")
public class GoodsController extends InteractiveBaseController{
    
    

    @Override
    protected Object doCall(String opetype, Map<String, Object> map) {
        //执行不同的操作
        if ("1".equals(opetype)){

        }else if ("2".equals(opetype)){

        }
        GoodsModel goodsModel=new GoodsModel();
        goodsModel.setName("abc");
        goodsModel.setUuid("132132");
        System.out.println("call");
        return goodsModel;
    }
}

Se escribe una demostración que usa el módulo de llamada remota HTTP, pero el protocolo HTTP es ineficiente, por lo que en el desarrollo diario, a menudo usamos el protocolo RPC para implementar el módulo de llamada remota, como el famoso marco Dubbo

El código completo se ha subido a github: https://github.com/jkgeekJack/UseRemoteInvoker

Supongo que te gusta

Origin blog.csdn.net/qq_32198277/article/details/77523210
Recomendado
Clasificación