zoukankan      html  css  js  c++  java
  • Spring跨系统转发HTTP请求的简易实现(支持下载文件二进制流)

    背景

    有一个系统是Web端,作为Gateway服务,背后有许多微服务,可以经过HTTP转发过去,同时这个Web系统作为权限认证,因此可以修改一些Header,放一些用户信息给到后端系统。

    需求

    就是将HttpServletRequest 翻译成一个RestTemplate请求

    使用RestTemplate转发所有请求

    public static ResponseEntity<byte[]> dispatchHttpRequest(HttpServletRequest request, String url,
                                                             Map<String, String[]> params, HttpHeaders headerParams,
                                                             String service, boolean isFile) {
            HttpHeaders requestHeaders = new HttpHeaders();
            HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    
            //复制原始HttpHeaders
            Enumeration<?> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String key = (String) headerNames.nextElement();
                String value = request.getHeader(key);
                requestHeaders.set(key, value);
            }
               
            requestHeaders.setAll(headerParams.toSingleValueMap());
    
            if (httpMethod.equals(HttpMethod.GET)) {
                requestHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
            }
            //读取RequestBody, 似乎读取不到 Form参数。
            String dataFromRequest = getJsonDataFromRequest(request);
    
            UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url).query(request.getQueryString());
            UriComponents build;
            try {
                params.forEach(builder::queryParam);
                build = builder.build(true);
            }catch (Exception e) {
                throw new BaseException(-1, "参数不合法:" + e.getMessage());
            }
            Optional<List<String>> contentTypes = Optional.ofNullable(requestHeaders.get(HttpHeaders.CONTENT_TYPE));
            
            //修改Content-Type
            if (contentTypes.isPresent()
                    && !contentTypes.get().contains(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")
                && !contentTypes.get().contains(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
                && !contentTypes.get().contains(MediaType.APPLICATION_JSON_UTF8_VALUE)
                && !contentTypes.get().contains(MediaType.APPLICATION_JSON_VALUE)
            ) {
              requestHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
            }
            //设置默认值为JSON。
            if (!httpMethod.equals(HttpMethod.GET) && !contentTypes.isPresent()) {
              requestHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
            }
    
            logger.info("data from request: {}", dataFromRequest);
            HttpEntity<?> entity  = new HttpEntity<>(dataFromRequest, requestHeaders);
            
            //处理 APPLICATION_FORM_URLENCODED形式编码 的参数
            if (!httpMethod.equals(HttpMethod.GET)
                && contentTypes.isPresent() && (
                        contentTypes.get().contains(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
                    || contentTypes.get().contains(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"))
                && requestHeaders.getContentLength() > 0
            ) {
                MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
                Enumeration parameterNames = request.getParameterNames();
                while (parameterNames.hasMoreElements()) {
                    String o = (String)parameterNames.nextElement();
                    if (!build.getQueryParams().containsKey(o)) {
                        parameters.add(o, request.getParameter(o));
                    }
                }
                logger.info("parameterMap {}", parameters);
                if (StringUtils.isBlank(dataFromRequest)) {
                    entity = new HttpEntity<>(parameters,  requestHeaders);
                }
            }
            logger.info("Content-Type: {}, Content-Length: {}", requestHeaders.getContentType(), requestHeaders.getContentLength());
            logger.debug("after url: {} entity: {}", build.toUriString(), JSON.toJSONString(entity));
            ResponseEntity<byte[]> response;
            try {
                response = restTemplate.exchange(build.toUri(), httpMethod, entity, byte[].class);
            }catch (HttpClientErrorException httpClientException) {
                if (httpClientException.getStatusCode().value() == 404) {
                    throw new BaseException(-1, service + "可能已经离线或重启中,请稍后再访问,因为您访问的地址出现404错误");
                }
                if (isFile && httpClientException.getStatusCode().value() >= 400) {
                    return ResponseEntity.status(HttpStatus.NOT_FOUND).body(httpClientException.getResponseBodyAsByteArray());
                }
                throw httpClientException;
            }
            return response;
        }
    
        private static String getJsonDataFromRequest(HttpServletRequest request) {
            BufferedReader br = null;
            StringBuilder sb = new StringBuilder();
            try {
                br = new BufferedReader(new InputStreamReader(request.getInputStream(), "utf-8"));
                String temp;
                while ((temp = br.readLine()) != null) {
                    sb.append(temp);
                }
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return sb.toString();
        }
    
    
  • 相关阅读:
    原来触发器不是单行数据触发
    C#-Json-抽象类的反序列化
    vs项目模板创建和使用
    c#-Json-Json字符串字段递归排序
    C# 递增操作符 ++ --
    C# in 参数修饰符
    C# 改变控制台背景颜色
    第一篇不知道说什么
    爬取性感小姐姐
    windows + Eclipse 汉化
  • 原文地址:https://www.cnblogs.com/slankka/p/13746174.html
Copyright © 2011-2022 走看看