ICode9

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

浅析@ResponseStatus的作用、属性、用法、底层原理及使用注意事项

2021-07-22 23:03:03  阅读:234  来源: 互联网

标签:ResponseStatus RequestMapping 自定义 浅析 Response reason 注意事项 public


  @ResponseStatus注解是spring-web包中提供的一个注解,其主要作用就是为了改变HTTP响应的状态码,具有value、code、reason 三个属性,如下:

一、@ResponseStatus注解用法

  @ResponseStatus注解有两种用法,一种是加载自定义异常类上,一种是加在目标方法中,当修饰一个类的时候,通常修饰的是一个异常类。

  这里我们说一下加在目标方法上的这种情况,注解中有两个参数,value属性设置异常的状态码,reaseon是对于异常的描述,其实@ResponseStatus大部分情况下更适合于在自定义异常类或者目标方法上使用。

1、标注在@ControllerAdvice中

// controller
@GetMapping("/err")
public Response errorTest(){
    int i = 1 / 0;
    return new Response(401, "1/0", null);
}
// ExceptionController
@RestControllerAdvice
public class ExceptionController {
    // 捕捉其他所有异常
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Response globalException(HttpServletRequest request, Throwable ex) {
        return new Response(400,"1 / 0",null);
    }
}

  由于1 / 0 出现异常被我们捕获之后返回我们自定义的状态码400,和自定义的结果。ResponseStatus就是设置了状态码400。

2、标注在controller方法上

(1)修改状态码

@RequestMapping(path = "/401")
@ResponseStatus(value = HttpStatus.CREATED)
public Response unauthorized() {
    return new Response(401, "Unauthorized", null);
}

  HttpStatus.CREATED 状态码为201,将原来请求状态码200改为201。

(2)使用reason

@RequestMapping(path = "/401")
@ResponseStatus(value = HttpStatus.UNAUTHORIZED,reason = "no no no")
public Response unauthorized() {
    return new Response(401, "Unauthorized", null);
}

  如果@ResponseStatus有reason属性,@RequestMapping方法返回值都不处理了,直接返回服务器自带的 ERROR 页面,交互体验比较差,建议不要使用。

3、标注在自定义的异常类上

  使用时,先声明一个自定义异常类,在自定义异常类上面加上@ResponseStatus注释表示在系统运行期间,当抛出自定义异常的时候,使用@ResponseStatus注解中声明的属性和reason属性将异常信息返回给客户端,提高可读性。

// MyException
@ResponseStatus(code = HttpStatus.PAYMENT_REQUIRED,reason = "this is MyException")
public class MyException extends RuntimeException {
    public MyException() {
    }
}
// controller
@GetMapping("/err2")
public Response errorTest2(){
    throw new MyException();
}

二、底层实现原理

  注解底层还是通过设置 response.setStatus 来实现的。在@RequestMapping方法执行完成,Spring解析返回值之前,进行了responseStatus设置。

  代码片段位于:org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#setResponseStatus

  this对象指当前的ServletInvocableHandlerMethod,看到 @ResponseStatus的reason不为空,就调用response.sendError ; reason为空,就调用setStatus方法仅仅设置响应状态码。

  代码片段位于:org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle,发现如果ServletInvocableHandlerMethod的responseReason有值,也就是@ResponseStatus有reason属性,@RequestMapping方法返回值都不处理了,直接返回;

  也就是说只要有 @ResponseStatus 的 reason 属性标注在 处理器 Controller 类或者方法上,比如响应状态码code设置为 404,reason设置为页面没找到 ,那 tomcat 展示界面是这样大概,展示信息就是我们写的reason属性。

  @ResponseStatus(code=A,reason=B)标注在 @RequestMapping方法上,作用效果与 response.sendError(A,B)是一样的,所以需要慎用 reason 属性。

二、@ResponseStatus的注意事项

1、当@ResponseStatus用在方法上,如果添加了reason属性,且reason不为"",且code > 0(哪怕状态码是200),会对当前请求走错误处理。

@RequestMapping("/test")
@ResponseStatus(reason="ok",code=HttpStatus.OK)
public String test() {
    return "test";
}

  原因:org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod 类中,设置返回状态。

  io.undertow.servlet.handlers.ServletInitialHandler 类中,判断错误码。

2、返回状态码的其他翻案:返回状态码也可通过modelAndView.setStatus()实现

@RequestMapping(value = { "/test" }, method = RequestMethod.GET)
public ModelAndView test() {
  ModelAndView modelAndView = new ModelAndView();
  modelAndView.setViewName("test");
  modelAndView.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
  return modelAndView;
}

以上来源于这三篇文章的学习笔记:

https://www.cnblogs.com/lvbinbin2yujie/p/10575101.html

https://blog.csdn.net/Thinkingcao/article/details/110875494

https://blog.csdn.net/jumpe_17/article/details/118196644

标签:ResponseStatus,RequestMapping,自定义,浅析,Response,reason,注意事项,public
来源: https://www.cnblogs.com/goloving/p/15046737.html

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

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

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

ICode9版权所有