(Springboot,SpringCloud )RestTemplate原封不动进行路由(ROUTE)支持所有请求方式转发

  1. 代码
package com.phfund.dmsp.transfer.controller;


import com.phfund.dmsp.common.util.IpUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.RestTemplate;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

@RequestMapping(value = "/route")
@RestController
public class RouteController {
    @Value("${zullurl}")
    private String zullurl;

    @Autowired
    RestTemplate restTemplate;
    Logger logger = LogManager.getLogger(this.getClass());

    private final long MAX_SIZE = 10 * 1024 * 1024 * 1024;// 设置上传文件最大为 10G

    /**
     * 统一转发入口
     */
    @RequestMapping(value = "dispatch/api/**")
    private Object route(HttpServletRequest request, HttpServletResponse response) {

        String msg = "请求异常,具体请查看系统日志.....";
        Object result = null;
        try {
            result = dispatch(request, response);
        } catch (ServletException e) {
            logger.error("转发异常:" + e.getMessage());
            return msg;
        }

        return result;
    }

    /**
     * 请求的转发
     */
    private Object dispatch(HttpServletRequest req, HttpServletResponse res) throws ServletException {
        RequestEntity<byte[]> requestEntity = null;
        try {
            String prefix = "/route/dispatch/api/";
            String requestURI = req.getRequestURI().replace(" ", "");
            String path = requestURI.substring(prefix.length());
            String url = zullurl + path;
            String queryString = req.getQueryString();
            if (queryString != null) {
                url += "?" + queryString;
            }
            logger.info(url);
            requestEntity = this.createRequestEntity(req, url);
        } catch (Exception e) {
            logger.error("构造request请求实体报错:" + e);
            return null;
        }
        String msg = "非401鉴权不通过的其他状态错误,请根据日志定位";
        try {
            ResponseEntity<String> result = restTemplate.exchange(requestEntity, String.class);
            createResponseHeaders(res, result);
            if (200 == result.getStatusCodeValue()) {
                return result.getBody();
            }
        } catch (RestClientResponseException e) {
            //捕获非200状态码异常
            //获取接口返回状态码
            int stu = e.getRawStatusCode();
            if (401 == stu) {
                logger.error("鉴权不通过.......");
                msg = "鉴权不通过......";
            } else {
                logger.error("非401鉴权不通过的其他状态错误,请根据日志定位", e);
            }
        }
        return msg;
    }
    /**
     * 构造response请求头
     */
    private void createResponseHeaders(HttpServletResponse res, ResponseEntity<String> result) {
        HttpHeaders httpHeaders = result.getHeaders();
        for (Map.Entry<String, List<String>> entry : httpHeaders.entrySet()) {
            String headerName = entry.getKey();
            List<String> headerValues = entry.getValue();
            for (String headerValue : headerValues) {
                res.addHeader(headerName, headerValue);
            }
        }
    }

    /**
     * 构造request实体
     */
    private RequestEntity<byte[]> createRequestEntity(HttpServletRequest request, String url)
            throws URISyntaxException, IOException {
        String method = request.getMethod();
        //获取请求方式
        HttpMethod httpMethod = HttpMethod.resolve(method);
        //处理header部分
        MultiValueMap<String, String> headers = createRequestHeaders(request);
        //处理body部分
        byte[] body = createRequestBody(request);
        //构造request
        RequestEntity<byte[]> requestEntity = new RequestEntity<byte[]>(body, headers, httpMethod, new URI(url));
        return requestEntity;
    }

    /**
     * 处理body部分
     */
    private byte[] createRequestBody(HttpServletRequest request) throws IOException {
        InputStream inputStream = request.getInputStream();
        return StreamUtils.copyToByteArray(inputStream);
    }

    /**
     * 处理请求头
     */
    private MultiValueMap<String, String> createRequestHeaders(HttpServletRequest request) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("dptServer", "dptServer");
        String consumerIp = IpUtils.getIpAddr(request);
        logger.info("客户端ip: " + consumerIp);
        headers.add("consumerIp", consumerIp);
        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;
    }


    public void uploadDispatch(ServletRequest request, ServletResponse res, String toUrl)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 设置内存缓冲区,超过后写入临时文件
        factory.setSizeThreshold(4096);
        // 设置上传到服务器上文件的临时存放目录 -- 非常重要,防止存放到系统盘造成系统盘空间不足
        factory.setRepository(new File("./uploadFileTemp"));

        ServletFileUpload fileUpload = new ServletFileUpload(factory);
        fileUpload.setHeaderEncoding("utf-8");
        // 设置单个文件的最大上传值
        fileUpload.setSizeMax(MAX_SIZE);  // 文件上传上限10G
        List<FileItem> fileItemList = null;
        try {
            fileItemList = fileUpload.parseRequest(req);
        } catch (FileUploadException e) {
            //log.error("上传文件解析错误,{}", e.getMessage());
            throw new ServletException(e);
        }
         /*
         * 注意,在SpringMVC环境中,需要配置spring.servlet.multipart.enabled=false
         * 来去掉SpringMVC对上传操作的解析,否则这里得到的上传文件个数为0
         * */
        if (fileItemList == null || fileItemList.size() == 0) {
            throw new ServletException("没有文件");
        }
        List<Object> fileList = new ArrayList<>();
        for (final FileItem fileItem : fileItemList) {
            //log.info(">>>file name:{}", fileItem.getName());
            ByteArrayResource byteArr = new ByteArrayResource(fileItem.get()) {
                @Override
                public String getFilename() throws IllegalStateException {
                    return fileItem.getName();
                }
            };
            fileList.add(byteArr);
        }
        // 进行转发
        MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
        if (fileList.size() == 1) {
            parts.add("file", fileList.get(0));
        } else {
            parts.add("file", fileList);
        }

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity<MultiValueMap<String, Object>> mutiReq = new HttpEntity<>(parts, headers);
        ResponseEntity<byte[]> responseEntity = restTemplate.exchange(toUrl, HttpMethod.POST, mutiReq, byte[].class,
                new HashMap<String, Object>());

        if (responseEntity.hasBody()) {
            try {
                ServletOutputStream outputStream = res.getOutputStream();
                outputStream.write(responseEntity.getBody());
                outputStream.flush();
            } catch (IOException e) {
                throw new ServletException(e);
            }
        }
    }

}
  1. 如果经过zuul网关,需要在网关配置中加入
# 将指定路由的敏感头信息设置为空
zuul.routes.dpt-server.sensitive-headers=
# 对指定路由开启自定义敏感头
zuul.routes.dpt-server.custom-sensitive-headers=true

**网关默认过滤掉headers中的 "Cookie", "Set-Cookie", "Authorization"**
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值