如何使用 @ControllerAdvice @ModelAttribute 定位特定的处理程序?
How to target specific handlers with a @ControllerAdvice @ModelAttribute?
我想在系统关闭前 5 分钟在特定页面上显示警告消息。我没有手动将它添加到每个页面,而是创建了一个 @ControllerAdvice class 和一个 @ModelAttribute 方法,该方法将消息添加到 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);
}
}
}
通过使用 @ControllerAdvice
注释的值之一,例如
,可以将控制器建议限制为某些控制器(不是方法)
@ControllerAdvice(assignableTypes = {MyController1.class, MyController2.class})
如果您需要在方法级别上执行此操作,我建议您查看 Interceptors。
感谢@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);
}
现在我可以注释需要维护通知的具体方法。十分简单。 :)
我想在系统关闭前 5 分钟在特定页面上显示警告消息。我没有手动将它添加到每个页面,而是创建了一个 @ControllerAdvice class 和一个 @ModelAttribute 方法,该方法将消息添加到 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);
}
}
}
通过使用 @ControllerAdvice
注释的值之一,例如
@ControllerAdvice(assignableTypes = {MyController1.class, MyController2.class})
如果您需要在方法级别上执行此操作,我建议您查看 Interceptors。
感谢@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);
}
现在我可以注释需要维护通知的具体方法。十分简单。 :)