当一个 Web 应用中的多个控制器类需要完成一些共同的操作时,传统的做法是定义一个控制器父类(例如 BaseController),包含执行共同操作的方法,其他控制器类继承这个父类。虽然继承能提高代码可重用性,但 Java 不支持多继承,一旦控制器类继承了父类,就不能再继承其他类,这限制了灵活性。
Spring MVC 框架提供了另一种方式来为多个控制器类提供共同的方法:利用 @ControllerAdvice 注解来定义一个控制器增强类。
控制器增强类并不是控制器类的父类。在程序运行时,Spring MVC 框架会把控制器增强类的方法代码块动态注入到其他控制器类中,通过这种方式来增强控制器类的功能。
以下是一个典型的 MyControllerAdvice 类示例,其中的 setColors() 方法向 Model 中加入一个 colors 属性:
package mypack;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
import java.util.*;
@ControllerAdvice
public class MyControllerAdvice {
@ModelAttribute(name = "colors")
public Map<String,String> setColors() {
HashMap<String, String> colors = new HashMap<>();
colors.put("RED", "红色");
colors.put("BLUE", "蓝色");
colors.put("GREEN", "绿色");
return colors;
}
}
当程序运行时,Spring MVC 框架会把 MyControllerAdvice 类的 setColors() 方法动态注入到其他控制器类中,因此其他控制器类自动拥有了该方法。例如在 TestAttributeController 类中可以直接访问 Model 中的 colors 属性:
@RequestMapping(value="/testColor")
public String testColor(
@ModelAttribute("colors") Map<String,String> colors,
@ModelAttribute("userName") String name){
System.out.println(name+"'s favourite color:" +colors.get("RED"));
return "result";
}
通过浏览器访问 http://localhost:8080/helloapp/testColor?name=Tom,testColor() 方法会在服务器端打印'TOM's favourite color:红色'。


