Design of Java motan gateway

@TOC Insert code slice here
Recently joined a company that built it from scratch. The rpc framework is motan. The reason why motan is used is mainly because the company is divided into two teams: java and php. motan can realize cross language call and is relatively lightweight, so motan is selected.

Since rpc is used for communication between backend projects, there is no mvc layer. The docking front end needs to provide an http interface to the front end, so a motan gateway is needed to complete the task of docking the front end.

Realization idea

Read the information
https://github.com/weibocom/motan/issues/581
There are two ways to implement motan gateway

Use motango-1 gateway development.
2. Modify motan source code for custom forwarding.

Because I am not familiar with go language, the workload of modifying motan source code is relatively large. Therefore, a more compromise approach is selected here. Using spring boot to develop motan gateway, a layer of forwarding logic is wrapped on the basis of the original motan to realize the dynamic forwarding of motan interface.
The basic idea is as follows

Between the gateway and the service, a public motan interface method is used to call, and then the public run method forwards according to the agreed rules to call the actual method.
The advantage of doing this is that I don't need to care about the interface changes of the service provider. I just need to call it directly according to the agreed given parameters. There is no need to restart the service frequently like ordinary motan rpc service calls.

1. Calling method Convention

The public method for the service provider to listen is
String run(String param) throws Exception;
The parameter is String, the return value is String, and the method name is run,

2. Calling format Convention

The calling parameter is a json string, which must contain two parameters: the method to be called by redirectMethod and the class of the method to be called by redirectClazz
These two methods are mainly used to reflect and call specific methods when calling dynamically

code implementation

With the above ideas, let's implement the specific code.

Method MotanRedirectUtil

This class is the core, which specifies the parameter call, the requestor call method, and the corresponding party call method

package com.happotech.motan.core.util;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * motan Gateway forwarding util
 * @author songxulin
 * @date 2021/4/14
 */
@Component
public class MotanRedirectUtil implements ApplicationContextAware {
	//spring context 
    private static ApplicationContext applicationContext;

    public static Object getMotanBean(Class clazz){
        return applicationContext.getBean(clazz);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
	//Send request
    public static JSONObject requestRun(Object iActMotanService,String param,String ApiUrlPrefix,String redirectMethod) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        param = getParam(param,ApiUrlPrefix,redirectMethod);
        Method run = iActMotanService.getClass().getMethod("run", String.class);
        return JSONObject.parseObject(run.invoke(iActMotanService,param).toString());
    }
	//Corresponding request
    public static String responseRun(String param,Class clazz) throws Exception {
        JSONObject parseObject = JSONObject.parseObject(param);
        String redirectMethod = parseObject.getString("redirectMethod");
        String redirectClazz = parseObject.getString("redirectClazz");
        if(clazz.getName().equals(redirectClazz)&&"run".equals(redirectMethod)){
            throw new Exception("run Method does not allow redirection");
        }
        Class<?> aClass = Class.forName(redirectClazz);
        Object motanBean = MotanRedirectUtil.getMotanBean(aClass);
        Method method = aClass.getMethod(redirectMethod, String.class);
        Object invoke = method.invoke(motanBean, param);
        if(invoke instanceof String){
            return (String) invoke;
        }
        return JSONObject.toJSONString(invoke);
    }
	//Get parameters
    public static String getParam(String body,String ApiUrlPrefix,String redirectMethod){
        JSONObject param = JSONObject.parseObject(body);
        param.put("redirectMethod",redirectMethod);
        param.put("redirectClazz",ApiUrlPrefix.replaceAll("/",".").substring(1,ApiUrlPrefix.length()-1));
        return param.toJSONString();
    }
}

The above is the core code

Specific use

When using, the core code can be packaged into jar s and introduced to the server and gateway.

Gateway end use

Must contain a String run(String param) method.

/**
 * @author songxulin
 * @date 2021/4/14
 */
public interface IActMotanService {

    String run(String param) throws Exception;
}

realization

@MotanService
public class ActMotanServiceImpl implements IActMotanService {


    @Override
    public String run(String param) throws Exception {
        return MotanRedirectUtil.responseRun(param,IActMotanService.class);
    }
}

Gateway end use

@RestController
public class MotanController {
    @MotanReferer
    private IMotanService iMotanService;
    @Autowired
    private LoginUtil loginUtil;
    //ApiUrlPrefix is the full path of the interface class
    private static final String ApiUrlPrefix = "/com/happotech/actmgr/motan/service/api/IMgrService/";

    @RequestMapping(ApiUrlPrefix + "{method}")
    @ResponseBody
    public JSONObject urcService(@RequestBody String body, @PathVariable("method") String method, HttpServletRequest request)
            throws Exception {
        loginUtil.checkTicket(body);
        return MotanRedirectUtil.requestRun(iActMotanService, body, ApiUrlPrefix, method);
    }
}

In this way, the gateway of motan is realized. If a new project is added later, just add a new controller.

Keywords: Java framework gateway

Added by Xajel on Fri, 04 Mar 2022 17:12:54 +0200