使用控制器通知()

  本篇文章为你整理了使用控制器通知()的详细内容,包含有 使用控制器通知,希望能帮助你了解 使用控制器通知。

  控制器通知

    在编写代码时,需要对异常进行处理。进行异常处理的普通的代码是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”:"这是自定义异常"}

  以上就是使用控制器通知()的详细内容,想要了解更多 使用控制器通知的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: