ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringBoot(12)使用控制器通知

2022-07-18 00:03:04  阅读:151  来源: 互联网

标签:web 控制器 12 ControllerAdvice SpringBoot springframework import org 异常


控制器通知

  在编写代码时,需要对异常进行处理。进行异常处理的普通的代码是try-catch结构。但在开发业务时,只想关注业务正常的代码,对于catch语句中的捕获异常,希望交给异常捕获来处理,不单独在每个方法中编写。这样不仅可以减少冗余代码,还可以减少因忘记写catch而岀现错误的概率。Spring正好提供了一个非常方便的异常处理方案——控制器通知@ControllerAdvice或 @RestcontrollerAdvice),它将所有控制器作为一个切面,利用切面技术来实现。通过基于@ControllerAdvice或@RestControllerAdvice的注解可以对异常进行全局统一处理,默认对所有的Controller有效。如果要限定生效范围,则可以使用ContrallerAdvice支持的限定范围方式。

  • 按注解:@ControllerAdvice(annotations = RestController.class) 
  • 按包名:@ControllerAdvice("org.example.controller")
  • 按类型:@ControllerAdvice(assignableTypes = {Controllerinterface.class, Abstract- Controller.class})

这是ControllerAdvice进行统一异常处理的优点,它能够细粒度地控制该异常处理器针对娜些 Controller、包或类型有效。

可以利用这一特性在一个系统实现多个异常处理器,然后Controller可以有选择地决定使用哪 个,使得异常处理更加灵活,降低侵入性。

异常处理类会包含以下一个或多个方法。

  • @lnitBinder:对表单数据进行绑定,用于定义控制器参数绑定规则。如转换规则、格式化 等。可以通过这个注解的方法得到WebDataBinder对象,它在参数转换之前被执行。
  • @ModelAttribute:在控制器方法被执行前,对所有Controller的Model添加属性进行操作。
  • @ExceptionHandler:定义控制器发生异常后的操作,可以拦截所有控制器发生的异常。
  • @ControllerAdvice:统一异常处理,通过 @ExceptionHandler(value = class) 来指定捕获的异常。"@ControllerAdvice + @ExceptionHandle"可以处理除“404” 以外的运行异常。

  实例:自定义错误处理控制器

package com.itheima.controller;

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("${server.error.path:${error.path:/error}}")
public class TestErrorController implements ErrorController {
    @Override
    public String getErrorPath() {
        return null;
    }
    @RequestMapping
    public Map<String,Object> handleError(){
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("code",404);
        map.put("msg","不存在");
        return map;
    }
    @RequestMapping("ok")
    @ResponseBody
    public Map<String,Object> noError(){
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("code",200);
        map.put("msg","正常");
        return map;
    }
}

启动项目,访问一个不存在的网址,则返回下方信息:

