将对象的新实例注入每个请求处理程序

时间:2015-03-25 07:49:54

标签: java spring spring-mvc autowired

我有很多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
}

这是否可以通过任何方式创建这样的机制,以便我可以将每个请求对象的自定义注入到我的请求处理方法中?

4 个答案:

答案 0 :(得分:3)

Spring MVC有一个参数解析器构造,直接支持您的请求。每个使用 @RequestMapping 注释的处理程序方法都将受到参数解析的约束,其中框架扫描处理程序参数,检查类型并实例化适当的对象。这就是注入请求,模型和许多其他类型的机制,只需在处理程序的方法签名中声明对象即可。

您可以编写自定义参数解析程序,以便在方法中解析并提供自定义类型。程序简单的三步过程

  1. 根据您的情况制作一个POJO课 MyRequestFoo

  2. 制作解析器,例如

      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. 3.注册一个解析器

     <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) {
       // ...
    }
    

答案 1 :(得分:2)

如何在Controller类上放置MyRequestFoo类型的实例变量,并自动将其更改为&#34; Singleton&#34;到&#34;请求&#34;关于Bean定义?

查看this链接或Spring参考表!

答案 2 :(得分:0)

我找到了一个解决方案,就是我要做的事情。

只需将MyRequestFoo创建为具有范围的bean&#34;请求&#34;并且您可以通过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中。

答案 3 :(得分:0)

由于您需要将特定于请求的信息传递给您的bean,我建议您将构建器bean注入控制器并从您的方法调用builder.build(request)以创建新的每个请求实例。