现在项目都是前后端分离,前后端通过JSON交换数据,这时,后端就需要提供健全的api接口供前端调用。本文主要介绍自己封装的JsonResult与Spring Boot的统一异常处理,项目地址在这里。
JsonResult是自己封装的一个返还Json,主要由返还码、返还信息,以及返还数据构成,其中提供了静态方法success、failed可供controller层直接调用。废话不多说,直接上代码供大家参考。
package com.lm.common;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.io.Serializable;
import java.util.Objects;
/**
* @author [email protected]
* @date 18-11-7 下午12:25
*/
public class JsonResult implements Serializable {
private static final long serialVersionUID = 5598308977637490090L;
private int status;
private String message;
private Object data;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void setData(Object data) {
this.data = data;
}
public Object getData() {
return data;
}
public static JsonResult success() {
return success(null);
}
public static JsonResult success(Object data) {
JsonResult jsonResult = new JsonResult();
jsonResult.setStatus(200);
jsonResult.setMessage("SUCCESS");
if (data != null) {
jsonResult.setData(data);
}
return jsonResult;
}
public static JsonResult failed() {
return failed("FAILED");
}
public static JsonResult failed(String message) {
JsonResult jsonResult = new JsonResult();
jsonResult.setStatus(500);
jsonResult.setMessage(message);
return jsonResult;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof JsonResult)) {
return false;
}
JsonResult result = (JsonResult) o;
return status == result.status &&
Objects.equals(message, result.message) &&
Objects.equals(data, result.data);
}
@Override
public int hashCode() {
return Objects.hash(status, message, data);
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("status", status)
.append("message", message)
.append("data", data)
.toString();
}
}
以下就是一个模拟登录成功返还的Json信息.
{
"status":200,
"message":"SUCCESS",
"data":
{
"id":1,
"userName":"lmm",
"password":"123"
}
}
在前后端分离项目中,无论后台程序出现了什么问题,我们都要返还一个错误的Json信息。这个错误的信息可以包括错误码,错误信息等,这样不仅仅方便前端处理,也方便后期运维、开发人员快速的定位到错误。下面就是一个错误的Json信息。
{
"status":700,
"message":"用户不存在!",
"data":null
}
首先我们需要定义一个基本异常,它主要包包含错误码,错误信息。我们也可以在这个基本异常中预先定义一些异常如参数错误、没有权限等。
package com.lm.common;
/**
* @author [email protected]
* @date 18-11-7 上午11:46
*/
public class BaseException extends Exception {
private static final long serialVersionUID = -3392027101671055457L;
public static final int ERROR_CODE_ILLEGAL_ARGUMENTS = 600;
// 错误码
private int code;
//错误信息
private String errorMessage;
public BaseException(int code) {
super("error code" + code);
this.code = code;
}
public BaseException(int code, Throwable throwable) {
super(throwable);
this.code = code;
}
public BaseException(int code, String errorMessage) {
super(errorMessage);
this.code = code;
this.errorMessage = errorMessage;
}
public int getCode() {
return code;
}
public String getErrorMessage() {
return errorMessage;
}
}
一个系统由多个模块组成,每个模块中都可能会抛出各种各样的异常,这时我们就需要在模块中定义属于本模块中的异常,这些异常需继承BaseException。比如用户登录模块,可能就会抛出用户不存在、密码错误等异常,这时我们定义一个UserException异常,如下所示。
package com.lm.user;
import com.lm.common.BaseException;
/**
* @author [email protected]
* @date 18-11-7 上午11:53
*/
public class UserException extends BaseException {
public static final int ERROR_CODE_NOT_EXIT = 700;
public static final int ERROR_CODE_PASSWORD_EEEOR = 701;
public UserException(int code) {
super(code);
}
}
定义完异常后,我们需要对异常进行处理,这样后台抛出异常后,将直接返还错误Json。我们定义一个统一异常处理类(GlobalExceptionHandle),用@ControllerAdvice注解该类,用注解@ExceptionHandler来定义要处理的异常类型。用@ResponseBody来使返还的数据为Json格式。
package com.lm.dubboconsumer.common;
import com.google.gson.Gson;
import com.lm.common.BaseException;
import com.lm.common.JsonResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Locale;
/**
* @author [email protected]
* @date 18-11-7 下午12:17
*/
@ControllerAdvice
public class GlobalExceptionHandle {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandle.class);
private final MessageSource messageSource;
@Autowired
public GlobalExceptionHandle(MessageSource messageSource) {
this.messageSource = messageSource;
}
@ExceptionHandler(value = Exception.class)
@ResponseBody
public JsonResult defaultErrorHandle(HttpServletRequest request, HttpServletResponse response,
Exception e, Locale locale) throws IOException {
JsonResult result = new JsonResult();
int code = 500;
String errorMessage = null;
Throwable exception = e;
if (exception instanceof BaseException) {
code = ((BaseException) exception).getCode();
errorMessage = ((BaseException) exception).getErrorMessage();
} else if (exception instanceof MissingServletRequestParameterException) {
code = BaseException.ERROR_CODE_ILLEGAL_ARGUMENTS;
} else if (!(exception instanceof BaseException || exception instanceof MissingServletRequestParameterException)) {
LOGGER.error("Unknown Exception, URI = " + request.getRequestURI(), e);
} else {
LOGGER.error("URI = {}, errorCode = {}, errorMessage = {}", request.getRequestURI(), code, errorMessage);
}
// 如果异常中包含了错误信息,则不会通过错误码获取定义的错误信息
if (StringUtils.isBlank(errorMessage)) {
String prefix = exception.getClass().getSimpleName();
errorMessage = getMessage(prefix + "." + code, locale);
if (errorMessage == null) {
errorMessage = getMessage(Integer.toString(code), locale);
}
}
result.setStatus(code);
result.setMessage(errorMessage);
return result;
}
private String getMessage(String key, Locale locale) {
String errorMessage = null;
try {
errorMessage = messageSource.getMessage(key, null, locale);
} catch (NoSuchMessageException exception) {
LOGGER.debug("ErrorMessage|NotFound|{}", key);
}
return errorMessage;
}
}
我们前面定义的异常都是都是只定义了错误码,至于错误信息,我们可以在项目resource下建一个error_codes.properties文件,其中=前面是我们自定义异常中的code,而=号右边的就是错误信息了。
500=系统错误,请稍后重试!
600=参数错误!
700=用户不存在!
701=用户已经存在!
error_codes.properties文件创建完后,需要在aplication.yml(aplication.properties)中设置一下。
spring:
messages:
basename: error_codes
cache-duration: 600s
Service层
package com.lm.dubboprovider.user.impl;
import com.lm.common.BaseException;
import com.lm.user.User;
import com.lm.user.UserException;
import com.lm.user.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
/**
* @author [email protected]
* @date 18-11-4 下午2:55
*/
@Service
public class UserServiceImpl implements UserService {
private static final String USERNAME = "lm";
private static final String PASSWORD = "123";
@Override
public Boolean login(String userName, String password) throws BaseException {
if (StringUtils.isBlank(userName) || StringUtils.isBlank(password)) {
throw new BaseException(BaseException.ERROR_CODE_ILLEGAL_ARGUMENTS);
}
if (!userName.equals(USERNAME)) {
throw new UserException(UserException.ERROR_CODE_NOT_EXIT);
}
if (USERNAME.equals(userName) && PASSWORD.equals(password)) {
return true;
}
return false;
}
}
Controller层
package com.lm.dubboconsumer.user;
import com.lm.common.BaseException;
import com.lm.common.JsonResult;
import com.lm.user.User;
import com.lm.user.UserException;
import com.lm.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* @author [email protected]
* @date 18-11-5 下午5:10
*/
@RestController
@RequestMapping("user")
public class UserRestController {
private final UserService userService;
@Autowired
public UserRestController(UserService userService) {
this.userService = userService;
}
@GetMapping("login")
public JsonResult login(HttpServletRequest request) throws UserException, BaseException {
String userName = request.getParameter("username");
String password = request.getParameter("password");
Boolean flag = userService.login(userName, password);
if (flag) {
return JsonResult.success();
} else {
throw JsonResult.failed();
}
}
}
CSDN写博客一定要定时点击保存按钮。