前言:
  最近使用springmvc写了不少rest api, 觉得真是一个好框架. 之前描述的几篇关于rest api的文章, 其实还是不够完善. 比如当遇到参数缺失, 类型不匹配的情况时, 直接抛出异常, 返回的内容是400+的错误页面, 而不是json内容, 这让移动端的调用方很难处理.
  本文主要讲述对于rest api, springmvc对异常的解决处理方案.

系列整理:
  springmvc学习笔记系列的文章目录:
  • idea创建springmvc项目
  • 面向移动端的REST API
  • Jackson的使用和定制
  REST API的设计原则博文
  • 移动互联网实战—Web Restful API设计和基础架构

场景构造:
  大背景, 我们已借助使用Jackson框架和注解@ResonseBody来实现pojo对象以json形式返回.
  先来构造几个案例, 来描述我们所要解决的问题.
  共同的测试代码:

@Controller
@RequestMapping("/math")
public class TestController { @RequestMapping(value="/div", method= RequestMethod.GET)
@ResponseBody
public int div(@RequestParam("a") int a,
@RequestParam("b") int b) {
// *) div zero error
return a / b;
} }

  1). 场景一(参数缺失, 类型不匹配)
  case 1:
    http://localhost:8080/math/div?a=10
  参数b缺失, 返回400错误页
  
  case 2:
    http://localhost:8080/math/div?a=10&b=hehe
  参数b类型不对, 类型转换失败
  
  我们的希望是, 将这些参数缺少/类型不匹配的异常, 以JSON串的形式返回, 而不是以400的错误页面返回.
  2). 场景二(业务代码抛出异常)
  case 1:
    http://localhost:8080/math/div/a=10&b=0
  发生除零异常
  
  内部抛出业务异常非常常见, 防不胜防, 返回是500+的错误页面.

解决方案:
  基于上文的场景, 遇到异常时, 返回的都是400+/500+的错误页面, 一方面客户端sdk解析和处理麻烦, 另一方面泄露了内部的错误细节. 那是否一种办法拦截异常, 并返回自己定义的错误数据格式呢?
  答案是肯定的, springmvc引入了织入@ControlAdvice.
  其对异常的处理, 非常的方便, 可简单参考如下sample.

@ControllerAdvice
public class RestApiControlAdvice { @ExceptionHandler(value=RuntimeException.class)
@ResponseBody
public String handle(RuntimeException e) {
// *记入异常日志
return e.getMessage();
} @ExceptionHandler(value=Exception.class)
@ResponseBody
public String handle(Exception e) {
// *记入异常日志
return e.getMessage(); } }

  通过结合注解@ExceptionHanlder, 来定义具体的异常处理, 以及返回的结果.
  这边需要注意的是, @ExceptionHandler可定义多个, 当多个匹配时, 按编写最早的处理函数优先处理. 这边就像try/catch那种常见的情况了, 既顺序敏感. 最佳实践, 需要把处于顶层的异常类搁置到代码最尾端.
  当然对于参数缺失/类型不匹配的处理, 可以如下定义.

@ExceptionHandler(value=MissingServletRequestParameterException.class)
@ResponseBody
public TResult<Void> handle(MissingServletRequestParameterException e) {
return "Miss parameter " + e.getParameterName() + ":" + e.getParameterType();
} @ExceptionHandler(value= TypeMismatchException.class)
@ResponseBody
public String handle(TypeMismatchException e) {
return e.getErrorCode() + ", required type: " + e.getRequiredType() + ", but value: " + e.getValue();
}

  业务上的异常代码, 往往可以抽象出一个异常基类.

总结:
  springmvc的入门和上手确实非常快, 但要真正的理解. 确实还是需要花功夫, 这边只是简单介绍一下, 并没有深入源码. 希望将来有一天有机会讲讲背后的技术原理.

公众号&游戏站点:
  个人微信公众号: 木目的H5游戏世界
  
  个人游戏作品集站点, www.mmxfgame.com,  请点击访问http://120.26.221.54/.

