范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

SpringbootAPI接口统一输出消息格式保持原接口返回值不变

  环境:Springboot2.4.11
  很多时候我们对接口的返回值都会做统一的处理,返回{code, message,data}等信息标识本次请求的处理结果,这统一的处理也都是在各自的Controller上做自行的处理。本篇内容告诉你如何通过ResponseBodyAdvice对象来实现对结果的统一处理,也就是说在Controller上我们不再对返回结果进行处理了,而是由统一的一个ControllerAdice Bean对象进行处理。这对我们的Controller接口来说可读性更强,也业务无关的东西一概不出现,同时代码也更加简洁。ResponseBodyAdvice是什么
  ResponseBodyAdvice类型的Bean对象允许在执行@ResponseBody或ResponseEntity控制器方法之后但在使用HttpMessageConverter写入正文之前自定义响应。实现可以直接向RequestMappingHandlerAdapter和ExceptionHandlerExceptionResolver注册,或者更可能使用@ControllerAdvice进行注释,在这种情况下,它们都将被自动检测到。定义统一返回对象public class R { 	   public R() {   }    private int code ; 	   private String message ; 	   private Object result ; 	   private String errorDetails ;    public R(int code, String message, Object result) {     super();     this.code = code;     this.message = message;     this.result = result;   } 	   public R(int code, String message, Object result, String errorDetails) {     super();     this.code = code;     this.message = message;     this.result = result;     this.errorDetails = errorDetails ;   }    public R(int code, String message, String errorDetails) {     super();     this.code = code;     this.message = message;     this.errorDetails = errorDetails ;   } 	   public R(int code, String message) {     super();     this.code = code;     this.message = message;   }   public static R success() {     return success(null) ;   } 	   public static R success(Object data) {     return success("成功", data) ;   } 	   public static R success(String message, Object data) {     return new R(ResultCode.SUCCESS, message, data) ;   } 	   public static R failure() {     return failure("失败") ;   } 	   public static R failure(Object data) {     return failure("失败", data) ;   } 	   public static R failure(String message) {     return failure(message, null) ;   }   public static R failure(int code, String message) {     return new R(code, message) ;   }      public static R failure(String message, Object data) {     return new R(ResultCode.FAILURE, message, data) ;   }   public static R failure(String message, String errorDetails) {     return new R(ResultCode.FAILURE, message, errorDetails) ;   } 	   public static R error(String message, String errorDetails) {     return new R(ResultCode.ERROR, message, errorDetails) ;   }   public static interface ResultCode {     int SUCCESS = 0 ;     int FAILURE = -1 ;     int ERROR = 500 ;   } }定义ResponseBodyAdvice@RestControllerAdvice public class ResponseResultControllerAdvice implements ResponseBodyAdvice {    @Override   public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {     return returnType.getParameterType() != Void.TYPE          && (!returnType.hasMethodAnnotation(NoPack.class)          && !returnType.getMethod().getDeclaringClass().isAnnotationPresent(NoPack.class)) ; 	}    @Override   public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,     Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {     if (body instanceof R) {       return body ;     }     return R.success(body) ;   }  }
  上面的类非常简单
  supports 方法判断当前的请求接口是否支持,在这里对于void,或是有@NoPack注解的都不进行处理。
  beforeBodyWrite 该方法判断如果返回值类型本身就是R类型就之间进行输出了,否则就进行包装处理。测试接口@GetMapping("/get1") public Users get1() {   Users users = new Users() ;   users.setAge(100) ;   return users ; }
  包装成功!!!
  修改测试接口
  在接口中抛出一个异常@GetMapping("/get1") public Users get1() {   Users users = new Users() ;   users.setAge(100) ;   System.out.println( 1 / 0 ) ;   return users ; }
  当有异常的时候并不能被处理,这里我们需要结合统一异常处理的机制。异常处理@RestControllerAdvice public class ExceptionControllerAdvice {    private static final Logger logger = LoggerFactory.getLogger(ExceptionControllerAdvice.class) ; 	   @ExceptionHandler(Exception.class)   public R jsonErrorHandler(HttpServletRequest req, Exception e){     String fullThrowMessage = getStackTrace(e);     if (e instanceof ServletRequestBindingException) {       return R.error("参数绑定异常,请检查接口入参: " + e.getMessage(), fullThrowMessage) ;     }     if (e instanceof ClassCastException) {       return R.error("请检查入参是否正确", fullThrowMessage) ;     }     if (e instanceof MethodArgumentNotValidException) {       return R.failure(((MethodArgumentNotValidException)e).getBindingResult().getAllErrors().stream().map(err -> err.getDefaultMessage()).collect(Collectors.toList())) ;     }     Throwable cause = e.getCause() ;     if (cause != null) {       if (cause instanceof SQLDataException) {         return R.error("数据格式错误,请检查入参是否正确", fullThrowMessage) ;       }       if (cause instanceof NumberFormatException) {         return R.error("数据格式错误,请检查!" + cause.getMessage(), fullThrowMessage) ;       }     }     logger.error("未捕获的异常:{}", e) ;     return R.error(e.getMessage(), fullThrowMessage) ;   }        private static String getStackTrace(final Throwable throwable) {     final StringWriter sw = new StringWriter();     final PrintWriter pw = new PrintWriter(sw, true);     throwable.printStackTrace(pw);     return sw.getBuffer().toString() ;   } }
  在Springboot中可以通过@RestControllerAdvice注解标识一个类,让其可以统一处理未捕获的异常。查看这篇文章《Spring MVC 异常处理方式》该篇文章详细的讲解了异常的处理。
  在进行测试
  对于异常也统一的处理了。实现原理
  在Spring MVC中返回值的处理都是由HandlerMethodReturnValueHandler对象进行处理的public abstract class AbstractMessageConverterMethodProcessor extends AbstractMessageConverterMethodArgumentResolver implements HandlerMethodReturnValueHandler {     protected  void writeWithMessageConverters(@Nullable T value, ...) {         // 根据当前的请求获取客户端能产生的响应类型         List producibleTypes = getProducibleMediaTypes(request, valueType, targetType);         // 遍历所有的HttpMessageConverter对象         for (HttpMessageConverter<?> converter : this.messageConverters) {             GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ?                                                             (GenericHttpMessageConverter<?>) converter : null);             if (genericConverter != null ?                 ((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) :                 converter.canWrite(valueType, selectedMediaType)) {                 // 在输出内容前先通过ResponseBodyAdvice处理内容信息                 body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,                                                    (Class<? extends HttpMessageConverter<?>>) converter.getClass(),                                                    inputMessage, outputMessage);                 if (body != null) {                     Object theBody = body;                     addContentDispositionHeader(inputMessage, outputMessage);                     if (genericConverter != null) {                         // ResponseBodyAdvice处理完后,最后通过GenericHttpMessageConverter输出内容到客户端了。                         // 后续就是处理其它的比如拦截器的afterCompletion方法等操作了。                         genericConverter.write(body, targetType, selectedMediaType, outputMessage);                     } else {                         ((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);                     }                 } else {                 }                 return;             }         }     } }
  完毕!!!
  求关注+转发
  公众:Springboot实战案例锦集
  SpringCloud Nacos 服务消费者
  SpringCloud Hystrix实现资源隔离应用
  SpringCloud zuul 动态网关配置
  SpringCloud Nacos 整合feign
  SpringCloud整合Seata实现分布式事务通过nacos实现注册和配置
  SpringCloud Zookeeper配置中心详解
  SpringCloud Zookeeper服务发现及负载均衡
  Springboot Security 基础应用 (1)
  SpringBoot中使用Cache及JSR107的使用
  Springboot项目使用docker部署
  sharding-jdbc oracle分表避坑
高精尖科技产品云集华为Mate20系列惊艳亮相珠海航展今天上午,第12届中国国际航空航天博览会(珠海航展)正式开幕,此次航展为大家带来了很多高精尖产品,首次实现陆海空天电的全覆盖。据了解,此次航展有40多个国家和地区的700多家展商参坐稳财富500强的京东,不止做技术这样简单!近日,在综合考量了全球范围内中国上市企业在过去一年的业绩和成就,财富中文网发布了最新的财富中国500强排行榜,京东排位第18名,领跑所有上榜的互联网企业。毋庸置疑,京东的快速发展与火了!菜鸟再次出手,世界的家具或将被中国承包!今天,菜鸟携家具出海!又一中国方案驶向全球!刚刚传来消息,继菜鸟打通中国与海外出海方案后,中国家具也乘着菜鸟之风走向了世界。要知道,家具这样的大家伙,在中国的大街小巷运转已经够呛了关爱父母健康,私人医生H1让这变得如此简单在过去的四十年间,中国完成了人口转变,在2000年进入老龄社会以后,不断提升的人口预期寿命和持续的低生育水平使得中国人口老龄化开始了加速的进程,应对老龄社会所面临的医疗长期照护压力通吃电商流媒体网游大数据华为云服务器傲视群雄当前云计算应用日趋火热,云计算所提供的大数据分析人工智能,乃至于物联网等全新的应用也已经成为用户所关注的热点。但是云计算的基础计算能力,却长期受到忽视。在云计算的虚拟系统中,网络的Mate力四射张云龙自爆是拍照狂魔!如今正值足球大战之际,足球也成为了最热门的话题,而说到演艺圈的明星,也有很多和足球有着深厚的渊源,比如说张云龙就是其中一个。在Mate力四射冠军时刻华为终端官方微博联合新浪体育官方阿里巴巴王矛AliOS让汽车进化出大脑7月27日,第二届中国汽车智能座舱论坛在广州举行,AliOS总经理王矛参加此次会议并做了主题演讲。他提出未来的方向应该是全车智能,是基于OS的融合智能,包括感知设备交互方式计算能力私人医生H1健康手机如何在生活中担任你的专属医生?当下我们生活在一个较好的时代,生活质量不断提高,大部分人越来越注重养生,随之崛起的养生行业可谓是风生水起,各种打着养生旗号的手环公众号APP等,充斥着我们的朋友圈,赚取了不少点击量原来小龙虾也能借钱,生鲜商家的福利来了小龙虾鲜嫩多汁,入味Q弹,北方称麻小,南方叫作口味虾,是全国人民都喜爱的生鲜美食。有数据显示,每年小龙虾的消耗近百万吨,是吃货吃出的一个千亿市场!这让无数商家忧也愁,小龙虾本来是时7nm麒麟980实力碾压10nm骁龙845,Mate20下月首发2018年下半年,芯片行业即将迎来全新7nm制程工艺,打头阵的无疑是移动芯片。此前苹果华为高通的旗舰芯片都是采用10nm工艺,而目前华为手机领先一步发布的华为麒麟980,采用台积电暗光样张佐证华为P20系列堪称夜神之眼在手机硬件性能飞速发展的今天,人们对于手机拍照功能的要求同样日新月异,白天或许每款旗舰机型的差距不大,但在暗光情形下大部分手机的拍照短板就暴露出来。弱光下拍摄本就是一件极具挑战的事
如何借助互联网的技术,帮助企业增长获客?网络营销作为时下最热门的营销方式,网络营销方法很多,最常见的主要有以下几种1论坛营销(bbs营销)论坛营销可以成为支持整个网站推广的主要渠道,尤其是在网站刚开始的时候,是个很好的推手机炒股和电脑炒股的区别有哪些?我是一个高频交易者,个人认为最大的区别是手机炒股几乎每次报单你都难获取更全面的市场同步信息,每次买卖你都会有细小的价差损失,久而久之可能就是你投资生涯的全部利润。如果你是一个深入研很多人都在手机背面放了一张钱,大家知道是什么意义吗?自从发生那一件事之后,我朋友再也不在手机后面放钱了!以前我朋友,经常在手机背面放一张一百的,平铺着,我看到了,还问他你放一百块钱在手机后面干啥?他说玩呗,他感觉好看!有一天,他儿子液晶电视取消关机按钮,只能用遥控器调到待机状态,调到待机状态对电视好吗?你好我是小书修电器,下面回答关于你的问题液晶电视取消关机按钮,只能用遥控器调到待机状态,调到待机状态对电视好吗?目前国内智能液晶电视厂家大多数把简洁作为设计元素,现在目前也是主流设明知道月球不能居住,人类为什么花费大量人力物力去探索?人类为了探索宇宙,必须循环渐近。月球距离地球最近,人类要向外太空发展,那就要依月球为基地。一步步向前迈进。人类进驻月球,需要很多科学知识。能登上月球也就解决向宇宙迈出第一步。这一步iPhone6s用什么版本的系统最好?目前苹果iOS最高的正式版固件为iOS11。3,最高的测试版固件为iOS11。4beta1,至于iPhone6s用哪个系统版本好,这个确实无法定义,因为根据苹果历来iOS固件版本的杨利伟降落地球后,为何再也没重返太空?杨利伟1965年出生,2003年乘坐神舟五号进入太空时已经38岁了,或许很多人觉得他年龄太大身体素质跟不上才没重返太空,其实并不是这样。中国宇航员第一次进入太空的平均年龄都将近40从地球到达金星只需100天,为何人类放弃登陆金星?人类没有放弃金星,只是根据目前的探测结果,金星上的环境太过于恶劣。金星和地球一样,都是太阳系中的行星之一,从地球上看金星,它就是天空中最亮的那颗星星。基于目前人类对金星探测了解,金如果地球和太阳距离缩短1000公里,地球会发生什么变化?人类会灭亡吗?假如地球和太阳间的距离缩短1000公里,地球基本上不会受到任何影响,人类更不可能出现灭亡的情况。如果学习过开普勒定律的话,那我们应该知道任何行星围绕太阳的公转轨道都会是一个椭圆形,如何看待曾仕强,他是反科学者还是得道高人?曾仕强是1934年出生在中国福建人,被称为中国管理教育之父。台湾多所大学教授。改革开放后多次往返大陆与台湾进行中国传统文化,易经等中国历史文化经典。用自己的研究与专研。写出了许多文国内三大品牌手机商,华为ViVOOPPO,哪一款科技领先?百度了一下,所有手机厂商基本都是组装!从主板,处理器,摄像头,屏幕,内存,听筒,送话器,外壳,到里面小小螺丝钉。甚至连手机保护套,钢化膜,也不是纯自己生产的!就是说,都是全世界到处