将对象的新实例注入每个请求处理程序
Inject a new instance of an object into each request handler
我有很多 Spring 个 RestControllers,其方法用 RequestMapping
注释。我现在想在这些 RequestMapping
方法中注入一个自定义对象,并为每个请求创建一个自定义实例。
我想写这样的东西:
@RequestMapping("/search")
public SomeReturnObject foobar(@RequestParam("query") String query, MyRequestFoo foo) {
// ...
}
现在我想创建一种机制,每次调用该方法(即每个请求)都会创建一个 MyRequestFoo
的新实例并将其注入到该方法中。如果使用参数注释而不是按类型注入会更好,那也可以(例如 @MyRequestInject MyRequestFoo foo
)。
我需要知道我现在是否可以创建一个方法来创建 MyRequestFoo
的新实例,特别是针对该请求,如下所示:
public MyRequestFoo createRequestInstanceSomehow(HttpServletRequest request) {
// extract some values from the HttpServletRequest and create a
// new MyRequestFoo instance from that and return it
}
是否可以通过任何方式创建这样一种机制,以便我可以将自定义的每个请求对象注入到我的请求处理方法中?
如何将 MyRequestFoo 类型的实例变量放在控制器 class 上并自动装配它,将 Bean 定义的默认范围从 "Singleton" 更改为 "Request"?
查看 this link 或 Spring 参考资料 sheet!
我找到了一个解决方案,可以满足我的要求。
只需将 MyRequestFoo
创建为范围为 "request" 的 bean,您就可以通过 RequestContextHolder
:
访问当前请求
@Component
@Scope("request")
public class MyRequestFoo {
private final HttpServletRequest request;
public MyRequestFoo() {
request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
}
// do whatever you want with the request
}
现在我可以将其类型的新实例注入到任何请求处理程序方法中:
@RequestMapping("/search")
public SomeReturnObject search(MyRequestFoo foo) {
// ...
}
并且 Spring 将自动负责实例化新实例。
无法将 MyRequestFoo
自动装配为实例变量,因为您无法将请求范围的 bean 自动装配到非请求范围的 bean 中。
Spring MVC 有一个直接支持您的请求的参数解析器构造。每个用 @RequestMapping 注释的处理程序方法都将进行参数解析,其中框架扫描处理程序参数,检查类型并实例化适当的对象。这就是注入请求、模型和许多其他类型背后的机制,只需在处理程序的方法签名中声明对象即可。
您可以编写自定义参数解析器来解析自定义类型并在方法中使用。程序简单三步流程
创建一个 POJO class,在你的情况下 MyRequestFoo
制作解析器,例如
public class MyRequestFooResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(MyRequestFoo.class);
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory)
throws Exception {
return new MyRequestFoo();
}
}
3.Register 解析器
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="your.package.MyRequestFooResolver "></bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
或在java配置中
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List< Handlermethodargumentresolver > argumentResolvers) {
MyRequestFooResolver myRequestFooResolver = new MyRequestFooResolver ();
argumentResolvers.add(myRequestFooResolver );
}
}
比你只通过添加类型作为处理程序方法参数来使用它
@RequestMapping("/search")
public SomeReturnObject search(MyRequestFoo foo) {
// ...
}
由于您需要将特定于请求的信息传递给您的 bean,我建议改为将构建器 bean 注入您的控制器并从您的方法中调用 builder.build(request)
以创建新的每个请求实例。
我有很多 Spring 个 RestControllers,其方法用 RequestMapping
注释。我现在想在这些 RequestMapping
方法中注入一个自定义对象,并为每个请求创建一个自定义实例。
我想写这样的东西:
@RequestMapping("/search")
public SomeReturnObject foobar(@RequestParam("query") String query, MyRequestFoo foo) {
// ...
}
现在我想创建一种机制,每次调用该方法(即每个请求)都会创建一个 MyRequestFoo
的新实例并将其注入到该方法中。如果使用参数注释而不是按类型注入会更好,那也可以(例如 @MyRequestInject MyRequestFoo foo
)。
我需要知道我现在是否可以创建一个方法来创建 MyRequestFoo
的新实例,特别是针对该请求,如下所示:
public MyRequestFoo createRequestInstanceSomehow(HttpServletRequest request) {
// extract some values from the HttpServletRequest and create a
// new MyRequestFoo instance from that and return it
}
是否可以通过任何方式创建这样一种机制,以便我可以将自定义的每个请求对象注入到我的请求处理方法中?
如何将 MyRequestFoo 类型的实例变量放在控制器 class 上并自动装配它,将 Bean 定义的默认范围从 "Singleton" 更改为 "Request"?
查看 this link 或 Spring 参考资料 sheet!
我找到了一个解决方案,可以满足我的要求。
只需将 MyRequestFoo
创建为范围为 "request" 的 bean,您就可以通过 RequestContextHolder
:
@Component
@Scope("request")
public class MyRequestFoo {
private final HttpServletRequest request;
public MyRequestFoo() {
request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
}
// do whatever you want with the request
}
现在我可以将其类型的新实例注入到任何请求处理程序方法中:
@RequestMapping("/search")
public SomeReturnObject search(MyRequestFoo foo) {
// ...
}
并且 Spring 将自动负责实例化新实例。
无法将 MyRequestFoo
自动装配为实例变量,因为您无法将请求范围的 bean 自动装配到非请求范围的 bean 中。
Spring MVC 有一个直接支持您的请求的参数解析器构造。每个用 @RequestMapping 注释的处理程序方法都将进行参数解析,其中框架扫描处理程序参数,检查类型并实例化适当的对象。这就是注入请求、模型和许多其他类型背后的机制,只需在处理程序的方法签名中声明对象即可。
您可以编写自定义参数解析器来解析自定义类型并在方法中使用。程序简单三步流程
创建一个 POJO class,在你的情况下 MyRequestFoo
制作解析器,例如
public class MyRequestFooResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.getParameterType().equals(MyRequestFoo.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { return new MyRequestFoo(); } }
3.Register 解析器
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="your.package.MyRequestFooResolver "></bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
或在java配置中
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List< Handlermethodargumentresolver > argumentResolvers) {
MyRequestFooResolver myRequestFooResolver = new MyRequestFooResolver ();
argumentResolvers.add(myRequestFooResolver );
}
}
比你只通过添加类型作为处理程序方法参数来使用它
@RequestMapping("/search")
public SomeReturnObject search(MyRequestFoo foo) {
// ...
}
由于您需要将特定于请求的信息传递给您的 bean,我建议改为将构建器 bean 注入您的控制器并从您的方法中调用 builder.build(request)
以创建新的每个请求实例。