{"msg":"不存在",”code":404}

访问正确定义的映射"http://localhost:8080/error/ok",则返回下方正确信息:

{"msg":"正常","code":200}

  实例:自定义业务异常类

  (1)自定义异常类

  自定义异常类需要继承Exception (异常)类。这里继承RuntimeException,

package com.itheima.exception;

public class BusinessException extends RuntimeException {
    private Integer code;
    public BusinessException(int code, String msg) {
        super(msg);
        this.code = code;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
}

  (2)自定义全局捕获异常

package com.itheima.handler;

import com.itheima.exception.BusinessException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class CustomerBusinessExceptionHandler {
    @ResponseBody
    @ExceptionHandler(BusinessException.class)
    public Map<String,Object> businessExceptionHandler(BusinessException e){
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("code",e.getCode());
        map.put("message",e.getMessage());
        return map;
    }
}

     @ControllerAdvice:

   对于@ControllerAdvice,我们比较熟知的用法是结合@ExceptionHandler用于全局异常的处理,但其作用不止于此。ControllerAdvice拆开来就是Controller Advice,关于Advice,在Spring的AOP中,是用来封装一个切面所有属性的,包括切入点和需要织入的切面逻辑。这里ControllerAdvice也可以这么理解,其抽象级别应该是用于对Controller进行切面环绕的,而具体的业务织入方式则是通过结合其他的注解来实现的。@ControllerAdvice是在类上声明的注解,其用法主要有三点:

1.结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的。

2.结合方法型注解@InitBinder,用于request中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的。

3.结合方法型注解@ModelAttribute,表示其注解的方法将会在目标Controller方法执行之前执行。

   从上面的讲解可以看出,@ControllerAdvice的用法基本是将其声明在某个bean上,然后在该bean的方法上使用其他的注解来指定不同的织入逻辑。不过这里@ControllerAdvice并不是使用AOP的方式来织入业务逻辑的,而是Spring内置对其各个逻辑的织入方式进行了内置支持。

   @Component用于声明@ExceptionHandler 、 @InitBinder或@ModelAttribute方法的类的特化,以便在多个@Controller类之间共享。
   使用@ControllerAdvice注释的类可以显式声明为 Spring bean 或通过类路径扫描自动检测。所有此类 bean 都基于Ordered语义或@Order / @Priority声明进行排序, Ordered语义优先于@Order / @Priority声明。然后在运行时按该顺序应用@ControllerAdvice bean。但是请注意,实现PriorityOrdered的@ControllerAdvice bean 的优先级不高于实现Ordered的@ControllerAdvice bean。此外, Ordered不适用于作用域@ControllerAdvice bean — 例如,如果此类 bean 已配置为请求作用域或会话作用域 bean。为了处理异常, @ExceptionHandler将在第一个通知中选择一个匹配的异常处理程序方法。对于模型属性和数据绑定初始化,@ @ModelAttribute和@InitBinder方法将遵循@ControllerAdvice顺序。
   注意:对于@ExceptionHandler方法,在特定通知 bean 的处理程序方法中,根异常匹配将优于仅匹配当前异常的原因。但是,高优先级通知上的原因匹配仍将优先于低优先级通知 bean 上的任何匹配(无论是根级别还是原因级别)。因此,请在具有相应顺序的优先通知 bean 上声明您的主根异常映射。
默认情况下, @ControllerAdvice ControllerAdvice 中的方法全局应用于所有控制器。使用诸如annotations 、 basePackageClasses和basePackages (或其别名value )之类的选择器来定义目标控制器的更窄子集。如果声明了多个选择器,则应用布尔OR逻辑,这意味着所选控制器应至少匹配一个选择器。请注意,选择器检查是在运行时执行的,因此添加许多选择器可能会对性能产生负面影响并增加复杂性。

   @ExceptionHandler:

   用于处理特定处理程序类和/或处理程序方法中的异常的注释。
使用此注释注释的处理程序方法可以具有非常灵活的签名。它们可能具有以下类型的参数,按任意顺序:异常参数:声明为一般异常或更具体的异常。如果注释本身没有通过其value()缩小异常类型,这也可用作映射提示。请求和/或响应对象(通常来自 Servlet API)。您可以选择任何特定的请求/响应类型,例如javax.servlet.ServletRequest / javax.servlet.http.HttpServletRequest 。
会话对象:通常是javax.servlet.http.HttpSession 。这种类型的参数将强制存在相应的会话。因此,这样的论点永远不会是null 。请注意,会话访问可能不是线程安全的,尤其是在 Servlet 环境中:如果允许多个请求同时访问会话,请考虑将"synchronizeOnSession"标志切换为“true”。
   org.springframework.web.context.request.WebRequest或org.springframework.web.context.request.NativeWebRequest 。允许通用请求参数访问以及请求/会话属性访问,而不与本机 Servlet API 绑定。
java.util.Locale用于当前请求的语言环境(由可用的最具体的语言环境解析器确定,即在 Servlet 环境中配置的org.springframework.web.servlet.LocaleResolver )。
java.io.InputStream / java.io.Reader用于访问请求的内容。这将是 Servlet API 公开的原始 InputStream/Reader。
java.io.OutputStream / java.io.Writer用于生成响应的内容。这将是 Servlet API 公开的原始 OutputStream/Writer。
org.springframework.ui.Model作为从处理程序方法返回模型映射的替代方法。请注意,提供的模型未预先填充常规模型属性,因此始终为空,以便为特定于异常的视图准备模型。
处理程序方法支持以下返回类型:
一个ModelAndView对象(来自 Servlet MVC)。
一个org.springframework.ui.Model对象,视图名称通过org.springframework.web.servlet.RequestToViewNameTranslator隐式确定。
用于公开模型的java.util.Map对象,视图名称通过org.springframework.web.servlet.RequestToViewNameTranslator隐式确定。
一个org.springframework.web.servlet.View对象。
一个String值,它被解释为视图名称。
@ResponseBody注释方法(仅限 Servlet)来设置响应内容。返回值将使用消息转换器转换为响应流。
用于设置响应标头和内容的HttpEntity<?>或ResponseEntity<?>对象(仅限 Servlet)。 ResponseEntity 正文将使用消息转换器进行转换并写入响应流。
void如果方法本身处理响应(通过直接编写响应内容,为此目的声明javax.servlet.ServletResponse / javax.servlet.http.HttpServletResponse类型的参数)或者视图名称应该通过隐式确定org.springframework.web.servlet.RequestToViewNameTranslator (不在处理程序方法签名中声明响应参数)。
您可以将ExceptionHandler注释与@ResponseStatus结合使用以获取特定的 HTTP 错误状态。

  (3)测试自定义异常类

  创建控制器,以抛BusinessException的自定义异常

package com.itheima.controller;

import com.itheima.exception.BusinessException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    @RequestMapping("BusinessException")
    public String testBusinessExceptionStatus(@RequestParam("i") int i){
        if (i == 0){
            throw new BusinessException(600,"这是自定义异常");
        }
        return "success";
    }
}

  启动项目,访问 "http://localhost:8080/BusinessException?i=0" 测试异常处理情况,则抛出下方错误信息:

  {"code”:600,"message”:"这是自定义异常"}

  

标签:web,控制器,12,ControllerAdvice,SpringBoot,springframework,import,org,异常
来源: https://www.cnblogs.com/liwenruo/p/16487913.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有