参考博客:服务器端返回统一格式的数据 相关博客:SpringBoot 统一页面异常处理
第一步:创建项目 Maven依赖
org.projectlombok
lombok
1.18.10
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-web
org.slf4j
slf4j-log4j12
1.7.30
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
application.yml
server:
port: 80
servlet:
context-path: /tye
log4j.properties
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
第二步:创建封装统一返回数据的类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private int code;
private String msg;
private T data;
public Result(int code, String msg) {
this.code = code;
this.msg = msg;
}
public Result(ResultCode resultCode) {
this.code = resultCode.getCode();
this.msg = resultCode.getMsg();
}
}
第三步:结果工具类
public class ResultUtil {
/**
* 操作成功,只返回结果码和提示信息
*
* @param resultCode
* @return
*/
public static Result success(ResultCode resultCode) {
return new Result(ResultCode.SUCCESS);
}
/**
* 操作成功,只返回结果码和具体的数据,但不返回提示信息
*
* @return
*/
public static Result success(int code, String msg) {
return new Result(code, msg);
}
/**
* 操作成功,返回具体的数据、结果码和提示信息
*
* @param data
* @return
*/
public static Result success(Object data) {
Result result = new Result(ResultCode.SUCCESS);
result.setData(data);
return result;
}
/**
* 操作成功,返回具体的数据、结果码和提示信息
*
* @param code
* @param msg
* @param data
* @return
*/
public static Result success(Integer code, String msg, Object data) {
return new Result(code,msg,data);
}
/**
* 操作成功,只返回结果码和提示信息
*
* @param resultCode
* @return
*/
public static Result fail(ResultCode resultCode) {
return new Result(ResultCode.FAIL);
}
/**
* 操作失败,只返回指定的结果码和具体的数据,但不返回提示信息
*
* @return
*/
public static Result fail(int code, String msg) {
return new Result(code, msg);
}
/**
* 操作失败,返回具体的数据、结果码和提示信息
*
* @param data
* @return
*/
public static Result fail(Object data) {
Result result = new Result(ResultCode.FAIL);
result.setData(data);
return result;
}
/**
* 操作失败,返回具体的数据、结果码和提示信息
*
* @param code
* @param msg
* @param data
* @return
*/
public static Result fail(Integer code, String msg, Object data) {
return new Result(code,msg,data);
}
}
第四步:结果枚举类
public enum ResultCode {
/* 成功状态码 */
SUCCESS(0,"操作成功!"),
/* 错误状态码 */
FAIL(-1,"操作失败!"),
/* 参数错误:10001-19999 */
PARAM_IS_INVALID(10001, "参数无效"),
/* 用户错误:20001-29999*/
USER_NOT_LOGGED_IN(20001, "用户未登录,请先登录"),
/* 系统错误:40001-49999 */
SYSTEM_INNER_ERROR(40001, "系统繁忙,请稍后重试"),
/* 权限错误:70001-79999 */
PERMISSION_TOKEN_EXPIRED(70004, "token已过期"),
PERMISSION_TOKEN_INVALID(70006, "无效token"),
PERMISSION_SIGNATURE_ERROR(70007, "签名失败");
//操作代码
int code;
//提示信息
String msg;
ResultCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
第五步:自定义异常
public class CustomException extends RuntimeException {
//错误代码
private ResultCode resultCode;
public CustomException(ResultCode resultCode){
super(resultCode.getMsg());
this.resultCode = resultCode;
}
public CustomException(ResultCode resultCode, Object... args){
super(resultCode.getMsg());
String message = MessageFormat.format(resultCode.getMsg(), args);
resultCode.setMsg(message);
this.resultCode = resultCode;
}
public ResultCode getResultCode(){
return resultCode;
}
}
第六步:统一异常处理类
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 处理自定义异常
*/
@ExceptionHandler(CustomException.class)
public Result handleException(CustomException e) {
// 打印异常信息
log.error("### 异常信息:{} ###", e.getMessage());
return new Result(e.getResultCode());
}
/**
* 处理所有不可知的异常
*/
@ExceptionHandler(Exception.class)
public Result handleOtherException(Exception e){
//打印异常堆栈信息
e.printStackTrace();
// 打印异常信息
log.error("### 不可知的异常:{} ###", e.getMessage());
return new Result(ResultCode.SYSTEM_INNER_ERROR);
}
}
第七步:Controller
@RestController
@RequestMapping("/demo")
public class DemoController {
/**
* 异常处理测试
*/
@RequestMapping("/test")
@ResponseBody
public String test(int num, String name) throws Exception {
System.out.println(num + "\t" + name);
if (num == 4) {
throw new CustomException(ResultCode.FAIL);
}
if (name == null) {
throw new Exception("字段空值");
}
return "index";
}
}
测试
http://localhost/tye/demo/test?num=fdsfds