適配器(qi)模(mo)式應用~獲取IP地(di)址時想起了適配器(qi)
獲取IP地址信息時,一般我們需要一個HttpServletRequest對象,然后從請求頭里獲取x-forwarded-for的(de)值,而當我們使用(yong)dubbo+netty開發rest接口時,如果希(xi)望(wang)獲取IP地(di)址(zhi),HttpServletRequest是用(yong)不了的(de),你需(xu)要使用(yong)netty中的(de)NettyRequestFacade對象,這(zhe)時,你之前的(de)獲取IP地(di)址(zhi)的(de)方(fang)法需(xu)要擴展(zhan),加一(yi)個只有(you)入參不一(yi)樣,代(dai)碼邏(luo)輯完成一(yi)樣的(de)丑(chou)陋的(de),重復的(de)代(dai)碼;這(zhe)無(wu)疑是一(yi)種代(dai)碼的(de)壞(huai)味道(dao),應該(gai)想辦法解決它。
適配器(包裝器)
這種常用的設計模式在spring框架里用的非常多,如ServletRequestAttributes,它包裝了HttpServletRequest和HttpServletResponse,用(yong)來添加(jia)額外(wai)的(de)功能,如獲取請求參數(shu)、session等信息。
為獲取IP地址添加包裝
自己的http請求包裝(zhuang)器接口RequestWrapper
public interface RequestWrapper {
String getHeader(String name);
String getRemoteAddr();
}
HttpServletRequest的(de)包裝(zhuang)
public class HttpRequestWrapper implements RequestWrapper {
private final HttpServletRequest request;
public HttpRequestWrapper(HttpServletRequest request) {
this.request = request;
}
@Override
public String getHeader(String name) {
return request.getHeader(name);
}
@Override
public String getRemoteAddr() {
return request.getRemoteAddr();
}
}
NettyRequestFacade的包裝
public class NettyRequestWrapper implements RequestWrapper {
private final NettyRequestFacade request;
public NettyRequestWrapper(NettyRequestFacade request) {
this.request = request;
}
@Override
public String getHeader(String name) {
return request.getHeader(name);
}
@Override
public String getRemoteAddr() {
return request.getRemoteAddr();
}
}
獲取IP地址方法,入參是一個http包裝器
public static String getIpAddr(RequestWrapper request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
if (ip.equals("127.0.0.1")) {
// 根據網卡取本機配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
}
catch (UnknownHostException e) {
e.printStackTrace();
}
ip = inet != null ? inet.getHostAddress() : ip;
}
}
// 對于通過多個代理的情況,第一個IP為客戶端真實IP,多個IP按照','分割
if (ip != null && ip.length() > 15) {
if (ip.indexOf(",") > 0) {
ip = ip.substring(0, ip.indexOf(","));
}
}
if ("0:0:0:0:0:0:0:1".equals(ip)) {
ip = "127.0.0.1";
}
return ip;
}
調用示例:
// 使用HttpServletRequest
public String getIpFromHttp(HttpServletRequest request) {
return getIpAddr(new HttpRequestWrapper(request));
}
// 使用NettyRequestFacade
public String getIpFromNetty(NettyRequestFacade request) {
return getIpAddr(new NettyRequestWrapper(request));
}