【问题标题】:How to target specific handlers with a @ControllerAdvice @ModelAttribute?如何使用@ControllerAdvice @ModelAttribute 定位特定的处理程序?
【发布时间】:2016-03-17 04:37:29
【问题描述】:

我想在系统关闭前 5 分钟在特定页面上显示警告消息。我没有手动将其添加到每个这些页面,而是创建了一个带有 @ModelAttribute 方法的 @ControllerAdvice 类,该方法将消息添加到 Model 参数中,但据我了解阅读文档和 SO 以及一些初始测试,此模型属性将被添加到每个方法都带有@RequestMapping。

我意识到我可以重构我的代码,以便目标方法都在一个控制器中,并将 @ControllerAdvice 限制在该控制器中,但我最终会在该控制器中得到一组其他不相关的方法,这会混淆我的控制器的整体结构。

那么,有没有办法指示@ModelAttribute 应用于多个控制器中的哪些特定方法?自定义注释会是一个解决方案吗(不确定它是如何工作的)?如果可能的话,我想通过注释来做到这一点。

编辑:

@ControllerAdvice 代码非常基本:

@ControllerAdvice
public class GlobalModelController {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private MaintenanceInterceptor maintInterceptor; 

    @ModelAttribute()
    public void globalAttributes(Model model, Locale locale) {
        if (maintInterceptor.isMaintenanceWindowSet() && !maintInterceptor.isMaintenanceInEffect()) {
            String msg = maintInterceptor.getImminentMaint(locale);
            model.addAttribute("warningMaint", msg);
            logger.debug("maint msg= " + msg);          
        }
    }
}

【问题讨论】:

  • 能否请您添加一些代码来阐明您到目前为止所做的尝试?

标签: spring-mvc spring-4


【解决方案1】:

可以通过使用 @ControllerAdvice 注释的值之一将控制器建议限制为某些控制器(而不是方法),例如

@ControllerAdvice(assignableTypes = {MyController1.class, MyController2.class})

如果您需要在方法级别上执行此操作,我建议您查看Interceptors

【讨论】:

  • 我实际上是在使用拦截器在维护开始后重定向到“系统不可用”页面。那么,您的建议是查看 preHandle 方法中的处理程序参数,并将消息作为会话属性而不是模型属性添加到请求中?
  • 拦截器可以通过postHandle方法访问模型。 “作为会话属性添加到请求中” 是矛盾的。您只需将其添加到请求中即可。
  • 我的错,我应该在评论之前查看postHandle方法。
【解决方案2】:

感谢@zeroflagL 将我指向拦截器解决方案。我放弃了@ControllerAdvice 方法并最终得到了这个:

自定义注释:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MaintAware {
    String name() default "MaintAware";
}

拦截器:

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

    HandlerMethod handlerMethod = (HandlerMethod)handler;
    Method method = handlerMethod.getMethod();
    MaintAware maintAware = method.getAnnotation(MaintAware.class);
    if (maintAware != null) {
        Locale locale = request.getLocale();
        if (isMaintenanceWindowSet() && !isMaintenanceInEffect()) {
            String msg = getImminentMaint(locale);
            if (!msg.isEmpty())
                modelAndView.addObject("warningMaint", msg);
        }
    }

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

现在我可以注释需要维护通知的具体方法。十分简单。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-12
    相关资源
    最近更新 更多