大家好,欢迎来到IT知识分享网。
@ControllerAdvice
Spring源码中有关@ControllerAdvice
的注解如下:
Specialization of {@link Component @Component} for classes that declare {@link ExceptionHandler @ExceptionHandler}, {@link InitBinder @InitBinder}, or {@link ModelAttribute @ModelAttribute} methods to be shared across multiple {@code @Controller} classes.
理解:
@ControllerAdvice
是一个特殊的@Component
,用于标识一个类,这个类中被以下三种注解标识的方法:@ExceptionHandler
,@InitBinder
,@ModelAttribute
,将作用于所有的@Controller
类的接口上。
那么,这个三个注解分别是什么意思,起到什么作用呢?
@InitBinder
Annotation that identifies methods which initialize the {@link org.springframework.web.bind.WebDataBinder} which will be used for populating command and form object arguments of annotated handler methods. Such init-binder methods support all arguments that {@link RequestMapping} supports, except for command/form objects and corresponding validation result objects. Init-binder methods must not have a return value; they are usually declared as {@code void}.
作用:注册属性编辑器,对HTTP请求参数进行处理,再绑定到对应的接口,比如格式化的时间转换等。应用于单个@Controller类的方法上时,仅对该类里的接口有效。与@ControllerAdvice组合使用可全局生效。
示例:
@ControllerAdvice
public class ActionAdvice {
@InitBinder
public void handleException(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss"));
}
}
IT知识分享网
@ExceptionHandler
作用:统一异常处理,也可以指定要处理的异常类型
示例:
IT知识分享网@ControllerAdvice
public class ActionAdvice {
@ExceptionHandler(Exception.class)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public Map handleException(Exception ex) {
Map<String, Object> map = new HashMap<>();
map.put("code", 400);
map.put("msg", ex.toString());
return map;
}
}
@ModelAttribute
作用:绑定数据
示例:
@ControllerAdvice
public class ActionAdvice {
@ModelAttribute
public void handleException(Model model) {
model.addAttribute("user", "zfh");
}
}
在接口中获取前面绑定的参数:
IT知识分享网@RestController
public class BasicController {
@GetMapping(value = "index")
public Map index(@ModelAttribute("user") String user) {
//...
}
}
完整示例代码:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.validation.Validator;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/** * 统一异常处理 * @author zfh * @version 1.0 * @since 2019/1/4 15:23 */
@ControllerAdvice
public class ControllerExceptionHandler {
private Logger logger = LoggerFactory.getLogger(ControllerExceptionHandler.class);
@InitBinder
public void initMyBinder(WebDataBinder binder) {
// 添加对日期的统一处理
//binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss"));
// 添加表单验证
//binder.addValidators();
}
@ModelAttribute
public void addMyAttribute(Model model) {
model.addAttribute("user", "zfh"); // 在@RequestMapping的接口中使用@ModelAttribute("name") Object name获取
}
@ExceptionHandler(value = Exception.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody // 如果使用了@RestControllerAdvice,这里就不需要@ResponseBody了
public Map handler(Exception ex) {
logger.error("统一异常处理", ex);
Map<String, Object> map = new HashMap<>();
map.put("code", 400);
map.put("msg", ex);
return map;
}
}
测试接口:
@RestController
public class TestAction {
@GetMapping(value = "testAdvice")
public JsonResult testAdvice(@ModelAttribute("user") String user, Date date) throws Exception {
System.out.println("user: " + user);
System.out.println("date: " + date);
throw new Exception("直接抛出异常");
}
}
高阶应用–格式化时间转Date
使用@ControllerAdvice
+ @InitBinder
,可将http请求参数中的时间自动转换成Date类型。
@InitBinder
public void initBinder(WebDataBinder binder) {
GenericConversionService genericConversionService = (GenericConversionService) binder.getConversionService();
if (genericConversionService != null) {
genericConversionService.addConverter(new DateConverter());
}
}
自定义的时间类型转换器:
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.StringUtils;
import java.text.SimpleDateFormat;
import java.util.Date;
/** * 日期转换类 * 将标准日期、标准日期时间、时间戳转换成Date类型 */
public class DateConverter implements Converter<String, Date> {
private static final String dateFormat = "yyyy-MM-dd HH:mm:ss";
private static final String shortDateFormat = "yyyy-MM-dd";
private static final String timeStampFormat = "^\\d+$";
@Override
public Date convert(String value) {
if(StringUtils.isEmpty(value)) {
return null;
}
value = value.trim();
try {
if (value.contains("-")) {
SimpleDateFormat formatter;
if (value.contains(":")) {
formatter = new SimpleDateFormat(dateFormat);
} else {
formatter = new SimpleDateFormat(shortDateFormat);
}
return formatter.parse(value);
} else if (value.matches(timeStampFormat)) {
Long lDate = new Long(value);
return new Date(lDate);
}
} catch (Exception e) {
throw new RuntimeException(String.format("parser %s to Date fail", value));
}
throw new RuntimeException(String.format("parser %s to Date fail", value));
}
}
扩展:
@RestControllerAdvice
= @ControllerAdvice
+ @ResponseBody
参考:
- Spring Boot 系列(八)@ControllerAdvice 拦截异常并统一处理
- SpringMVC重要注解(二)@ControllerAdvice
- 精通Spring Boot —— 第十五篇:使用@ControllerAdvice处理异常
- @InitBinder
- SpringMVC中利用@InitBinder来对页面数据进行解析绑定
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/13425.html