Spring Controllers:我可以在调用每个 @RequestMapping 方法之前调用一个方法吗?

Posted

技术标签:

【中文标题】Spring Controllers:我可以在调用每个 @RequestMapping 方法之前调用一个方法吗?【英文标题】:Spring Controllers: Can I call a method before each @RequestMapping method is called? 【发布时间】:2011-02-23 07:41:13 【问题描述】:

我有一些公共组件,它们始终存在于给定 Controller 类提供的每个页面中。

在每个@RequestMapping 方法的开始,我用这些通用组件填充模型。

有没有办法在每个控制器方法之前定义一个方法被调用,以便我可以将所有这些复制/粘贴到一个地方?

【问题讨论】:

你试过扩展 HandlerInterceptorAdapter 吗? 【参考方案1】:

只需用@ModelAttribute注解一个方法

下面会在模型中添加一个名为“foo”的 Foo 实例

@ModelAttribute("foo")
public Foo foo() 
    return new Foo();

请参阅@ModelAttribute 文档

【讨论】:

你可以只为请求映射方法的一个子集做吗?【参考方案2】:

拦截器是解决方案。它有 preHandler 和 postHandler 方法,分别在每次请求之前和之后调用。您可以挂钩到每个 HTTPServletRequest 对象,也可以通过挖掘它来传递一些。

这是一个示例代码:

@Component
public class AuthCodeInterceptor extends HandlerInterceptorAdapter 

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception 

        // set few parameters to handle ajax request from different host
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
        response.addHeader("Access-Control-Max-Age", "1000");
        response.addHeader("Access-Control-Allow-Headers", "Content-Type");
        response.addHeader("Cache-Control", "private");

        String reqUri = request.getRequestURI();
        String serviceName = reqUri.substring(reqUri.lastIndexOf("/") + 1,
                reqUri.length());
                if (serviceName.equals("SOMETHING")) 

                
        return super.preHandle(request, response, handler);
    

    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception 

        super.postHandle(request, response, handler, modelAndView);
    

【讨论】:

在这种情况下,您将调用所有控制器。有没有办法在不再次明确定义请求映射的情况下将其与控制器紧密结合? 你能把它固定在一个控制器上吗? 是的,您可以在 pre & post 处理程序方法中设置条件,例如 if (serviceName.startsWith("SOMETHING")) .... ,其中某些内容是您在控制器上提供的 requestMapping .唯一的问题是,您应该在控制器级别有一些通用映射。例如对于 AuthController,如果我在控制器级别提供了一个带有单词“AUTH”的 Req 映射,那么同样可以在 pre & post 处理程序方法条件下使用。希望这会有所帮助!【参考方案3】:

具有@ModelAttribute 注解的所有方法在特定处理程序之前被调用,并且返回值被添加到模型实例中。然后,您可以在视图中使用此属性并作为处理程序参数。

我发现this blog 非常有用。

【讨论】:

这对我来说比接受的答案更有用,因为这并没有告诉你如何访问你的 ModelAttribute。作为参考,它是myRequestMappingHandler(@ModelAttribute("myobject") MyObject myObject)【参考方案4】:

是的,您可以使用interceptor。你可以通过<mvc:interceptors>来定义它们

另一种选择是使用 s Filter,但您将无法将 spring bean 注入其中。

【讨论】:

更正:Spring bean 可以使用 DelegatingFilterProxy 注入过滤器。【参考方案5】:

另一种方法是将控制器类注释为请求范围 (@Scope('request')),以便每个请求都会创建控制器的新实例以调用其上的匹配方法。

然后,您可以将所有预处理工作放入构造后方法(即使用@PostConstruct 注释的普通方法),该方法将始终在初始化新控制器实例(即创建并解决所有依赖项)后调用) 并且在调用请求匹配方法之前。

我想如果控制器的初始化很繁重(例如昂贵的计算或需要解决的许多依赖项),这将有点低效;但这是解决这个问题的另一种方法。

【讨论】:

以上是关于Spring Controllers:我可以在调用每个 @RequestMapping 方法之前调用一个方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

应用Mongoose开发MongoDB控制器(controllers)

Laravel 5.1 错误调用未定义函数 App\Http\Controllers\Auth\sendRegistermail()

在 Laravel 5 中找不到类“App\Http\Controllers\Artisan”

具有多个 DispatcherServlet 的 Spring Boot,每个 DispatcherServlet 都有自己的 @Controller

Spring Boot 编写Test测试用例的几种方式

无法在 codeigniter 中调用控制器