因为需要将应用服务器之外的另一台文件服务器的ip地址隐藏,并且需要记录文件访问记录,以及需要对request的请求做一些处理,nginx实现这些相当麻烦,因此直接用Java写一个反向代理,简单明了。
utils
相当于使用流拷贝的方式,将获取到的newUrl的response,拷贝到客户请求的response中,这样就实现了转发
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.StreamUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
public class ProxyUtil {
public static void proxy(URI newUri, HttpServletRequest request, HttpServletResponse response) throws IOException {
String methodName = request.getMethod();
HttpMethod httpMethod = HttpMethod.resolve(methodName);
if(httpMethod == null) {
return;
}
ClientHttpRequest delegate = new SimpleClientHttpRequestFactory().createRequest(newUri, httpMethod);
Enumeration<String> headerNames = request.getHeaderNames();
// 设置请求头
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
Enumeration<String> v = request.getHeaders(headerName);
List<String> arr = new ArrayList<>();
while (v.hasMoreElements()) {
arr.add(v.nextElement());
}
delegate.getHeaders().addAll(headerName, arr);
}
StreamUtils.copy(request.getInputStream(), delegate.getBody());
// 执行远程调用
ClientHttpResponse clientHttpResponse = delegate.execute();
response.setStatus(clientHttpResponse.getStatusCode().value());
// 设置响应头
clientHttpResponse.getHeaders().forEach((key, value) -> value.forEach(it -> {
response.setHeader(key, it);
}));
StreamUtils.copy(clientHttpResponse.getBody(), response.getOutputStream());
}
}
controller
//经过/proxy/**的地址都会返回192.168.1.1的结果,相当于nginx反向代理的效果
@RequestMapping(value = "/proxy/**")
public void proxy(HttpServletRequest request, HttpServletResponse response){
String path = uri.getPath();
URI newUri = new URI("http://192.168.1.1" + path.replace("/proxy",""))
ProxyUtil.proxy(newUri,request,response);
}
这样加上后,所有经过/proxy/**
的地址都会走一遍Java代码,你可以在代码中增加登录验证等功能
分别是哔哩哔哩序号35,小米运动序号2,米友社序号13,这个是同一个账号下运行的任务