【java框架系列】spring boot将rpc服务的业务逻辑暴露成http服务

本文参考资料

https://juejin.im/post/5908a811da2f60005d188aee

定义数据模型

请求协议

请求url:http://url/接口/方法
请求参数:param:{json串}

服务端对请求的封装

public class HttpRequest {
private String param;
private String service;
private String method;
set/get方法
}

服务端的通用应答

public class HttpResponse implements Serializable {
private boolean success;
private String code;
private String description;
set/get方法
}

具体实现

application.yml配置

conf:
package: com.jxdw.dubbo.service
```
## 配置类

@Component
public class HttpProviderConf {

@Value("${conf.package}")
private String usePackageString;
private  List<String> userPackage;

public List<String> getUserPackage() {
    return userPackage;
}

public void setUserPackage(List<String> userPackage) {
    this.userPackage =Arrays.asList(StringUtils.split(usePackageString,","));
}

}


## 业务类

import com.alibaba.fastjson.JSON;
import com.jxdw.config.HttpProviderConf;
import com.jxdw.config.HttpRequest;
import com.jxdw.config.HttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping(“/ThriftAPI”)
public class ThriftServiceController implements ApplicationContextAware {

private final static Logger logger= LoggerFactory.getLogger(ThriftServiceController.class);

private ApplicationContext applicationContext;

@Autowired
private HttpProviderConf httpProviderConf;
private final Map<String, Class<?>> cacheMap = new HashMap<String, Class<?>>();

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext=applicationContext;
}

@ResponseBody
@RequestMapping(value = "/{service}/{method}",method = RequestMethod.POST)
public String api(HttpServletRequest httpServletRequest, HttpRequest httpRequest,
                  @PathVariable String service, @PathVariable String method){
    logger.info("ip-{},http-request {}",getIp(httpServletRequest), JSON.toJSONString(httpRequest));
    String invoke= invoke(httpRequest,service,method);
    logger.info("callback {}",invoke);
    return invoke;
}

private String invoke(HttpRequest httpRequest, String service, String method)  {
    httpRequest.setMethod(method);
    httpRequest.setService(service);
    HttpResponse httpResponse=new HttpResponse();
    if (!CollectionUtils.isEmpty(httpProviderConf.getUserPackage())){
        boolean isPac=false;
        for(String pac:httpProviderConf.getUserPackage()){
            if(service.startsWith(pac)){
                isPac=true;
                break;
            }
        }
        if (!isPac){
            logger.error("service is not  correct service is {}",service);
            httpResponse.setCode("2");
            httpResponse.setSuccess(false);
            httpResponse.setDescription("service is not conrect");
        }
    }
    Class<?> serviceClass=cacheMap.get(service);
    if (serviceClass==null){
        try {
            serviceClass=Class.forName(service);
            cacheMap.put(service,serviceClass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    if (method == null){
        logger.error("method is not correct,method="+method);
        httpResponse.setCode("2");
        httpResponse.setSuccess(false);
        httpResponse.setDescription("method is not correct,method="+method);
    }
    Method[] methodArray=serviceClass.getMethods();
    Method targetMethod=null;
    Boolean isMethod=false;
    for (Method method1:methodArray){
        if (method1.getName().equals(method)){
            targetMethod=method1;
            isMethod=true;
            break;
        }
    }
    if (!isMethod){
        logger.error("method is not correct,method="+method);
        httpResponse.setCode("3");
        httpResponse.setSuccess(false);
        httpResponse.setDescription("method is not correct,method="+method);
        return JSON.toJSONString(httpResponse);
    }
    Object  bean=this.applicationContext.getBean(serviceClass);
    Object result=null;
    if (targetMethod!=null){
        Class<?>[] parameterTypes=targetMethod.getParameterTypes();
        try{
            if (parameterTypes.length==0){
                result=targetMethod.invoke(bean);
                return JSON.toJSONString(result);
            }else if(parameterTypes.length==1){
                Object json=JSON.parseObject(httpRequest.getParam(),parameterTypes[0]);
                result=targetMethod.invoke(bean,json);
                return JSON.toJSONString(result);
            }else {
                logger.error("can only have one parameter");
                httpResponse.setCode("2");
                httpResponse.setSuccess(false);
                httpResponse.setDescription("can only have one parameter");
            }
        }
        catch (InvocationTargetException inException){
            logger.error("{}",inException);
        }catch(IllegalAccessException illException){
            logger.error("{}",illException);
        }
        return JSON.toJSONString(httpResponse);
    }
    return null;
}

private Object getIp(HttpServletRequest httpServletRequest) {
    if (httpServletRequest == null)
        return null;
    String s = httpServletRequest.getHeader("X-Forwarded-For");
    if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {
        s = httpServletRequest.getHeader("Proxy-Client-IP");
    }
    if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {
        s = httpServletRequest.getHeader("WL-Proxy-Client-IP");
    }
    if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {
        s = httpServletRequest.getHeader("HTTP_CLIENT_IP");
    }
    if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {
        s = httpServletRequest.getHeader("HTTP_X_FORWARDED_FOR");
    }
    if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {
        s = httpServletRequest.getRemoteAddr();
    }
    if ("127.0.0.1".equals(s) || "0:0:0:0:0:0:0:1".equals(s))
        try {
            s = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException unknownhostexception) {
            return "";
        }
    return s;
}

}