Spring中@RestControllerAdvice注解的使用详解
作者:小七乀
一、@RestControllerAdvice是什么
@RestControllerAdvice是一个组合注解,由@ControllerAdvice、@ResponseBody组成,而@ControllerAdvice继承了@Component,因此@RestControllerAdvice本质上是个Component,用于定义@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMapping方法。
二、@RestControllerAdvice的特点
1、注解了@RestControllerAdvice的类的方法可以使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上。
2、@RestControllerAdvice注解将作用在所有注解了@RequestMapping的控制器的方法上。
3、@ExceptionHandler:用于指定异常处理方法。当与@RestControllerAdvice配合使用时,用于全局处理控制器里的异常。
4、@InitBinder:用来设置WebDataBinder,用于自动绑定前台请求参数到Model中。
5、@ModelAttribute:本来作用是绑定键值对到Model中,当与@RestControllerAdvice配合使用时,可以让全局的@RequestMapping都能获得在此处设置的键值对
@RestControllerAdvice public class GlobalControllerAdivice { private static final Logger log = LoggerFactory.getLogger(GlobalControllerAdivice.class); @InitBinder public void dataBind(WebDataBinder binder) { // 构造方法中 boolean 参数含义为如果是空白字符串,是否转换为 null // 即如果为 true,那么 " " 会被转换为 null,否者为"" binder.registerCustomEditor(String.class, new StringTrimmerEditor(true)); } /** * 权限码异常 */ @ExceptionHandler(NotPermissionException.class) public AjaxResult handleNotPermissionException(NotPermissionException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage()); return AjaxResult.error(HttpStatus.FORBIDDEN, "没有访问权限,请联系管理员授权"); } // 全局数据绑定 // 应用到所有@RequestMapping注解方法 // 此处将键值对添加到全局,注解了@RequestMapping的方法都可以获得此键值对 @ModelAttribute public void addUser(Model model) { model.addAttribute("msg", "此处将键值对添加到全局,注解了@RequestMapping的方法都可以获得此键值对"); } }
@ControllerAdvice可以指定 Controller 范围
basePackages: 指定一个或多个包,这些包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理
@RestControllerAdvice(basePackages={"com.alibaba"}) @Slf4j public class ExceptionHandlerAdvice { @ExceptionHandler(Exception.class) public String handleException(Exception e) { return "error"; } }
basePackageClasses: 是 basePackages 的一种变形,指定一个或多个 Controller 类,这些类所属的包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理
@RestControllerAdvice(basePackageClasses={TestController.class}) @Slf4j public class ExceptionHandlerAdvice { @ExceptionHandler(Exception.class) public String handleException(Exception e) { return "error"; } }
assignableTypes: 指定一个或多个 Controller 类,这些类被该 @ControllerAdvice 管理
@RestControllerAdvice(assignableTypes={TestController.class}) @Slf4j public class ExceptionHandlerAdvice { @ExceptionHandler(Exception.class) public String handleException(Exception e) { return "error"; } }
annotations: 指定一个或多个注解,被这些注解所标记的 Controller 会被该 @ControllerAdvice 管理
@ControllerAdvice(annotations = {TestAnnotation.class}) @Slf4j public class ExceptionHandlerAdvice { @ExceptionHandler(Exception.class) public String handleException(Exception e) { return "error"; } }
三、@ExceptionHandler
1、根据不同业务场景自定义返回码
/** * 返回状态码 * * @author */ public class HttpStatus { /** * 操作成功 */ public static final int SUCCESS = 200; /** * 对象创建成功 */ public static final int CREATED = 201; /** * 请求已经被接受 */ public static final int ACCEPTED = 202; /** * 操作已经执行成功,但是没有返回数据 */ public static final int NO_CONTENT = 204; /** * 资源已被移除 */ public static final int MOVED_PERM = 301; /** * 重定向 */ public static final int SEE_OTHER = 303; /** * 资源没有被修改 */ public static final int NOT_MODIFIED = 304; /** * 参数列表错误(缺少,格式不匹配) */ public static final int BAD_REQUEST = 400; /** * 未授权 */ public static final int UNAUTHORIZED = 401; /** * 访问受限,授权过期 */ public static final int FORBIDDEN = 403; /** * 资源,服务未找到 */ public static final int NOT_FOUND = 404; /** * 不允许的http方法 */ public static final int BAD_METHOD = 405; /** * 资源冲突,或者资源被锁 */ public static final int CONFLICT = 409; /** * 不支持的数据,媒体类型 */ public static final int UNSUPPORTED_TYPE = 415; /** * 系统内部错误 */ public static final int ERROR = 500; /** * 接口未实现 */ public static final int NOT_IMPLEMENTED = 501; }
2、根据不同的业务场景定制异常
/** * 未能通过的权限认证异常 * * @author */ public class NotPermissionException extends RuntimeException { private static final long serialVersionUID = 1L; public NotPermissionException(String permission) { super(permission); } public NotPermissionException(String[] permissions) { super(StringUtils.join(permissions, ",")); } }
3、业务流程中抛出定制异常
/** * 验证用户是否具备某权限, 如果验证未通过,则抛出异常: NotPermissionException * * @param permission 权限字符串 * @return 用户是否具备某权限 */ public void checkPermi(String permission) { if (!hasPermi(getPermiList(), permission)) { throw new NotPermissionException(permission); } }
4、定制全局异常处理器处理各种异常
/** * 全局异常处理器 * * @author */ @RestControllerAdvice public class GlobalExceptionHandler { private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * 权限码异常 */ @ExceptionHandler(NotPermissionException.class) public AjaxResult handleNotPermissionException(NotPermissionException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage()); return AjaxResult.error(HttpStatus.FORBIDDEN, "没有访问权限,请联系管理员授权"); } }
四、@InitBinder
@InitBinder从字面意思可以看出这个的作用是给Binder做初始化的,@InitBinder主要用在@Controller中标注于方法上(@RestController也算),表示初始化当前控制器的数据绑定器(或者属性绑定器),只对当前的Controller有效。@InitBinder标注的方法必须有一个参数WebDataBinder。所谓的属性编辑器可以理解就是帮助我们完成参数绑定,然后是在请求到达controller要执行方法前执行!
用法如下:
@InitBinder private void initBinder(WebDataBinder binder) { // 可用于自定义参数校验,然后通过addValidators来进行绑定controller binder.addValidators(userValidator); // 可用于注册 属性编译器 binder.registerCustomEditor(String.class,new StringTrimmerEditor(true)); }
WebDataBinder到底是干嘛的?
在Servlet中,有一个方法:request.getParameter("paramName"),它会根据key返回一个String类型的数据,从而获取到前端传递过来的请求参数。但是如果我们这样一个一个地去取出Web请求中的所有参数,就会很麻烦。我们知道Java中有对象的概念,那有没有办法将request中的请求参数都自动封装到一个Java对象中呢?为了解决这个问题,SpringMVC中就引入了WebDataBinder的概念。
WebDataBinder的作用是从Web 请求中,把请求里的参数都绑定到对应的JavaBean上!在Controller方法中的参数类型可以是基本类型,也可以是封装后的普通Java类型。若这个普通的Java类型没有声明任何注解,则意味着它的每一个属性都需要到Request中去查找对应的请求参数,而WebDataBinder则可以帮助我们实现从Request中取出请求参数并绑定到JavaBean中。
到此这篇关于Spring中@RestControllerAdvice注解的使用详解的文章就介绍到这了,更多相关@RestControllerAdvice注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!