获取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));
}

适配器模式应用~获取IP地址时想起了适配器的更多相关文章

  1. 解决获取IP地址时出现“在一个非套…

    今天单位的一台机器在用IPCONFIG/RENEW时遇到了这个问题,上网查了一下,网上的版本在对XP不太好用,网上的版本如下: 1.从注册表中备份以下项:(当然也可以用Erunt备份整个注册表)HKE ...

  2. ubuntu16.04无法获取ip地址的解决方案

    当我们无法获取ip地址时可以使用dhcp来动态获取ip地址,安装dhcpcd5和dhcpcd-gtk sudo apt-get install dhcpcd5 sudo apt-get install ...

  3. DHCP获取IP地址过程中捕获的报文—三级网络总结(二)

    上一篇文章主要说了一下知识点中的IP地址的考点,这一篇我打算说说DHCP获取IP地址过程中捕获的报文的这个考点,都是自己的理解,有错误欢迎指正. DHCP是应用层协议,UDP是传输层协议,IP是网络层 ...

  4. vc根据域名获取IP地址 gethostbyname()函数

    以下是VC Socket初始化时用到的两个函数 一.WSAStartup函数                int WSAStartup                       (         ...

  5. iOS根据域名获取ip地址

    引入头文件 #include <netdb.h> #include <sys/socket.h> #include <arpa/inet.h> //根据域名获取ip ...

  6. linux如何自动获取ip地址

    第一步:激活网卡 系统装好后默认的网卡是eth0,用下面的命令将这块网卡激活. # ifconfig eth0 up 第二步:设置网卡进入系统时启动 想要每次开机就可以自动获取IP地址上网,就要设置网 ...

  7. 1. 通过DHCP服务器动态获取IP地址之后无法上网的解决方法

    故障:内网正常,在同一个局域网内的其它PC端通过DHCP获取IP地址并且可以正常上网. 1.通过wireshark抓包,使用ipconfig /renew时,wireshark内出现DHCP请求服务, ...

  8. php 获取ip地址的5种方法,插入用户登录日志实例

    php 获取ip地址的5种方法,插入用户登录日志实例,推荐使用第二种方法 <?php //方法1: $ip = $_SERVER["REMOTE_ADDR"]; echo $ ...

  9. PHP 获取IP地址位置信息「聚合数据API」

    聚合数据 提供了[查询IP所属区域]的服务接口,只需要以 GET 请求的方式向 API 传入 IP地址 和 APPKEY 即可获得查询结果. 这里的难点主要在于如何通过PHP获取客户端IP地址,以及如 ...

  10. JavaScript和微信小程序获取IP地址的方法

    最近公司新加了一个需求,根据用户登录的IP地址判断是否重复登录,重复登录就进行逼退,那么怎么获取到浏览器的IP地址呢?最后发现搜狐提供了一个JS接口,可以通过它获取到客户端的IP. 接口地址如下: h ...

随机推荐

  1. 音视频入门-8-ffmpeg小实验-v4l2 ubuntu取图、格式转换、编码成H264,ffplay观看

    1. getpic_transform_encode2h264.c #include <stdio.h> #include <string.h> #include <st ...

  2. 暑假集训CSP提高模拟1

    A.Start 比较小的大模拟,还没改出来 B.mine 线性推一下(这个题记搜容易写偏,因为分讨太多) 设 \(f[i][j]\),第一维表示位置,第二位表示末位状态(是雷,是 \(0\),是 \( ...

  3. excel江湖异闻录--Klaus

    最开始接触数组公式,是偶然在公众号看到"看见星光"大佬的一个提取混合文本中电话号码的公式,记得当时大佬是用vlookup解的这题,当时完全不能理解,mid中第二参数为什么是个row ...

  4. meminfo一些容易混淆的点

    MemTotal: 688576 kB 总内存 MemFree: 153736 kB 空闲内存 MemAvailable: 339884 kB 可用内存 Buffers: 16 kB 给文件的缓冲大小 ...

  5. 【首场重磅亮相】KaiwuDB 1.0 时序数据库线上发布会明日开启!邀您共同见证

    首场重磅亮相 KaiwuDB 是浪潮集团控股的数据库企业,以多模数据库为核心,面向工业物联网.数字能源.交通车联网.智慧城市.数字政务等多种场景,提供领先创新的数据服务软件. 新生代数据库,扬帆起航正 ...

  6. 通过maven动态配置spring boot配置文件

    一.引入maven插件的jar包 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifact ...

  7. 云原生周刊:Kubernetes v1.31 中的移除和主要变更|2024.7.22

    开源项目 Argo Rollouts Argo Rollouts 是一个 Kubernetes 控制器和一组自定义资源定义(CRDs),提供高级部署功能,例如蓝绿部署.金丝雀部署.金丝雀分析.实验以及 ...

  8. 入门级别 Nginx 常用配置清单

    本文为转发文章,转发来自"https://mp.weixin.qq.com/s/ipUHaFPcDfIM9MsyqDGSEg",觉得不错分享给大家 Nginx 是一个高性能的 HT ...

  9. JS 绘制 Cardinal 样条曲线

    Cardinal 曲线 根据定义,给定点集 \(\{ \mathbf {P}_{k-1}, \mathbf {P}_k, \mathbf {P}_{k+1}, \mathbf {P}_{k+2} \} ...

  10. 七、Spring Boot集成Spring Security之前后分离认证最佳实现

    二.自定义用户名密码认证过滤器RestfulUsernamePasswordAuthenticationFilter 1.注册过滤器方式 使用httpSecurity.addFilter/addFil ...