昨天学习@ControllerAdvice
注解时,很可惜Spring MVC
中文文档对其的描述很简单,难以理解它的用法。通过百度一翻,最后总结了@ControllerAdvice
的以下几种用法:
文档对其的描述是:
@ControllerAdvice
是一个组件注解
,它使得其实现类能够被classpath扫描自动发现。若应用是通过MVC命令空间或MVC Java编程方式配置,那么该特性默认是自动开启的。
注解@ControllerAdvice
的类可以拥有@ExceptionHandler、@InitBinder或@ModelAttribute
注解的方法,并且这些方法会被应用至控制器类层次的所有@RequestMapping
方法上。
所以,在使用@ControllerAdvice
注解时,应该在dispatcherservlet
配置文件中指定其路径。例如(该注解类放在org.spring包下):
控制器
package org.spring;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping(path = "/hello")
public String execute()
throws Exception {
throw new Exception("抛出异常啦");
}
}
@ControllerAdvive注解类
package org.spring;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class Advice {
@ExceptionHandler(Exception.class)
public void test(Exception e) {
System.out.println(e.getMessage());
}
}
这里的Advice
是全局处理器,test
是全局异常处理方法,当控制器抛出异常时,test
方法将会被调用,同时可以传入抛出的异常,获取其中定义的错误信息。
@ControllerAdvive注解类
package org.spring;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
@ControllerAdvice
public class Advice {
@ModelAttribute("name")
public String test() {
return "huanghaifeng";
}
}
控制器
package org.spring;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping(path = "/hello")
public String execute(ModelMap model){
return model.getAttribute("name").toString();
}
}
在 @RequestMapping
注解方法execute
执行前,先会执行@ControllerAdvice
注解的类里的test
方法,把数据填充到model
中,然后可以在execute
方法调用mode
l的相应方法取出。
控制器
package org.spring;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping(path = "/hello")
public String execute(@ModelAttribute("a") person p) {
return p.name;
}
}
class person {
public person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String name;
}
@ControllerAdvive注解类
package org.spring;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
@ControllerAdvice
public class Advice {
@InitBinder("a")
public void a(WebDataBinder binder) {
binder.setFieldDefaultPrefix("a.");
}
@ModelAttribute("name")
public String test() {
return "huanghaifeng";
}
}
http://localhost/hello?a.name=12xh
当往@ControllerAdvice
注解添加参数,可以指定@ControllerAdvice
应用的范围。如,
// Target all Controllers annotated with @RestController
@ControllerAdvice(annotations = RestController.class)
public class AnnotationAdvice {}
指定作用域为@RestController
注解的控制器
// Target all Controllers within specific packages
@ControllerAdvice("org.example.controllers")
public class BasePackageAdvice {}
作用域为指定的包内的控制器
// Target all Controllers assignable to specific classes
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class AssignableTypesAdvice {}
直接指定作用域为控制器类型
@ControllerAdvice
注解实际上是一个增强了@Controller
功能的注解,可以把一些控制器共有的处理,解离出去,优化程序。