目的:写一个外壳,把用户请求转发到不同的微服务中
思路:通过过滤器filter把所有请求拦截下来,然后调用okHttpHelper方法获取响应。
okHttpHelper方法内判断请求类型,调用不同的方法进行拼接请求。
getRemoteResponse封装响应类
createCookieJar生成CookieJar可以理解为cookie的一个集合
使用的是httpclient封装请求okhttp3,之前使用的RestTemplate,请求体会产生乱码,无法解决,最后换成okhttp3。
注意事项:
1.设置响应,再响应体Headers里面遍历添加
if (!CollectionUtils.isEmpty(okResponseWrap.getHeaders())) {
okResponseWrap.getHeaders().get(“Set-Cookie”).forEach(cookie -> {
servletResponse.addHeader(“Set-Cookie”, cookie);
});
}
servletResponse.setStatus(okResponseWrap.getCode());
out.write(String.valueOf(okResponseWrap.getBody()));
out.flush();
2.springboot初始化bean的顺序为:listener -> filter -> servlet -> 普通bean所以无法在filter中注入普通的bean,只能通过init方法中手工进行bean注入
ServletContext servletContext = filterConfig.getServletContext();
WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
okHttpHelper = applicationContext.getBean(OkHttpHelper.class);
3.构建请求参数遍历数组的时候记得加上索引
两个帮助类
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
public class OkHttpUtil {
private static final Logger logger = LoggerFactory.getLogger(OkHttpUtil.class);
/**
- get
- @param url 请求的url
- @param queries 请求的参数,在浏览器 ? 后面的数据,没有可以传null
- @return
*/
public static String get(String url, Map<String, String> queries) {
String responseBody = “”;
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());
}
}
}
Request request = new Request.Builder().url(sb.toString()).build();
Response response = null;
try {
OkHttpClient okHttpClient = new OkHttpClient();
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.getStackTrace());
} finally {
if (response != null) {
response.close();
}
}
return responseBody;
}
/**
- post
- @param url 请求的url
- @param params post form 提交的参数
- @return
*/
public static String post(String url, Map<String, String> params) {
String responseBody = “”;
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()).build();
Response response = null;
try {
OkHttpClient okHttpClient = new OkHttpClient();
response = okHttpClient.newCall(request).execute();
int status = response.code();
if (response.isSuccessful()) {
return response.body().string();
}
} catch (Exception e) {
logger.error(“okhttp3 post error >> ex = {}”, e.getStackTrace());
} finally {
if (response != null) {
response.close();
}
}
return responseBody;
}
/**
- getForHeader
- @param url 请求的url
- @param queries 请求的参数,在浏览器 ? 后面的数据,没有可以传null
- @return
*/
public static String getForHeader(String url, Map<String, String> queries) {
String responseBody = “”;
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());
}
}
}
Request request = new Request.Builder()
.addHeader(“key”,“value”)
.url(sb.toString())
.build();
Response response = null;
try {
OkHttpClient okHttpClient = new OkHttpClient();
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.getStackTrace());
} finally {
if (response != null) {
response.close();
}
}
return responseBody;
}
/**
- Post请求发送JOSN数据…{“name”:“zhangsan”,“password”:“1234”}
- @param url 请求的url
- @param jsonParams 请求的JSON
-
请求回调
- @return
*/
public static String postJsonParams(String url,String jsonParams){
String responseBody = null;
RequestBody requestBody = RequestBody.create(MediaType.parse(“application/json; charset=utf8”), jsonParams);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
Response response = null;
try {
OkHttpClient okHttpClient = new OkHttpClient();
response = okHttpClient.newCall(request).execute();
int status = response.code();
if (response.isSuccessful()) {
return response.body().string();
}
} catch (Exception e) {
logger.error(“okhttp3 post error >> ex = {}”, e.getStackTrace());
} finally {
if (response != null) {
response.close();
}
}
return responseBody;
}
/**
- Post请求发送xml数据…
- 参数一:请求Url
- 参数二:请求的xmlString
- 参数三:请求回调
*/
public static String postXmlParams(String url, String xml) {
String responseBody = “”;
RequestBody requestBody = RequestBody.create(MediaType.parse(“application/xml; charset=utf-8”), xml);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
Response response = null;
try {
OkHttpClient okHttpClient = new OkHttpClient();
response = okHttpClient.newCall(request).execute();
int status = response.code();
if (response.isSuccessful()) {
return response.body().string();
}
} catch (Exception e) {
logger.error(“okhttp3 post error >> ex = {}”, e.getStackTrace());
} finally {
if (response != null) {
response.close();
}
}
return responseBody;
}
}
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.*;
import java.nio.charset.Charset;
public class HttpHelper {
/**
- 获取post请求中的Body
- @param request
- @return
*/
public static String getBodyString(ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
//读取流并将流写出去,避免数据流中断; //设置编码
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName(“UTF-8”)));
//reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName(“GBK”)));
String line = “”;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
public static String getResponseBodyString(ServletResponse response) {
StringBuilder sb = new StringBuilder();
OutputStream outputStream = null;
BufferedWriter writer = null;
try {
outputStream = response.getOutputStream();
//读取流并将流写出去,避免数据流中断;
writer = new BufferedWriter(new OutputStreamWriter(outputStream, Charset.forName(“UTF-8”)));
String body = “”;
writer.write(body);
sb = sb.append(body);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
//添加自定义的信息到请求体中;
public static String appendCustomMsgToReqBody(String newReqBodyStr) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
String newReqBody = null;
try {
//通过字符串构造输入流;
inputStream = String2InputStream(newReqBodyStr);
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName(“UTF-8”)));
String line = “”;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//返回字符串;
newReqBody = sb.toString();
return newReqBody;
}
//将字符串转化为输入流;
public static InputStream String2InputStream(String str) {
ByteArrayInputStream stream = null;
try {
stream = new ByteArrayInputStream(str.getBytes(“UTF-8”));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return stream;
}
}
实现方法
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
@Component
@EnableConfigurationProperties({TransmitProperties.class})
public class OkHttpHelper {
@Autowired
private OkHttpClient okHttpClient;
@Autowired
private TransmitProperties transmitProperties;
/**
- 执行远程调用,获取响应状态码和响应体
- @param request
- @return
*/
public OkResponseWrap execute(HttpServletRequest request) {
String method = request.getMethod();
if (method.equalsIgnoreCase(“GET”)) {
return this.get(request);
} else if (method.equalsIgnoreCase(“POST”)) {
return this.post(request);
} else if (method.equalsIgnoreCase(“DELETE”)) {
return this.delete(request);
} else if (method.equalsIgnoreCase(“PUT”)) {
return this.put(request);
} else {
OkResponseWrap okResponseWrap = new OkResponseWrap();
okResponseWrap.setCode(400);
okResponseWrap.setBody(“请求异常,请检查网络!”);
return okResponseWrap;
}
}
/**
- 发起put请求
- @param request
- @return
*/
private OkResponseWrap put(HttpServletRequest request) {
//获取请求路径
String requestUrl = request.getRequestURI().toString();
//获取请求体
String jsonParams = HttpHelper.getBodyString(request);
//构造请求体
//StringBuffer remoteUrl = new StringBuffer(this.transmitProperties.getRemoteUrl() + requestUrl.replaceFirst(this.transmitProperties.getHostUrl(), “”));
StringBuffer remoteUrl = requestUrl(requestUrl);
RequestBody requestBody = RequestBody.create(MediaType.parse(“application/json;charset=utf-8”), jsonParams);
Request.Builder builder = new Request.Builder().url(remoteUrl.toString()).put(requestBody);
Request okRequest = this.createOkRequest(builder, request);
//发起请求
return this.getRemoteResponse(okRequest, request);
}
/**
- 发起delete请求
- @param request
- @return
*/
private OkResponseWrap delete(HttpServletRequest request) {
//获取请求路径
String requestUrl = request.getRequestURI().toString();
//获取请求体
String jsonParams = HttpHelper.getBodyString(request);
//StringBuffer remoteUrl = new StringBuffer(this.transmitProperties.getRemoteUrl() + requestUrl.replaceFirst(this.transmitProperties.getHostUrl(), “”));
StringBuffer remoteUrl = requestUrl(requestUrl);
RequestBody requestBody = RequestBody.create(MediaType.parse(“application/json;charset=utf-8”), jsonParams);
//构造请求体
Request.Builder builder = new Request.Builder().url(remoteUrl.toString()).delete(requestBody);
Request okRequest = this.createOkRequest(builder, request);
//发起请求
return this.getRemoteResponse(okRequest, request);
}
/**
- 发起post请求,参数为json
- @param request
- @return
*/
private OkResponseWrap post(HttpServletRequest request) {
//获取请求路径
String requestUrl = request.getRequestURI().toString();
//获取请求体
String jsonParams = HttpHelper.getBodyString(request);
//构造请求体
//StringBuffer remoteUrl = new StringBuffer(this.transmitProperties.getRemoteUrl() + requestUrl.replaceFirst(this.transmitProperties.getHostUrl(), “”));
StringBuffer remoteUrl = requestUrl(requestUrl);
RequestBody requestBody = RequestBody.create(MediaType.parse(“application/json;charset=ut-8”), jsonParams);
Request.Builder builder = new Request.Builder().url(remoteUrl.toString()).post(requestBody);
Request okRequest = this.createOkRequest(builder, request);
//发起请求
return this.getRemoteResponse(okRequest, request);
}
/**
- 发起get请求
- @param request
- @return
*/
private OkResponseWrap get(HttpServletRequest request) {
//获取请求路径
String requestUrl = request.getRequestURI().toString();
String[] split = requestUrl.split("/");
System.out.println(split[1]);
//获取请求头
Enumeration<String> headerNames = request.getHeaderNames();
//获取请求参数
Map<String, String[]> queries = request.getParameterMap();
StringBuffer sb = this.buildRemoteUrlWithParam(requestUrl, queries);
//构建请求体
Request.Builder builder = new Request.Builder().url(sb.toString()).get();
Request okRequest = this.createOkRequest(builder, request);
return getRemoteResponse(okRequest, request);
}
/**
- 根据请求域名前缀不同,拼接不同的情趣地址
- @param requestUrl
- @return
*/
private StringBuffer requestUrl(String requestUrl) {
StringBuffer remoteUrl = null;
String[] split = requestUrl.split("/");
String path = split[1];
if (path != null && path.equalsIgnoreCase("v1")) {
remoteUrl = new StringBuffer(this.transmitProperties.getOmsJavaUrl() + requestUrl.replaceFirst(this.transmitProperties.getHostUrl(), ""));
} else {
remoteUrl = new StringBuffer(this.transmitProperties.getRemoteUrl() + requestUrl.replaceFirst(this.transmitProperties.getHostUrl(), ""));
}
return remoteUrl;
}
private OkResponseWrap getRemoteResponse(Request request, HttpServletRequest servletRequest) {
OkResponseWrap okResponseWrap = new OkResponseWrap();
Response okResponse = null;
try {
//设置cookie
OkHttpClient build = okHttpClient.newBuilder().cookieJar(this.createCookieJar(servletRequest)).build();
//向remote服务器发起请求
okResponse = build.newCall(request).execute();
//封装okResponseWrap类
int code = okResponse.code();
String body = okResponse.body().string();
List cookieHeaders = okResponse.headers(“Set-Cookie”);
okResponseWrap.setCode(code);
okResponseWrap.setBody(body);
Map<String, List> headers = new ConcurrentHashMap<>();
if (!CollectionUtils.isEmpty(cookieHeaders)) {
headers.put(“Set-Cookie”, cookieHeaders);
okResponseWrap.setHeaders(headers);
}
} catch (IOException e) {
//此处添加日志
e.printStackTrace();
okResponseWrap.setCode(500);
okResponseWrap.setBody(“服务器异常,请联系管理员!”);
} finally {
if (okResponse != null) {
okResponse.close();
}
}
return okResponseWrap;
}
/**
-
生成cookieJar(可以理解为cookie一个集合)
-
@param request
-
@return
*/
private CookieJar createCookieJar(HttpServletRequest request) {
return new CookieJar() {
@Override
public void saveFromResponse(HttpUrl httpUrl, List<okhttp3.Cookie> list) {}
@Override
public List<okhttp3.Cookie> loadForRequest(HttpUrl httpUrl) {
List<okhttp3.Cookie> cookieList = new ArrayList<>();
Cookie[] cookies = request.getCookies();
okhttp3.Cookie.Builder cookieBuilder = new okhttp3.Cookie.Builder();
Stream.of(cookies).forEach(cookie -> {
//
cookieList.add(cookieBuilder.domain(transmitProperties.getRemoteDomain()).name(cookie.getName()).value(cookie.getValue()).build());
});
return cookieList;
}
};
}
/**
- 生成OkRequest请求
- @param builder
- @param request
- @return
*/
private Request createOkRequest(Request.Builder builder, HttpServletRequest request) {
//********
Enumeration<String> headerNames = request.getHeaderNames();
//遍历请求头,添加到okRequest中
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String header = request.getHeader(headerName);
builder.addHeader(headerName, header);
}
return builder.build();
}
private StringBuffer buildRemoteUrlWithParam(String requestUrl, Map<String, String[]> queries) {
// StringBuffer sb = new StringBuffer(this.transmitProperties.getRemoteUrl() + requestUrl.replaceFirst(this.transmitProperties.getHostUrl(), “”));
StringBuffer sb = requestUrl(requestUrl);
if (queries != null && queries.keySet().size() > 0) {
boolean firstFlag = true;
Iterator<Map.Entry<String, String[]>> iterator = queries.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String[]> entry = iterator.next();
if (firstFlag) {
for (int i = 0; i < entry.getValue().length; i++) {
if (firstFlag) {
sb.append("?" + entry.getKey() + "=" + entry.getValue()[i]);
firstFlag = false;
} else {
sb.append("&" + entry.getKey() + "=" + entry.getValue()[i]);
}
}
}
}
}
return sb;
}
}
拦截器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
- 任意请求转发处理过滤器
*/
@Component
public class RequestTransmitFilter implements Filter {
/**
- 配置url
*/
//private final String URL = “http://www.baidu.com/”;
@Autowired
private OkHttpHelper okHttpHelper;
/**
- springboot初始化bean的顺序为:listener -> filter -> servlet -> 普通bean
- 所以无法在filter中注入普通的bean,只能通过init方法中手工进行bean注入
- @param filterConfig
- @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
ServletContext servletContext = filterConfig.getServletContext();
WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
okHttpHelper = applicationContext.getBean(OkHttpHelper.class);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
/*chain.doFilter(request, response);
if(false){*/
/*response.setCharacterEncoding(this.filterConfig.getInitParameter("encoding"));
System.out.println("HttpRequestAndResponseFilterBefore");
chain.doFilter(request, response);*/
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
//设置响应头
servletResponse.setCharacterEncoding("UTF-8");
servletResponse.setContentType("application/json;charset=utf-8");
//发起请求,获取响应
OkResponseWrap okResponseWrap = this.okHttpHelper.execute((HttpServletRequest) request);
PrintWriter out = null;
try {
out = servletResponse.getWriter();
//设置响应
if (!CollectionUtils.isEmpty(okResponseWrap.getHeaders())) {
okResponseWrap.getHeaders().get("Set-Cookie").forEach(cookie -> {
servletResponse.addHeader("Set-Cookie", cookie);
});
}
servletResponse.setStatus(okResponseWrap.getCode());
out.write(String.valueOf(okResponseWrap.getBody()));
out.flush();
} catch (Exception e) {
//服务器异常
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
/* }*/
}
@Override
public void destroy() {
}
}