a54546 发表于 2025-2-7 01:15:03

适配器模式应用~获取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;        }调用示例:
// 使用HttpServletRequestpublic String getIpFromHttp(HttpServletRequest request) {    return getIpAddr(new HttpRequestWrapper(request));}// 使用NettyRequestFacadepublic String getIpFromNetty(NettyRequestFacade request) {    return getIpAddr(new NettyRequestWrapper(request));}
页: [1]
查看完整版本: 适配器模式应用~获取IP地址时想起了适配器