springmvc学习笔记--REST API的异常处理的更多相关文章

  1. springmvc学习笔记---面向移动端支持REST API

    前言: springmvc对注解的支持非常灵活和飘逸, 也得web编程少了以往很大一坨配置项. 另一方面移动互联网的到来, 使得REST API变得流行, 甚至成为主流. 因此我们来关注下spring ...

  2. 史上最全的SpringMVC学习笔记

    SpringMVC学习笔记---- 一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于Spring ...

  3. SpringMVC:学习笔记(8)——文件上传

    SpringMVC--文件上传 说明: 文件上传的途径 文件上传主要有两种方式: 1.使用Apache Commons FileUpload元件. 2.利用Servlet3.0及其更高版本的内置支持. ...

  4. springmvc学习笔记(简介及使用)

    springmvc学习笔记(简介及使用) 工作之余, 回顾了一下springmvc的相关内容, 这次也为后面复习什么的做个标记, 也希望能与大家交流学习, 通过回帖留言等方式表达自己的观点或学习心得. ...

  5. springmvc学习笔记(常用注解)

    springmvc学习笔记(常用注解) 1. @Controller @Controller注解用于表示一个类的实例是页面控制器(后面都将称为控制器). 使用@Controller注解定义的控制器有如 ...

  6. SpringMVC学习笔记之二(SpringMVC高级参数绑定)

    一.高级参数绑定 1.1 绑定数组 需求:在商品列表页面选中多个商品,然后删除. 需求分析:功能要求商品列表页面中的每个商品前有一个checkbok,选中多个商品后点击删除按钮把商品id传递给Cont ...

  7. springmvc学习笔记(19)-RESTful支持

    springmvc学习笔记(19)-RESTful支持 标签: springmvc springmvc学习笔记19-RESTful支持 概念 REST的样例 controller REST方法的前端控 ...

  8. springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定

    springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定 标签: springmvc springmvc学习笔记13-springmvc注解开发之集合类型參数绑定 数组绑定 需 ...

  9. springMVC 学习笔记(一):springMVC 入门

    springMVC 学习笔记(一):spring 入门 什么是 springMVC springMVC 是 spring 框架的一个模块,springMVC 和 spring 无需通过中间整合层进行整 ...

随机推荐

  1. USB鼠标按键驱动

    现象:把USB设备接到PC 1. 右下角弹出"发现android phone" 2. 跳出一个对话框,提示你安装驱动程序 问1. 既然还没有"驱动程序",为何能 ...

  2. IDEA调试javaScript

            谈起JavaScript调试,大家可能想到的就是FireFox下的FireBug,这毫无疑问,FireBug基本已经成为JavaScript开发人员的必备工具.在本文中,将向大家介绍如 ...

  3. html中offsetTop、clientTop、scrollTop、offsetTop

    HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth scrollHeight: 获取对象的滚动高度. scrollLeft:设置或获取位于对 ...

  4. Eclipse版本及其代号

    1.维基百科介绍 http://zh.wikipedia.org/wiki/Eclipse 2.版本及其代号

  5. Android文件Apk下载变ZIP压缩包

    在azure云存储中 上传apk文件 使用ie下载 变成zip压缩包 解决方法 编辑 blob 属性和元数据 修改 内容类型 为 application/vnd.android.package-arc ...

  6. php 未配置curl

    用到PHP的curl功能,发现服务器上的PHP并没有配置curl,进而查询PHP官方文档,得知编译PHP时需要带上 –with-curl参数,才能把curl模块编译进去.我现在PHP已经编译安装进服务 ...

  7. 数组的filter方法

    filter()函数用于过滤序列,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素. eg: var arr=[10,11,12,13,14 ...

  8. HTML--4格式布局

    一.position:fixed 锁定位置(相对于浏览器的位置),例如有些网站的右下角的弹出窗口. 示例: 二.position:absolute 1.外层没有position:absolute(或r ...

  9. UIControlEvents 中各种event被触发的方式解释(zz)

    转自:http://blog.csdn.net/yanxiaoqing/article/details/7108891 在控件事件中,简单解释下下面几个事件.说明:由于是在“iOS 模拟器”中测试的, ...

  10. jsCodeWar 多函数嵌套调用

    function compose(f, g) { return function() { return f(g.apply(this, arguments)); }; } --- function c ...