适配器模式应用~获取IP地址时想起了适配器

获取IP地址信息时,一般我们需要一个HttpServletRequest对象,然后从请求头里获取x-forwarded-for的值,而当我们使用dubbo+netty开发rest接口时,如果希望获取IP地址,HttpServletRequest是用不了的,你需要使用netty中的NettyRequestFacade对象,这时,你之前的获取IP地址的方法需要扩展,加一个只有入参不一样,代码逻辑完成一样的丑陋的,重复的代码;这无疑是一种代码的坏味道,应该想办法解决它。

适配器(包装器)

这种常用的设计模式在spring框架里用的非常多,如ServletRequestAttributes,它包装了HttpServletRequest和HttpServletResponse,用来添加额外的功能,如获取请求参数、session等信息。

为获取IP地址添加包装

自己的http请求包装器接口RequestWrapper

public interface RequestWrapper {

	String getHeader(String name);

	String getRemoteAddr();

}

HttpServletRequest的包装

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));
}
posted @ 2024-12-18 13:48  张占岭  阅读(17)  评论(0编辑  收藏  举报