【转】RestTemplate转发请求,支持所有请求类型
本文转自 :https://blog.csdn.net/weixin_44330810/article/details/122011494
最近项目中遇到网关跨区域转发请求问题,需要根据用户所在区域将请求转发到对应的区域网关,特将RestTemplate转发请求代码整理出来,供后续学习参考;
package xxx; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.core.io.FileSystemResource; import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StreamUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Map; /** * 路由代理工具类 * * 将请求重新包装发送 * * 支持所有请求; * * 支持form-data,表单,文件上传 * * @author pansh * @since 2021-12-16 16:37:54 */ @Slf4j @Component public class RoutingDelegateUtil { @Resource @Qualifier(value = "remoteRestTemplate") private RestTemplate restTemplate; /** * 上传form表单,文件 */ private final static String CONTENT_TYPE_FORM = "multipart/form-data;"; /** * 请求转发统一处理 * @param request * @param routeUrl 路由地址,统一前缀 * @return * @throws Exception */ public ResponseEntity<String> redirect(HttpServletRequest request, String routeUrl) throws Exception { String contentType = request.getContentType(); log.info("getContentType={}", contentType); // multipart/form-data处理 if (StringUtils.isNotEmpty(contentType) && contentType.contains(CONTENT_TYPE_FORM)) { return redirectFile(request, routeUrl); } else { return redirect(request, routeUrl, ""); } } /** * 上传form表单,文件 * * 请求转发处理 * @param request * @param routeUrl * @return * @throws IOException */ public ResponseEntity<String> redirectFile(HttpServletRequest request, String routeUrl) throws IOException { // build up the redirect URL String redirectUrl = createRedictUrl(request, routeUrl, ""); log.info("redirectFile redirectUrl={}", redirectUrl); String method = request.getMethod(); //设置请求头 MultiValueMap<String, String> headers = parseRequestHeader(request); // 组装form参数 MultiValueMap<String, Object> form = new LinkedMultiValueMap<>(); StandardMultipartHttpServletRequest standardMultipartHttpServletRequest = (StandardMultipartHttpServletRequest)request; // 组装form参数-文件 MultiValueMap<String, MultipartFile> multiValueMap = standardMultipartHttpServletRequest.getMultiFileMap(); for (Map.Entry<String, List<MultipartFile>> entries : multiValueMap.entrySet()) { for (MultipartFile multipartFile : entries.getValue()) { String fileName = multipartFile.getOriginalFilename(); log.info("redirectFile MultipartFile: fileName={}", fileName); File file = File.createTempFile("spw-", fileName); multipartFile.transferTo(file); FileSystemResource fileSystemResource = new FileSystemResource(file); form.add(entries.getKey(), fileSystemResource); } } // 组装form参数-一般属性 Enumeration<String> enumeration = standardMultipartHttpServletRequest.getParameterNames(); while (enumeration.hasMoreElements()) { String name = enumeration.nextElement(); String value = standardMultipartHttpServletRequest.getParameter(name); log.info("redirectFile enumeration: name={}, value={}", name, value); form.add(name, value); } // 用HttpEntity封装整个请求报文 HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<>(form, headers); return restTemplate.exchange(redirectUrl, HttpMethod.valueOf(method),formEntity,String.class); } /** * 非form-data请求转发处理 * @param request * @param routeUrl * @param prefix * @return * @throws Exception */ public ResponseEntity<String> redirect(HttpServletRequest request, String routeUrl, String prefix) throws Exception { // build up the redirect URL String redirectUrl = createRedictUrl(request,routeUrl, prefix); log.info("redirectUrl={}", redirectUrl); RequestEntity requestEntity = createRequestEntity(request, redirectUrl); return restTemplate.exchange(requestEntity, String.class); } /** * 构建重定向地址 * @param request * @param routeUrl * @param prefix * @return */ private String createRedictUrl(HttpServletRequest request, String routeUrl, String prefix) { String queryString = request.getQueryString(); return routeUrl + request.getRequestURI().substring(1, request.getRequestURI().length()).replace(prefix, "") + (queryString != null ? "?" + queryString : ""); } /** * 构建请求实体 * @param request * @param url * @return * @throws URISyntaxException * @throws IOException */ 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)); } /** * 解析请求体 * @param request * @return * @throws IOException */ private byte[] parseRequestBody(HttpServletRequest request) throws IOException { InputStream inputStream = request.getInputStream(); return StreamUtils.copyToByteArray(inputStream); } /** * 解析请求头 * @param request * @return */ 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; } }