将请求属性从请求注入弹簧控制器方法



我有一些弹簧@RestControllers方法,我想注入一个值,该值作为请求属性(包含用户)随每个请求一起提供,如下所示:

@RestController
@RequestMapping("/api/jobs")
public class JobsController {
     // Option 1 get user from request attribute as prop somehow
     private String userId = "user1";
    // Option 2 inject into method using aspect or something else
    @RequestMapping(value = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<List<Jobs>> getJobs() throws ResourceNotFoundException {
       // currentUser is injected 
       this.getJobs(currentUser);
}

我知道我可以做到:

@RestController
@RequestMapping("/api/jobs")
public class JobsController {
    @RequestMapping(value = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<List<Jobs>> getJobs(HttpServletRequest request) throws ResourceNotFoundException { 
       String currentUser = null;
       if (request.getAttribute("subject") != null) {
           currentUser = request.getAttribute("subject").toString();
       }
       this.getJobs(currentUser);
}

但这需要我在程序中的每个方法中添加此代码,在我看来,这是一种非常糟糕的做法。
有没有办法实现我想要的?

如果答案确实需要方面,那么代码示例将不胜感激,因为我只阅读过它,但从未真正做过方面的事情。

更新
我建议的代码可以使用以下内容进行简化:

@RestController
@RequestMapping("/api/jobs")
public class JobsController {
    @RequestMapping(value = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<List<Jobs>> getJobs(@Value("#{request.getAttribute('subject')}" String currentUser) throws ResourceNotFoundException { 
       this.getJobs(currentUser);
}

但仍然需要我在每种方法中添加该参数。这个参数可以以某种方式注入到每个方法吗?

您可以使用

Filter来填充存储该属性的ThreadLocal<String>变量:

public class MyFilter implements Filter {
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {}
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    ContextHolder.setSubject(request.getAttribute('subject'));
    chain.doFilter(request, response);
  }
  @Override
  public void destroy() {
    ContextHolder.removeSubject();
  }
}

public class ContextHolder {
  private static final ThreadLocal<String> SUBJECT = new ThreadLocal<String>() {
    @Override
    protected String initialValue() {
      return "empty";
    }
  };
  public static void setSubject(String subject) {
    SUBJECT.set(subject);
  }
  public static String getSubject() {
    return SUBJECT.get();
  }
  public static void removeSubject() {
    SUBJECT.remove();
  }
}

筛选器将配置为拦截所有请求并填充SUBJECT变量。通过使用 ThreadLocal ,您可以确保每个线程都有自己的subject值。现在,您可以通过调用 ContextHolder.getSubject() 在应用程序中的任何位置获取该值:

  @RequestMapping(value = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
  public ResponseEntity<List<Jobs>> getJobs(HttpServletRequest request) throws ResourceNotFoundException { 
    this.getJobs(ContextHolder.getSubject());
  }

您还必须在 web.xml 文件中注册Filter

<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>com.MyFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

如果您有多个属性,则可以改用ThreadLocal<Map<String, String>>变量。

只需在

休息条件中添加@RequestAttribute

@RestController
@RequestMapping(path="/yourpath")
@RequestMapping(method = RequestMethod.GET)
    public ResponseEntity getAll(
            @RequestAttribute(value = "yourAttribute") Object 

您的属性...

如果你真的想知道属性,那么你应该看看 spring 的@RequestParam注释。你可以像这样使用它:

@RequestMapping(value = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<Jobs>> getJobs(@RequestParam("subject") String currentUser) throws ResourceNotFoundException { 
   this.getJobs(currentUser);
}

最新更新