最近写代码的时候,遇到一个问题:


框架遇到异常后会返回一个 JSON 格式的数据,如:{"msg":"id不存在","code":"1001"}
为了方便前端统一处理,正常情况的 Controller 返回值也要是这个格式。但要考虑各种情况的异常信息,Service 类就也要返回这个格式的类。
问题示例代码如下:Controller 类

package blog.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;
import blog.service.UserService;
/** * 用户信息管理 * @author ConstXiong * @date 2020-04-26 20:49:02 */@Controller@RequestMapping("/user")public class UserController {
 @Autowired  private UserService userService;
 /**   * 保存用户电话   * @param id   * @param tel   * @return   */  @RequestMapping("saveUserTel")  @ResponseBody  public Map<String, Object> saveUserTel(Integer id, String tel) {    return userService.saveUserTel(id, tel);  }
}



Service 类

package blog.service;
import java.util.HashMap;import java.util.Map;
import org.springframework.stereotype.Service;import org.springframework.util.StringUtils;
/** * 用户信息管理服务类 * @author ConstXiong * @date 2020-04-26 10:52:58 */@Servicepublic class UserService {
 /**   * 保存用户电话信息   * @param id   * @param tel   */  public Map<String, Object> saveUserTel(int id, String tel) {    Map<String, Object> result = new HashMap<String, Object>();    //校验id是否存在    if (id < 1) {      result.put("code", "1001");//假设 id 不能为空的 错误码是1001      result.put("msg", "id不存在");      return result;    }    if (StringUtils.isEmpty(tel)) {      result.put("code", "1002");//假设  tel 为空的 错误码是1002      result.put("msg", "电话不能为空");      return result;    }    if (tel.length() > 11) {      result.put("code", "1003");//假设  tel 长度超过11 错误码1003      result.put("msg", "电话号码超长");      return result;    }    result.put("code", "0");//保存成功的错误    result.put("msg", "保存成功");    return result;  }
}



请求url返回如下:

http://localhost:8081/blog/user/saveUserTel.do?id=-1&tel=13888888888{"msg":"id不存在","code":"1001"}
http://localhost:8081/blog/user/saveUserTel.do?id=1&tel=138888888888{"msg":"电话号码超长","code":"1003"}
http://localhost:8081/blog/user/saveUserTel.do?id=1&tel=13888888888{"msg":"保存成功","code":"0"}



Service 类中存在这 2 个问题:

  1. saveUserTel(int id, String tel) 方法返回一个 boolean 类型的值表示保存成功或保存失败更容易理解,但这样就无法返回异常信息。
  2. 在实际开发中 saveUserTel(int id, String tel) 这类处理业务逻辑的方法,代码都比较复杂,以这种方式写,到后期阅读这段代码就比较困难,可维护性也差。



那如何解决这些问题呢?
@ControllerAdvice 是 spring web 中的一个注解,作用是对 Controller 进行增加,我们可以使用这个注解进行全局的异常处理。
通过 @ControllerAdvice 进行整改,是一种方式。
代码如下:
1、新增自定义异常

package blog.exception;
/** * 自定义异常 * @author ConstXiong * @date 2020-04-27 10:19:15 */public class CustomException extends RuntimeException {
 private static final long serialVersionUID = 675600741944661752L;
 private String code;
 public CustomException(String code, String msg) {    super(msg);    this.code = code;  }
 public String getCode() {    return code;  }}


2、新增自定义异常处理类

package blog.handler;
import java.util.HashMap;import java.util.Map;
import org.springframework.http.HttpStatus;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.ResponseStatus;
import blog.exception.CustomException;
/** * 全局异常处理,捕获所有Controller中抛出的异常。 */@ControllerAdvicepublic class GlobalExceptionHandler {
 @ExceptionHandler(CustomException.class)  @ResponseBody  @ResponseStatus(HttpStatus.OK)  public Map<String, Object> handleCustomException (CustomException e) throws Exception {    Map<String, Object> error = new HashMap<String, Object>();    error.put("code", e.getCode());    error.put("msg", e.getMessage());    return error;  }
}


3、新增信息校验类 Checker

package blog.service;
import org.springframework.util.StringUtils;
import blog.exception.CustomException;
/** * 信息校验类 * @author ConstXiong * @date 2020-04-26 20:28:41 */public class Checker {
 /**   * 必须大于等于某值   * @param num   * @param min   * @param errCode   * @param errMsg   */  public static void mustLargerThan(int num, int min, String errCode, String errMsg) {    if (num < min) {      throw new CustomException(errCode, errMsg);    }  }
 /**   * 不能为空   * @param str   * @param errCode   * @param errMsg   */  public static void mustNotEmpy(String str, String errCode, String errMsg) {    if (StringUtils.isEmpty(str)) {      throw new CustomException(errCode, errMsg);    }  }
 /**   * 字符串长度不能超过   * @param str   * @param len   * @param errCode   * @param errMsg   */  public static void lengthNoLongerThan(String str, int len, String errCode, String errMsg) {    if (str.length() > len) {      throw new CustomException(errCode, errMsg);    }  }
}



4、整改 Controller 和 Service 类的代码

package blog.controller;
import java.util.HashMap;import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;
import blog.service.UserService;
/** * 用户信息管理 * @author ConstXiong * @date 2020-04-26 20:49:02 */@Controller@RequestMapping("/user")public class UserController {
 @Autowired  private UserService userService;
 /**   * 保存用户电话   * @param id   * @param tel   * @return   */  @RequestMapping("saveUserTel")  @ResponseBody  public Map<String, Object> saveUserTel(Integer id, String tel) {    userService.saveUserTel(id, tel);
   //success 可以放到常量类里定义    Map<String, Object> success = new HashMap<String, Object>();    success.put("code", "0");    success.put("msg", "保存成功");
   return success;  }
}



package blog.service;
import org.springframework.stereotype.Service;
/** * 用户信息管理服务类 * @author ConstXiong * @date 2020-04-26 10:52:58 */@Servicepublic class UserService {
 /**   * 保存用户电话信息   * @param id   * @param tel   */  public boolean saveUserTel(int id, String tel) {    Checker.mustLargerThan(id, 0, "1001", "id不存在");    Checker.mustNotEmpy(tel, "1002", "电话不能为空");    Checker.lengthNoLongerThan(tel, 11, "1003",  "电话号码超长");    return true;  }
}


整改完之后,请求 url 返回与之前相同。

总结一下这样处理的好处:

  1. Service 类不需要返回 Controller 返回的数据结构,只关注自己的逻辑与返回值,提高公共可用性
  2. 统一处理了异常返回信息
  3. 可以抽象出公共的校验信息



PS:

  • Controller 里的 success 可以放到系统常量里直接返回,不用每次都 new
  • 错误码和错误信息根据业务系统需求,进行常量定义
  • 还可以通过 SpringMVC 中的 HandlerInterceptor 实现


更多相关文章

  1. JY06用户组权限管理
  2. 图书管理系统【用户、购买、订单模块、添加权限】
  3. 用户登陆注册【JDBC版】
  4. 69.批量创建mysql用户
  5. 如何检测用户有关退出页面的信息?
  6. 如何在用户选择操作后获取当前日期和时间
  7. Google地图信息窗口左箭头,右箭头传递TypeError:无法读取未定义的
  8. jquery 鼠标悬停显示信息提示框
  9. 谷歌地图信息窗口按钮没有显示?

随机推荐

  1. python新式类删改查
  2. [LeetCode] 244. Shortest Word Distance
  3. 解决SimpleCV的Hello World程序无法显示
  4. Python 2.6.2中的ElementTree处理指令支
  5. 向军laravel和vuejs webAPP实战开发
  6. 在Python中使用正则表达式匹配的字符串周
  7. Python——域名解析成IP地址
  8. 使用python实现一个简单的学生信息管理系
  9. 饮冰三年-人工智能-Python-22 Python初识
  10. 使用Python操作Redis