适配器模式应用~获取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)); } 

发表评论

相关文章