You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@Autowire注入HttpServletRequest出现空指针异常的原因排查

问题:为何HttpServletRequest注入后为Null?

编写了如下Spring代码:

package com.example.helloworld;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.annotation.RequestScope;

@RestController
public class HelloWorldController {
  @GetMapping("/")
  public ResponseEntity<String> getGet(
      @Autowired Foo foo) {

    foo.sayHi();

    return new ResponseEntity<>("OK", HttpStatus.OK);
  }
}

@Component
@RequestScope
class Foo {

  private @Autowired HttpServletRequest request;

  public void sayHi() {
    var name = this.request.getHeader("x-user-name");
    System.out.println("Hi " + name);
  }
}

执行curl命令 curl -H x-user-name:capybara http://localhost:8080 时,出现如下错误:

2022-09-09 17:07:28.623 ERROR 26350 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException: Cannot invoke "javax.servlet.http.HttpServletRequest.getHeader(String)" because "this.request" is null] with root cause

java.lang.NullPointerException: Cannot invoke "javax.servlet.http.HttpServletRequest.getHeader(String)" because "this.request" is null
        at com.example.helloworld.Foo.sayHi(HelloWorldController.java:32) ~[classes!/:0.0.1-SNAPSHOT]
        at com.example.helloworld.HelloWorldController.getGet(HelloWorldController.java:19) ~[classes!/:0.0.1-SNAPSHOT]
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:577) ~[na:na]
        at 
    ...

参考相关解答后仍未解决,为何this.request会为null?


原因分析

核心问题是在控制器方法参数上直接使用@Autowired注入请求作用域的Bean,这绕过了Spring对请求作用域Bean的代理机制:

  • Foo是@RequestScope的Bean,正常情况下Spring会为其创建代理对象,只有在请求上下文完全初始化后,才会实例化真实的Foo对象并注入HttpServletRequest。
  • 但在方法参数上标注@Autowired,Spring会在方法调用前提前尝试获取Foo的实例,此时请求上下文尚未准备完成,导致真实Foo对象创建时,HttpServletRequest无法被正常注入,最终出现NullPointerException。

解决方法

方法1:将Foo作为控制器成员变量注入

@RestController
public class HelloWorldController {
    @Autowired
    private Foo foo;

    @GetMapping("/")
    public ResponseEntity<String> getGet() {
        foo.sayHi();
        return new ResponseEntity<>("OK", HttpStatus.OK);
    }
}

方法2:移除方法参数上的@Autowired

Spring会自动解析方法参数中的Spring管理Bean,无需额外标注@Autowired,此时能正确处理请求作用域代理:

@GetMapping("/")
public ResponseEntity<String> getGet(Foo foo) {
    foo.sayHi();
    return new ResponseEntity<>("OK", HttpStatus.OK);
}

方法3:通过RequestContextHolder获取请求

绕过依赖注入,直接从请求上下文获取HttpServletRequest:

@Component
@RequestScope
class Foo {
    public void sayHi() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        var name = request.getHeader("x-user-name");
        System.out.println("Hi " + name);
    }
}

内容的提问来源于stack exchange,提问作者Renato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:50:26