将请求中的请求属性注入 spring 控制器方法
Inject request attribute from request to spring controller methods
我有一些 spring @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);
}
但仍然需要我在每个方法中添加该参数。
能否以某种方式将此参数注入到每个方法中?
如果您真的想了解属性,那么您应该查看 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);
}
您可以使用 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>>
变量。
只需在其余的 controller
中添加 @ResuestAttribute
@RestController
@RequestMapping(path="/yourpath")
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity getAll(
@RequestAttribute(value = "yourAttribute") Object
你的属性......
我有一些 spring @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);
}
但仍然需要我在每个方法中添加该参数。 能否以某种方式将此参数注入到每个方法中?
如果您真的想了解属性,那么您应该查看 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);
}
您可以使用 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>>
变量。
只需在其余的 controller
中添加@ResuestAttribute
@RestController
@RequestMapping(path="/yourpath")
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity getAll(
@RequestAttribute(value = "yourAttribute") Object
你的属性......