SpringMVC中几种获取访客IP的方法


核心在获取HttpServletRequest
第一种方法:

在方法上面的参数列表里打上HttpServletRequest

    @RequestMapping(value="/index.html",method=RequestMethod.GET)
        public String index(HttpServletRequest req) {
            String remoteAddr = req.getRemoteAddr();
            System.out.println(remoteAddr);
            return "index";
        }

第二种方法:

使用@autowire自动注入HttpServletRequest对象,在controller页面

    @Autowired
    HttpServletRequest req;


第三种方法:

使用springMVC封装的方法得到request

    @RequestMapping(value="/index.html",method=RequestMethod.GET)
        public String index() {
            HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String remoteAddr = req.getRemoteAddr();
            System.out.println(remoteAddr);
            return "index";
        }

注意点:

如果在本机上开发,使用http://localhost:8080/之类去访问,会得到一串都是0的IP,把localhost改成127.0.0.1即可看到效果

如果采用nginx反向代理,需要改写一下才能获取到访客的真实ip:可以写一个如下的工具类

    package com.utils;
     
    import javax.servlet.http.HttpServletRequest;
     
    public class GetIP {
        public String getIP(HttpServletRequest 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.getHeader("X-Real-IP");
            }
            if(ip==null || ip.length()==0 || "unknown".equalsIgnoreCase(ip)){
                ip=request.getRemoteAddr();
            }
            return ip;
        }
        
        
    }


---------------------
作者:白学家Lynn
来源:CSDN
原文:https://blog.csdn.net/Lynn_coder/article/details/79388337
版权声明:本文为博主原创文章,转载请附上博文链接!

====================================================================================================================================

SpringMvc中获取Request

  • Controller中加参数
  • 自动注入
  • 基类中自动注入
  • 手动调用
  • @ModelAttribute方法

 

Controller中加参数

 
@Controller
public class TestController { @RequestMapping("/test") public void test(HttpServletRequest request) { ...... } }
 

Controller中获取request对象后,如果要在其他方法中(如service方法、工具类方法等)使用request对象,需要在调用这些方法时将request对象作为参数传入

此时request对象是方法参数,相当于局部变量,毫无疑问是线程安全的。 

自动注入

 
@Controller
public class TestController{ @Autowired private HttpServletRequest request; //自动注入request  @RequestMapping("/test") public void test() throws InterruptedException{ ...... } }
 

使用这种方式,当Bean(本例的TestController)初始化时,Spring并没有注入一个request对象,而是注入了一个代理(proxy);当Bean中需要使用request对象时,通过该代理获取request对象。request实际上是一个代理:代理的实现参见AutowireUtils的内部类ObjectFactoryDelegatingInvocationHandler。

调用request的方法method时,实际上是调用了由objectFactory.getObject()生成的对象的method方法;objectFactory.getObject()生成的对象才是真正的request对象。

objectFactory的类型为WebApplicationContextUtils的内部类RequestObjectFactory;而RequestObjectFactory要获得request对象需要先调用currentRequestAttributes()方法获得RequestAttributes对象,生成RequestAttributes对象的核心代码在类RequestContextHolder中,生成的RequestAttributes对象是线程局部变量(ThreadLocal),因此request对象也是线程局部变量;这就保证了request对象的线程安全性。

基类中自动注入

 
public class BaseController { @Autowired protected HttpServletRequest request; } @Controller public class TestController extends BaseController { }
 

与方法2相比,避免了在不同的Controller中重复注入request;但是考虑到java只允许继承一个基类,所以如果Controller需要继承其他类时,该方法便不再好用。

手动调用

 
@Controller
public class TestController { @RequestMapping("/test") public void test() throws InterruptedException { HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest(); ....... } }
 

通过自动注入实现与通过手动方法调用实现原理差不多。因此本方法也是线程安全的。

优点:可以在非Bean中直接获取。缺点:如果使用的地方较多,代码非常繁琐;因此可以与其他方法配合使用。

@ModelAttribute方法

 
@Controller
public class TestController { private HttpServletRequest request; 此处线程不安全 @ModelAttribute public void bindRequest(HttpServletRequest request) { this.request = request; 此处request线程安全 } @RequestMapping("/test") public void test() throws InterruptedException { ...... } }
 

@ModelAttribute注解用在Controller中修饰方法时,其作用是Controller中的每个@RequestMapping方法执行前,该方法都会执行。bindRequest()的作用是在test()执行前为request对象赋值。虽然bindRequest()中的参数request本身是线程安全的,但由于TestController是单例的,request作为TestController的一个域,无法保证线程安全。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM