自定义拦截器,存储请求相关数据

通过自定义过滤器,拦截请求,存储请求相关数据,便于其他地方使用

  • 自定义bean,存储请求相关数据(可自行扩展)
/**
 * Created by ypc
 * 2023/6/27 14:52
 * Description:自定义bean,存储请求相关数据(可自行扩展)
 */
@Accessors(chain = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RequestInfo {
    /**
     * 请求ip
     */
    private String ip;

    /**
     * http 头的Referer
     */
    private String referer;

    /**
     * http 头的user-agent
     */
    private String userAgent;
}
  • 请求工具类

    利用ThreadLocal将请求数据封装在当前线程中。

/**
 * Created by ypc
 * 2023/6/27 15:12
 * Description:TODO
 */
public class RequestContext {

    private static final RequestInfo EMPTY = new RequestInfo();

    /**
     * 用于存储请求相关数据
     */
    private static final ThreadLocal<RequestInfo> threadLocal = new ThreadLocal<>();

    /**
     * 设置请求相关数据
     * @param requestInfo
     */
    public static void setRequestInfo(RequestInfo requestInfo) {
        if (requestInfo != null) {
            threadLocal.set(requestInfo);
        }
    }

    /**
     * 获取请求相关数据
     * @return
     */
    public static RequestInfo getRequestInfo() {
        return Optional.ofNullable(threadLocal.get()).orElse(EMPTY);
    }

    /**
     * 清除请求相关数据
     */
    public static void remove() {
        threadLocal.remove();
    }

    /**
     * 获取请求ip
     * @return
     */
    public static String getIp() {
        return getRequestInfo().getIp();
    }

    /**
     * 获取请求user-agent
     * @return
     */
    public static String getUserAgent() {
        return getRequestInfo().getUserAgent();
    }

    /**
     * 获取请求referer
     * @return
     */
    public static String getReferer() {
        return getRequestInfo().getReferer();
    }

}
  • 自定义请求过滤器

    实现OncePerRequestFilter接口,该接口的doFilterInternal方法可以实现对请求的过滤

    效果:基于线程,存储当前请求的相关数据

/**
 * Created by ypc
 * 2023/6/27 14:50
 * Description:自定义请求过滤器
 * 实现OncePerRequestFilter接口,该接口的doFilterInternal方法可以实现对请求的过滤
 * 效果:基于线程,存储当前请求的相关数据
 */
public class HttpContextFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        try {
            String referer = httpServletRequest.getHeader(HttpHeaderNames.REFERER.toString());
            String userAgent = httpServletRequest.getHeader(HttpHeaderNames.USER_AGENT.toString());
            String ip = getIPAddress(httpServletRequest);
            RequestInfo context = new RequestInfo(ip, referer, userAgent);
            RequestContext.setRequestInfo(context);
            filterChain.doFilter(httpServletRequest, httpServletResponse);
        } finally {
            RequestContext.remove();
        }
    }

    /**
     * 获取请求ip
     * @param request
     * @return
     */
    private String getIPAddress(HttpServletRequest request) {
        String ip = null;

        //X-Forwarded-For:Squid 服务代理
        String ipAddresses = request.getHeader("X-Forwarded-For");

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //Proxy-Client-IP:apache 服务代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //WL-Proxy-Client-IP:weblogic 服务代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //HTTP_CLIENT_IP:有些代理服务器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }

        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            //X-Real-IP:nginx服务代理
            ipAddresses = request.getHeader("X-Real-IP");
        }

        //有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }

        //还是不能获取到,最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}
  • 测试
	@RequestMapping(value = "/hi_test")
    public String hiTest(){
        return RequestContext.getIp() + "\n\n" + RequestContext.getUserAgent();
    }
  • 请求效果测试

    使用postman模拟请求,查看返回效果
    在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值