spring mvc环境之异常错误码的统一返回(十五)
1.根据不同的请求方式,返回页面或json数据
1).创建统一权限异常处理类,所有的权限异常走一个端口
2).根据请求方式不同返回不同数据,页面请求返回403未授权页面,ajax请求返回json数据
package com.cc8w.exception; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.json.MappingJackson2JsonView; import javax.servlet.http.HttpServletRequest; @ControllerAdvice public class MyExceptionAdvice { @ExceptionHandler(Exception.class) public ModelAndView showInfoE(Exception e, HttpServletRequest request){ if (isAjaxRequest(request)) { ModelAndView modelAndView=new ModelAndView(new MappingJackson2JsonView()); modelAndView.addObject(AjaxResult.authError("错误1")); return modelAndView; //return new ModelAndView(AjaxResult.authError("您没有权限查看该数据").toString()); } else { return new ModelAndView("error1"); } } /** * 是否是Ajax异步请求 * @param request */ public static boolean isAjaxRequest(HttpServletRequest request) { String accept = request.getHeader("accept"); if (accept != null && accept.indexOf("application/json") != -1) { return true; } String xRequestedWith = request.getHeader("X-Requested-With"); if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) { return true; } String uri = request.getRequestURI(); if (isContainStrs(uri, ".json", ".xml")) { return true; } String ajax = request.getParameter("__ajax"); if (isContainStrs(ajax, "json", "xml")) { return true; } return false; } public static boolean isContainStrs(String str, String... strs) { if (str != null && strs != null) { for (String s : strs) { if (str.equalsIgnoreCase(s.trim())) { return true; } } } return false; } }
其中:AjaxResult.authError是系统自定义的json通用返回对象,包含code、msg、data等通用字段自己可以自定义设置。
主要涉及到ModelAndView、MappingJackson2JsonView 通过传入的类型来控制是页面ORjson字符串
2.返回统一的数据结果
1).统一返回结果
所有的接口均返回 ResultDto 类型的数据,ResultDto 类的代码如下,主要有 4 个字段
- success:表示接口是成功还是失败
- code:错误码,当有异常的时候,可以返回具体的错误码
- msg:提示信息,比如:操作成功、用户名有误、密码有误等等
- data:类型是一个泛型,表示任意类型,这个用来存放接口中具体返回的数据,可以是任意类型的对象
还提供了几个静态方法,方便创建 ResultDto 对象
/** * rest接口通用返回值数据结构 * * @param <T> */ public class ResultDto<T> { //接口状态(成功还是失败) private Boolean success; //错误码 private String code; //提示信息 private String msg; //数据 private T data; public Boolean getSuccess() { return success; } public void setSuccess(Boolean success) { this.success = success; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } public static <T> ResultDto<T> success(T data) { return success(data, "操作成功!"); } public static <T> ResultDto<T> success(T data, String msg) { ResultDto<T> result = new ResultDto<>(); result.setSuccess(Boolean.TRUE); result.setMsg(msg); result.setData(data); return result; } public static <T> ResultDto<T> error(String msg) { return error(null,msg); } public static <T> ResultDto<T> error(String code,String msg) { return error(code,msg,null); } public static <T> ResultDto<T> error(String code, String msg, T data) { ResultDto<T> result = new ResultDto<>(); result.setSuccess(Boolean.FALSE); result.setCode(code); result.setMsg(msg); result.setData(data); return result; } }
2).统一异常处理
异常处理这块,我们的设计主要有 2 点,通过这 2 点来解决异常处理的问题
第一点:定义一个基础的业务异常类(BusException),业务代码中手动抛出异常的时候,统一抛出这种类型的异常,异常类型中可以携带更详细的错误信息,比如错误码、提示信息、扩展数据等等
第 二 点:采用 springmvc 全局来处理异常,控制器中不要捕获异常,将一次交给 springmvc 框架来统一处理。
业务异常类:BusException
代码比较简单,主要有 2 个属性和几个静态方法
- code:异常错误码,最终会丢给 ResultDto 的 code 属性输出到客户端
- data:异常的时候,可以传递一些扩展信息,此时可以丢到 data 中,最终会丢给 ResultDto 的 data 属性输出到客户端
- 提供了几个静态方法,便于抛出 BusException 异常
- 当我们的业务代码中需要抛出异常的时候,要求均抛出 BusException 类型的异常
/** * 业务异常 */ public class BusException extends RuntimeException { //异常错误码 private String code; //错误扩展信息 private Object data; public BusException(String msg) { this(null, msg); } public BusException(String code, String msg) { this(code, msg, null); } public BusException(String code, String msg, Object data) { super(msg); this.code = code; this.data = data; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public static void throwBusException(String msg) { throwBusException(null, msg); } public static void throwBusException(String code, String msg) { throwBusException(code, msg, null); } public static void throwBusException(String code, String msg, Object data) { throw new BusException(code, msg, data); } }
3).全局异常统一处理类:GlobalExceptionHandle
如下代码,大家对 springmvc 统一异常处理不了解,建议先看一下上一篇文章。
注意下面代码中的@1,这里使用到了@RestControllerAdvice,他和@ControllerAdvice 功能类似,只是这个注解内部定义的时候上面多了一个@ResponseBody 注解,表示下面这个类中处理异常的方法返回值最终都会以 json 格式输出到客户端
/** * 全局异常处理 */ @RestControllerAdvice // @1 public class GlobalExceptionHandle { /** * 统一处理业务异常 * * @param e * @param <T> * @return */ @ExceptionHandler(BusException.class) public <T> ResultDto<T> doBusException(BusException e) { //1、记录错误日志 //2、返回结果 return ResultDto.error(e.getCode(), e.getMessage(), (T) e.getData()); } /** * 处理其他异常 * * @param e * @param <T> * @return */ @ExceptionHandler public <T> ResultDto<T> doException(Exception e) { //1、记录错误日志 //2、返回结果 return ResultDto.error("系统异常,请联系管理员,错误详情:" + e.getMessage()); } }
4).示例:
如下代码,注意两点信息
内部提供了 2 个接口,接口的返回值都是 ResultDto 类型的
代码中,没有了 try catch,而是将异常类型封装为 BusException 类型抛出,比如验证码有误,会抛出了 BusException,顺便携带了错误码和错误提示信息,这些都会通过全局异常的处理,输出到客户端
@RestController @RequestMapping("/user") public class UserController { /** * 获取用户id * * @param code * @return */ @RequestMapping("/getUserName") public ResultDto<String> getUserName(@RequestParam("code") Integer code) { if (!Integer.valueOf(6666).equals(code)) { //验证码有误的时候,返回4001错误码 BusException.throwBusException("4001", "验证码有误!"); } return ResultDto.success("路人"); } /** * 获取用户id * * @param code * @return */ @RequestMapping("/getUserId") public ResultDto<String> getUserId(@RequestParam("code") Integer code) { if (!Integer.valueOf(6666).equals(code)) { BusException.throwBusException("4001", "验证码有误!"); } return ResultDto.success("8888"); } }
https://blog.csdn.net/zhangzengxiu/article/details/121622103
https://blog.csdn.net/m0_46991388/article/details/115611438
https://www.jb51.net/article/196535.htm
转:
https://blog.csdn.net/butioy_org/article/details/78718405
https://blog.csdn.net/s1040342522/article/details/123545878
https://www.cnblogs.com/chenzhubing/p/11438902.html
https://blog.csdn.net/weixin_56644618/article/details/127580941