SpringBoot 代理转发网关

RestTemplate

工具类:

import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;

/**
 * @author qhong
 * @date 2021/08/30 10:02
 **/
@Service
public class RoutingDelegate {

    public ResponseEntity<String> redirect(HttpServletRequest request, HttpServletResponse response,String routeUrl, String prefix) {
        try {
            // build up the redirect URL
            String redirectUrl = createRedictUrl(request,routeUrl, prefix);
            RequestEntity requestEntity = createRequestEntity(request, redirectUrl);
            return route(requestEntity);
        } catch (Exception e) {
            return new ResponseEntity("REDIRECT ERROR", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    private String createRedictUrl(HttpServletRequest request, String routeUrl, String prefix) {
        String queryString = request.getQueryString();
        return routeUrl + request.getRequestURI().replace(prefix, "") +
                (queryString != null ? "?" + queryString : "");
    }


    private RequestEntity createRequestEntity(HttpServletRequest request, String url) throws URISyntaxException, IOException {
        String method = request.getMethod();
        HttpMethod httpMethod = HttpMethod.resolve(method);
        MultiValueMap<String, String> headers = parseRequestHeader(request);
        byte[] body = parseRequestBody(request);
        return new RequestEntity<>(body, headers, httpMethod, new URI(url));
    }

    private ResponseEntity<String> route(RequestEntity requestEntity) {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.exchange(requestEntity, String.class);
    }


    private byte[] parseRequestBody(HttpServletRequest request) throws IOException {
        InputStream inputStream = request.getInputStream();
        return StreamUtils.copyToByteArray(inputStream);
    }

    private MultiValueMap<String, String> parseRequestHeader(HttpServletRequest request) {
        HttpHeaders headers = new HttpHeaders();
        List<String> headerNames = Collections.list(request.getHeaderNames());
        for (String headerName : headerNames) {
            List<String> headerValues = Collections.list(request.getHeaders(headerName));
            for (String headerValue : headerValues) {
                headers.add(headerName, headerValue);
            }
        }
        return headers;
    }
}

Spring集成:

@RestController
@RequestMapping(GraphDBController.DELEGATE_PREFIX)
@Api(value = "GraphDB", tags = {
        "graphdb-Api"
})
public class GraphDBController {

    @Autowired
    GraphProperties graphProperties;

    public final static String DELEGATE_PREFIX = "/graphdb";

    @Autowired
    private RoutingDelegate routingDelegate;

    @RequestMapping(value = "/**", method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE}, produces = MediaType.TEXT_PLAIN_VALUE)
    public ResponseEntity catchAll(HttpServletRequest request, HttpServletResponse response) {
        return routingDelegate.redirect(request, response, graphProperties.getGraphServer(), DELEGATE_PREFIX);
    }
}

OKHttp3

工具类:

import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StreamUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.*;

/**
 * Created by qhong on 2018/7/3 16:55
 **/
public class OkHttpUtil {

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

    /**
     * 调用okhttp的newCall方法
     *
     * @param request
     * @return
     */
    private static String execNewCall(Request request) {
        Response response = null;
        try {
            OkHttpClient okHttpClient = SpringUtils.getBean(OkHttpClient.class);
            response = okHttpClient.newCall(request).execute();
            int status = response.code();
            if (response.isSuccessful()) {
                return response.body().string();
            }
        } catch (Exception e) {
            logger.error("okhttp3 put error >> ex = {}", e);
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return "";
    }

    /**
     * 代理转发请求
     *
     * @param request
     * @return
     */
    public static String route(String routeUrl, String prefix, HttpServletRequest request) {
        try {
            String redirectUrl = createRedictUrl(request, routeUrl, prefix);
            Map<String, String> header = getOriginHeader(request);
            InputStream inputStream = request.getInputStream();
            String body = StreamUtils.copyToString(inputStream, Charset.defaultCharset());
            return postJsonParams(redirectUrl, header, body);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * get
     *
     * @param url     请求的url
     * @param queries 请求的参数,在浏览器?后面的数据,没有可以传null
     * @return
     */
    public static String get(String url, Map<String, String> queries) {
        StringBuffer sb = getQueryString(url, queries);
        Request request = new Request.Builder()
                .url(sb.toString())
                .build();
        return execNewCall(request);
    }

    /**
     * post
     *
     * @param url    请求的url
     * @param params post form 提交的参数
     * @return
     */
    public static String postFormParams(String url, Map<String, String> params) {
        return postFormParams(url, null, params);
    }

    /**
     * post  x-www-form-urlencoded
     *
     * @param url    请求的url
     * @param heads  head参数
     * @param params post form 提交的参数
     * @return
     */
    public static String postFormParams(String url, Map<String, String> heads, Map<String, String> params) {
        FormBody.Builder builder = new FormBody.Builder();
        //添加参数
        if (params != null && params.keySet().size() > 0) {
            for (String key : params.keySet()) {
                builder.add(key, params.get(key));
            }
        }
        Request request = new Request.Builder()
                .url(url)
                .post(builder.build())
                .headers(SetHeaders(heads))
                .build();

        return execNewCall(request);
    }

    /**
     * post  form-data
     *
     * @param url    请求的url
     * @param heads  head参数
     * @param params post form 提交的参数
     * @return
     */
    public static String postFormDataParams(String url, Map<String, String> heads,
                                            Map<String, String> params) {
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
        //添加参数
        if (params != null && params.keySet().size() > 0) {
            for (String key : params.keySet()) {
                builder.addFormDataPart(key, params.get(key));
            }
        }
        Request request = new Request.Builder()
                .url(url)
                .post(builder.build())
                .headers(SetHeaders(heads))
                .build();

        return execNewCall(request);
    }

    /**
     * Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"}
     * 参数一:请求Url
     * 参数二:请求的JSON
     * 参数三:请求回调
     */
    public static String postJsonParams(String url, String jsonParams) {
        return postJsonParams(url, null, jsonParams);
    }

    /**
     * Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"}
     * 参数一:请求Url
     * 参数二:请求的JSON
     * 参数三:请求回调
     */
    public static String postJsonParams(String url, Map<String, String> heads, String jsonParams) {
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .headers(SetHeaders(heads))
                .build();
        return execNewCall(request);
    }

    /**
     * Post请求发送xml数据....
     * 参数一:请求Url
     * 参数二:请求的xmlString
     * 参数三:请求回调
     */
    public static String postXmlParams(String url, String xml) {
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        return execNewCall(request);
    }


    //***************************************************内部方法******************************************//


    /**
     * 根据map获取get请求参数
     *
     * @param queries
     * @return
     */
    private static StringBuffer getQueryString(String url, Map<String, String> queries) {
        StringBuffer sb = new StringBuffer(url);
        if (queries != null && queries.keySet().size() > 0) {
            boolean firstFlag = true;
            Iterator iterator = queries.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry<String, String>) iterator.next();
                if (firstFlag) {
                    sb.append("?" + entry.getKey() + "=" + entry.getValue());
                    firstFlag = false;
                } else {
                    sb.append("&" + entry.getKey() + "=" + entry.getValue());
                }
            }
        }
        return sb;
    }

    /**
     * header参数
     *
     * @param headersParams
     * @return
     */
    private static Headers SetHeaders(Map<String, String> headersParams) {
        Headers headers = null;
        okhttp3.Headers.Builder headersbuilder = new okhttp3.Headers.Builder();
        if (headersParams != null && !headersParams.isEmpty()) {
            Iterator<String> iterator = headersParams.keySet().iterator();
            String key = "";
            while (iterator.hasNext()) {
                key = iterator.next().toString();
                headersbuilder.add(key, headersParams.get(key));
            }
        }
        headers = headersbuilder.build();
        return headers;
    }

    private static String createRedictUrl(HttpServletRequest request, String routeUrl, String prefix) {
        String queryString = request.getQueryString();
        return routeUrl + request.getRequestURI().replace(prefix, "") +
                (queryString != null ? "?" + queryString : "");
    }

    /**
     * 获取请求体的header参数
     *
     * @param request
     */
    private static Map<String, String> getOriginHeader(HttpServletRequest request) {
        Map<String, String> headers = new HashMap<>();
        List<String> headerNames = Collections.list(request.getHeaderNames());
        for (String headerName : headerNames) {
            List<String> headerValues = Collections.list(request.getHeaders(headerName));
            for (String headerValue : headerValues) {
                if (!headerName.equalsIgnoreCase("host")) {
                    headers.put(headerName, headerValue);
                }
            }
        }
        return headers;
    }

}

Spring集成

@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RequestMapping(NanoRoutingController.DELEGATE_PREFIX)
@Api(value = "nano代理")
public class NanoRoutingController {

    @Value("${rpc.nano.host:http://94343-test.net}")
    private String host;

    public static final String DELEGATE_PREFIX = "/nano";

    @RequestMapping(value = "/**", method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE},
            produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity catchAll(HttpServletRequest request) {
        String result = OkHttpUtil.route(host, DELEGATE_PREFIX, request);
        return ResponseEntity.ok(result);
    }
}

参考:

spring boot实现超轻量级网关(反向代理、转发)

posted @ 2022-09-20 14:39  hongdada  阅读(831)  评论(0编辑  收藏  举报