适配器模式应用~获取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));
}
适配器模式应用~获取IP地址时想起了适配器的更多相关文章
- 解决获取IP地址时出现“在一个非套…
今天单位的一台机器在用IPCONFIG/RENEW时遇到了这个问题,上网查了一下,网上的版本在对XP不太好用,网上的版本如下: 1.从注册表中备份以下项:(当然也可以用Erunt备份整个注册表)HKE ...
- ubuntu16.04无法获取ip地址的解决方案
当我们无法获取ip地址时可以使用dhcp来动态获取ip地址,安装dhcpcd5和dhcpcd-gtk sudo apt-get install dhcpcd5 sudo apt-get install ...
- DHCP获取IP地址过程中捕获的报文—三级网络总结(二)
上一篇文章主要说了一下知识点中的IP地址的考点,这一篇我打算说说DHCP获取IP地址过程中捕获的报文的这个考点,都是自己的理解,有错误欢迎指正. DHCP是应用层协议,UDP是传输层协议,IP是网络层 ...
- vc根据域名获取IP地址 gethostbyname()函数
以下是VC Socket初始化时用到的两个函数 一.WSAStartup函数 int WSAStartup ( ...
- iOS根据域名获取ip地址
引入头文件 #include <netdb.h> #include <sys/socket.h> #include <arpa/inet.h> //根据域名获取ip ...
- linux如何自动获取ip地址
第一步:激活网卡 系统装好后默认的网卡是eth0,用下面的命令将这块网卡激活. # ifconfig eth0 up 第二步:设置网卡进入系统时启动 想要每次开机就可以自动获取IP地址上网,就要设置网 ...
- 1. 通过DHCP服务器动态获取IP地址之后无法上网的解决方法
故障:内网正常,在同一个局域网内的其它PC端通过DHCP获取IP地址并且可以正常上网. 1.通过wireshark抓包,使用ipconfig /renew时,wireshark内出现DHCP请求服务, ...
- php 获取ip地址的5种方法,插入用户登录日志实例
php 获取ip地址的5种方法,插入用户登录日志实例,推荐使用第二种方法 <?php //方法1: $ip = $_SERVER["REMOTE_ADDR"]; echo $ ...
- PHP 获取IP地址位置信息「聚合数据API」
聚合数据 提供了[查询IP所属区域]的服务接口,只需要以 GET 请求的方式向 API 传入 IP地址 和 APPKEY 即可获得查询结果. 这里的难点主要在于如何通过PHP获取客户端IP地址,以及如 ...
- JavaScript和微信小程序获取IP地址的方法
最近公司新加了一个需求,根据用户登录的IP地址判断是否重复登录,重复登录就进行逼退,那么怎么获取到浏览器的IP地址呢?最后发现搜狐提供了一个JS接口,可以通过它获取到客户端的IP. 接口地址如下: h ...
随机推荐
- 单片机-XIP-外部闪存就地执行代码
声明:此博文所述我未实践,目的是知识整理. 1. 常说的 "单片机的norflash上可以执行代码 " 这句话该如何理解? CPU做取指.译码.执行. 常说的哪些介质可以执行程序 ...
- Java项目笔记(四)
1.包装类判断是否相等时,建议用equals 而不是 == 号 2.+= 默认包含了强制类型转换,单纯的s = s+1;编译是无法通过的,因为1属于int类型,必须显示声明强制类型转换 short s ...
- /proc/pids/limits
cat /proc/39977/limits Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Ma ...
- iOS定义常量的两种方式define和FOUNDATION_EXPORT
FOUNDATION_EXPORT的使用方法: 1.h文件 FOUNDATION_EXPORT NSString * const kTestString; 2.m文件NSString * const ...
- .Net 理解异步的学习
// 异步 - 在方法中使用 // 异步约等于线程 async await 一起使用 // 异步只有三种返回值 // 1. Task // 2. Task<T> // 3. void 几乎 ...
- DDD之领域服务与应用服务
领域服务: 聚合中的实体没有业务逻辑代码,只有对象的创建,对象的初始化,状态管理等个体相关的代码: 对于聚合内的业务逻辑,我们编写领域服务Domain service 而对于聚合协作以及聚合与外部系统 ...
- Android复习(三)清单文件中的元素——>path-permission、permission、permission-group、permission-tree
<path-permission> 语法: <path-permission android:path="string" android:pathPrefix=& ...
- spring cloud openfeign 源码
一.读取注解信息 入口 1 import org.springframework.boot.SpringApplication; 2 import org.springframework.boot.a ...
- 云原生周刊:Argo CD v2.12 发布候选版本 | 2024.06.24
开源项目推荐 kOps kOps - Kubernetes Operations,是一个用于创建.销毁.升级和维护生产级高可用 Kubernetes 集群的工具.它支持在 AWS.GCP.Digita ...
- Web渗透09_文件包含漏洞
1 文件包含漏洞描述 开发人员编写代码时独立性好是一个很重要的要求,这边一个数据库类,那边一个模型类.几百行的整体代码,在整合时两行行代码就可以包含进来使用.文件包含有助于独立的代码之间的配合!有时引 ...