javascript
controlleradvice 参数_Spring MVC之@ControllerAdvice详解
對(duì)于@ControllerAdvice,我們比較熟知的用法是結(jié)合@ExceptionHandler用于全局異常的處理,但其作用不僅限于此。ControllerAdvice拆分開來(lái)就是Controller Advice,關(guān)于Advice,前面我們講解Spring Aop時(shí)講到,其是用于封裝一個(gè)切面所有屬性的,包括切入點(diǎn)和需要織入的切面邏輯。這里ContrllerAdvice也可以這么理解,其抽象級(jí)別應(yīng)該是用于對(duì)Controller進(jìn)行“切面”環(huán)繞的,而具體的業(yè)務(wù)織入方式則是通過(guò)結(jié)合其他的注解來(lái)實(shí)現(xiàn)的。@ControllerAdvice是在類上聲明的注解,其用法主要有三點(diǎn):
結(jié)合方法型注解@ExceptionHandler,用于捕獲Controller中拋出的指定類型的異常,從而達(dá)到不同類型的異常區(qū)別處理的目的;
結(jié)合方法型注解@InitBinder,用于request中自定義參數(shù)解析方式進(jìn)行注冊(cè),從而達(dá)到自定義指定格式參數(shù)的目的;
結(jié)合方法型注解@ModelAttribute,表示其標(biāo)注的方法將會(huì)在目標(biāo)Controller方法執(zhí)行之前執(zhí)行。
從上面的講解可以看出,@ControllerAdvice的用法基本是將其聲明在某個(gè)bean上,然后在該bean的方法上使用其他的注解來(lái)指定不同的織入邏輯。不過(guò)這里@ControllerAdvice并不是使用AOP的方式來(lái)織入業(yè)務(wù)邏輯的,而是Spring內(nèi)置對(duì)其各個(gè)邏輯的織入方式進(jìn)行了內(nèi)置支持。本文將對(duì)@ControllerAdvice的這三種使用方式分別進(jìn)行講解。
1. @ExceptionHandler
@ExceptionHandler的作用主要在于聲明一個(gè)或多個(gè)類型的異常,當(dāng)符合條件的Controller拋出這些異常之后將會(huì)對(duì)這些異常進(jìn)行捕獲,然后按照其標(biāo)注的方法的邏輯進(jìn)行處理,從而改變返回的視圖信息。如下是@ExceptionHandler的屬性結(jié)構(gòu):
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
// 指定需要捕獲的異常的Class類型
Class extends Throwable>[] value() default {};
}
如下是我們使用@ExceptionHandler捕獲RuntimeException異常的例子:
@ControllerAdvice(basePackages = "mvc")
public class SpringControllerAdvice {
@ExceptionHandler(RuntimeException.class)
public ModelAndView runtimeException(RuntimeException e) {
e.printStackTrace();
return new ModelAndView("error");
}
}
這里我們模擬一個(gè)訪問(wèn)user detail的接口,在該接口中拋出了RuntimeException,那么理論上,這里的異常捕獲器就會(huì)捕獲該異常,然后返回默認(rèn)的error試圖。如下是UserController的代碼:
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/detail", method = RequestMethod.GET)
public ModelAndView detail(@RequestParam("id") long id) {
ModelAndView view = new ModelAndView("user");
User user = userService.detail(id);
view.addObject("user", user);
throw new RuntimeException("mock user detail exception.");
}
}
2. @InitBinder
對(duì)于@InitBinder,該注解的主要作用是綁定一些自定義的參數(shù)。一般情況下我們使用的參數(shù)通過(guò)@RequestParam,@RequestBody或者@ModelAttribute等注解就可以進(jìn)行綁定了,但對(duì)于一些特殊類型參數(shù),比如Date,它們的綁定Spring是沒有提供直接的支持的,我們只能為其聲明一個(gè)轉(zhuǎn)換器,將request中字符串類型的參數(shù)通過(guò)轉(zhuǎn)換器轉(zhuǎn)換為Date類型的參數(shù),從而供給@RequestMapping標(biāo)注的方法使用。如下是@InitBinder的聲明:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InitBinder {
// 這里value參數(shù)用于指定需要綁定的參數(shù)名稱,如果不指定,則會(huì)對(duì)所有的參數(shù)進(jìn)行適配,
// 只有是其指定的類型的參數(shù)才會(huì)被轉(zhuǎn)換
String[] value() default {};
}
如下是使用@InitBinder注冊(cè)Date類型參數(shù)轉(zhuǎn)換器的實(shí)現(xiàn):
@ControllerAdvice(basePackages = "mvc")
public class SpringControllerAdvice {
@InitBinder
public void globalInitBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
}
這里@InitBinder標(biāo)注的方法注冊(cè)的Formatter在每次request請(qǐng)求進(jìn)行參數(shù)轉(zhuǎn)換時(shí)都會(huì)調(diào)用,用于判斷指定的參數(shù)是否為其可以轉(zhuǎn)換的參數(shù)。如下是我們聲明的包含Date類型參數(shù)的接口:
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/detail", method = RequestMethod.GET)
public ModelAndView detail(@RequestParam("id") long id, Date date) {
System.out.println(date);
ModelAndView view = new ModelAndView("user");
User user = userService.detail(id);
view.addObject("user", user);
return view;
}
}
Tue Oct 02 00:00:00 CST 2018
可以看到,這里我們對(duì)request參數(shù)進(jìn)行了轉(zhuǎn)換,并且在接口中成功接收了該參數(shù)。
3. @ModelAttribute
關(guān)于@ModelAttribute的用法,處理用于接口參數(shù)可以用于轉(zhuǎn)換對(duì)象類型的屬性之外,其還可以用來(lái)進(jìn)行方法的聲明。如果聲明在方法上,并且結(jié)合@ControllerAdvice,該方法將會(huì)在@ControllerAdvice所指定的范圍內(nèi)的所有接口方法執(zhí)行之前執(zhí)行,并且@ModelAttribute標(biāo)注的方法的返回值還可以供給后續(xù)會(huì)調(diào)用的接口方法使用。如下是@ModelAttribute注解的聲明:
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ModelAttribute {
// 該屬性與name屬性的作用一致,用于指定目標(biāo)參數(shù)的名稱
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
// 與name屬性一起使用,如果指定了binding為false,那么name屬性指定名稱的屬性將不會(huì)被處理
boolean binding() default true;
}
這里@ModelAttribute的各個(gè)屬性值主要是用于其在接口參數(shù)上進(jìn)行標(biāo)注時(shí)使用的,如果是作為方法注解,其name或value屬性則指定的是返回值的名稱。如下是使用@ModelAttribute進(jìn)行方法標(biāo)注的一個(gè)例子:
@ControllerAdvice(basePackages = "mvc")
public class SpringControllerAdvice {
@ModelAttribute(value = "message")
public String globalModelAttribute() {
System.out.println("global model attribute.");
return "this is from model attribute";
}
}
這里需要注意的是,該方法提供了一個(gè)String類型的返回值,而@ModelAttribute中指定了該屬性名稱為message,這樣在Controller層就可以接收該參數(shù)了,如下是Controller層的代碼:
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/detail", method = RequestMethod.GET)
public ModelAndView detail(@RequestParam("id") long id,
@ModelAttribute("message") String message) {
System.out.println(message);
ModelAndView view = new ModelAndView("user");
User user = userService.detail(id);
view.addObject("user", user);
return view;
}
}
global model attribute.
this is from model attribute
可以看到,這里使用@ModelAttribute注解標(biāo)注的方法確實(shí)在目標(biāo)接口執(zhí)行之前執(zhí)行了。需要說(shuō)明的是,@ModelAttribute標(biāo)注的方法的執(zhí)行是在所有攔截器的preHandle()方法執(zhí)行之后才會(huì)執(zhí)行。
4. 小結(jié)
本文首先講解了@ControllerAdvice注解的作用,然后結(jié)合@ControllerAdvice講解了能夠與其結(jié)合的三個(gè)注解的使用方式。關(guān)于這三種使用方式,需要說(shuō)明的是,這三種注解如果應(yīng)用于@ControllerAdvice注解所標(biāo)注的類中,那么它們表示會(huì)對(duì)@ControllerAdvice所指定的范圍內(nèi)的接口都有效;如果單純的將這三種注解應(yīng)用于某個(gè)Controller中,那么它們將只會(huì)對(duì)該Controller中所有的接口有效,并且此時(shí)是不需要在該Controller上標(biāo)注@ControllerAdvice的。
5. 廣告
讀者朋友如果覺得本文還不錯(cuò),可以點(diǎn)擊下面的廣告鏈接,這可以為作者帶來(lái)一定的收入,從而激勵(lì)作者創(chuàng)作更好的文章,非常感謝!
總結(jié)
以上是生活随笔為你收集整理的controlleradvice 参数_Spring MVC之@ControllerAdvice详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: PHP probuf详细步骤_go+pr
- 下一篇: 事务回滚什么意思 try_三问Sprin