开发辅助六(实现统一数据返回格式+统一异常处理+统一日志处理)

统一返回格式

一、添加枚举类

public enum ResultCodeEnum{
	
	SUCCESS(true,20000,"成功"),
	UNKNOWN_REASON(false,20001,"未知错误");

	private final Boolean success;
	private final Inteer code;
	private final String message;

	ResultCodeEnum(Boolean success,Integer code,String message){
		this.success = success;
        this.code = code;
        this.message = message;
	}

	 public Boolean getSuccess() {
        return success;
    }
 
    public Integer getCode() {
        return code;
    }
 
    public String getMessage() {
        return message;
    }
 
    @Override
    public String toString() {
        return "ResultCodeEnum{" + "success=" + success + ", code=" + code + ", message='" + message + '\'' + '}';
    }
}

二、添加统一返回格式的类

该类是用来和前端交互的类

public class R{
	
	private Boolean success;
	private Integer code;
	private String message;

	private Map<String,Object> data = new HashMap<>();
	public R(){
		
	}

	public static R ok(){
		R r = new R();
		r.setSuccess(ResultCodeEnum.SUCCESS.getSuccess());
        r.setCode(ResultCodeEnum.SUCCESS.getCode());
        r.setMessage(ResultCodeEnum.SUCCESS.getMessage());
        return r;
	}

	public static R error() {
        R r = new R();
        r.setSuccess(ResultCodeEnum.UNKNOWN_REASON.getSuccess());
        r.setCode(ResultCodeEnum.UNKNOWN_REASON.getCode());
        r.setMessage(ResultCodeEnum.UNKNOWN_REASON.getMessage());
        return r;
    }
 
    public static R setResult(ResultCodeEnum resultCodeEnum) {
        R r = new R();
        r.setSuccess(resultCodeEnum.getSuccess());
        r.setCode(resultCodeEnum.getCode());
        r.setMessage(resultCodeEnum.getMessage());
        return r;
    }

	 public R success(Boolean success) {
        this.setSuccess(success);
        return this;
    }
 
    public R message(String message) {
        this.setMessage(message);
        return this;
    }
 
    public R code(Integer code) {
        this.setCode(code);
        return this;
    }
 
    public R data(String key, Object value) {
        this.data.put(key, value);
        return this;
    }
 
    public R data(Map<String, Object> map) {
        this.setData(map);
        return this;
    }
 
    /** 以下是get/set方法,如果项目有集成lombok可以使用@Data注解代替 */
 
    public Boolean getSuccess() {
        return success;
    }
 
    public void setSuccess(Boolean success) {
        this.success = success;
    }
 
    public Integer getCode() {
        return code;
    }
 
    public void setCode(Integer code) {
        this.code = code;
    }
 
    public String getMessage() {
        return message;
    }
 
    public void setMessage(String message) {
        this.message = message;
    }
 
    public Map<String, Object> getData() {
        return data;
    }
 
    public void setData(Map<String, Object> data) {
        this.data = data;
    }
}

三、测试

@RestController
@RequestMapping("testR")
public class TestController{
	
	@GetMapping("ok")
	public R testOk(){
		Map<String, Object> data = new HashMap<>();
        data.put("name", "李太白");
        return R.ok().data(data);
	}
}

开发辅助六(实现统一数据返回格式+统一异常处理+统一日志处理)_第1张图片

异常效果:
开发辅助六(实现统一数据返回格式+统一异常处理+统一日志处理)_第2张图片
开发辅助六(实现统一数据返回格式+统一异常处理+统一日志处理)_第3张图片

统一异常处理

一、添加统一异常处理器(创建一个handler包,在该包下面添加GlobalExceptionHandler类)

@ControllerAdvice
public class GlobalExceptionHnadler{
	
	@ResponseBody
	@ExceptionHandler(Exception.class)
	public R exception(Exception e){
		e.printStackTrace();
		return R.error();
	}
}

开发辅助六(实现统一数据返回格式+统一异常处理+统一日志处理)_第4张图片

二、添加自定义异常(新建exception包,在该包下添加自定义异常类)

public class TestException extends RuntimeException{
	
	private Integer code;
	public TestException(ResultCodeEnum resultCodeEnum){
		// 调用父类的方法添加信息
        super(resultCodeEnum.getMessage());
        this.code = resultCodeEnum.getCode();
	}

	public Integer getCode() {
        return code;
    }
}

在统一异常处理类GlobalExceptionHandler中添加一个自定义异常的处理

@ControllerAdvice
public class GlobalExceptionHandler {
 
    /**
     * 使用ExceptionHandler注解声明处理Exception异常
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public R exception(Exception e) {
        // 控制台打印异常
        e.printStackTrace();
        // 返回错误格式信息
        return R.error();
    }
 
    /**
     * 使用ExceptionHandler注解声明处理TestException异常
     */
    @ResponseBody
    @ExceptionHandler(TestException.class)
    public R exception(TestException e) {
        // 控制台打印异常
        e.printStackTrace();
        // 返回错误格式信息
        return R.error().message(e.getMessage()).code(e.getCode());
    }
 
}

三、测试自定义异常
开发辅助六(实现统一数据返回格式+统一异常处理+统一日志处理)_第5张图片
开发辅助六(实现统一数据返回格式+统一异常处理+统一日志处理)_第6张图片

统一日志处理

一、添加日志配置文件

在resources下条件日志配置,文件名必须是logback-spring.xml
以下配置一般不需要修改,要改的话也只是修改日志的输出目录


<configuration  scan="true" scanPeriod="10 seconds">
    
    
    
    
    <contextName>logbackcontextName>
    
    <property name="log.path" value="D:/javaWeb/log" />
 
    
    
    
    
    
    
    <property name="CONSOLE_LOG_PATTERN"
              value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/>
 
    
    <property name="FILE_LOG_PATTERN"
              value="%date{yyyy-MM-dd HH:mm:ss} |%-5level |%thread |%file:%line |%logger |%msg%n" />
 
    
    <property name="ENCODING"
              value="UTF-8" />
 
    
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            
            <level>DEBUGlevel>
        filter>
        <encoder>
            
            <Pattern>${CONSOLE_LOG_PATTERN}Pattern>
            
            <charset>${ENCODING}charset>
        encoder>
    appender>
 
    
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFOlevel>
            <onMatch>ACCEPTonMatch>
            <onMismatch>DENYonMismatch>
        filter>
        
        <file>${log.path}/log_info.logfile>
        <encoder>
            <pattern>${FILE_LOG_PATTERN}pattern>
            <charset>${ENCODING}charset>
        encoder>
        
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            
            <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.logfileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>500MBmaxFileSize>
            timeBasedFileNamingAndTriggeringPolicy>
            
            <maxHistory>15maxHistory>
        rollingPolicy>
    appender>
 
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARNlevel>
            <onMatch>ACCEPTonMatch>
            <onMismatch>DENYonMismatch>
        filter>
        
        <file>${log.path}/log_warn.logfile>
        <encoder>
            <pattern>${FILE_LOG_PATTERN}pattern>
            <charset>${ENCODING}charset> 
        encoder>
        
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.logfileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MBmaxFileSize>
            timeBasedFileNamingAndTriggeringPolicy>
            
            <maxHistory>15maxHistory>
        rollingPolicy>
    appender>
 
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERRORlevel>
            <onMatch>ACCEPTonMatch>
            <onMismatch>DENYonMismatch>
        filter>
        
        <file>${log.path}/log_error.logfile>
        <encoder>
            <pattern>${FILE_LOG_PATTERN}pattern>
            <charset>${ENCODING}charset> 
        encoder>
        
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.logfileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MBmaxFileSize>
            timeBasedFileNamingAndTriggeringPolicy>
            
            <maxHistory>15maxHistory>
        rollingPolicy>
    appender>
 
    
    <springProfile name="dev">
        
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
        root>
    springProfile>
 
    
    <springProfile name="pro">
        <root level="ERROR">
            <appender-ref ref="ERROR_FILE" />
        root>
    springProfile>
 
configuration>

二、添加application.properties

配置文件需要设置下环境,需要跟日志配置文件中的对应上,不然不生效

# 设置环境
spring.profiles.active=dev

三、修改GlobalExceptionHandler类

@ControllerAdvice
public class GlobalExceptionHandler{
	
	private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

	@ResponseBody
	@ExceptionHandler(Exception.class)
	public R exception(Exception e){
		log.error(e.getMessage());//控制台打印异常
		return R.error();
	}

	@ResponseBody
	@ExceptionHandler(TestException.class)
	public R exception(TestException e){
		 // 控制台打印异常
        log.error(e.getMessage());
        // 返回错误格式信息
        return R.error().message(e.getMessage()).code(e.getCode());
	}
}

四、测试效果
开发辅助六(实现统一数据返回格式+统一异常处理+统一日志处理)_第7张图片
本地磁盘javaWeb目录下也有对应的日志文件了
开发辅助六(实现统一数据返回格式+统一异常处理+统一日志处理)_第8张图片

五、进一步完善,将日志堆栈信息输出到文件

①、定义工具类(新建utils包,在该包下添加ExceptionUtils类)

public class ExceptionUtils{
	
	public static String getMessage(Exception e){
		StringWriter sw = null;
		PrintWriter pw = null;

		try{
			sw = new StringWriter();
			pw = new PrintWriter(sw);

			//将出错的堆栈信息输出到printWriter
			e.printStackTrace(pw);
			pw.flush();
			sw.flush();
		}finally{
			if (sw != null) {
                try {
                    sw.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (pw != null) {
                pw.close();
            }
		}

		return sw.toString();
	}
}

②、再修改GlobalExceptionHandler类

@ControllerAdvice
public class GlobalExceptionHandler{
	
	private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

	@ResponseBody
	@ExceptionHandler(Exception.class)
	public R exception(Exception e){
		// 控制台打印异常  借助工具类将错误堆栈输出到文件
        log.error(ExceptionUtils.getMessage(e));
        // 返回错误格式信息
        return R.error();
	}

	@ResponseBody
    @ExceptionHandler(TestException.class)
    public R exception(TestException e) {
        // 控制台打印异常   借助工具类将错误堆栈输出到文件
        log.error(ExceptionUtils.getMessage(e));
        // 返回错误格式信息
        return R.error().message(e.getMessage()).code(e.getCode());
    }
}

开发辅助六(实现统一数据返回格式+统一异常处理+统一日志处理)_第9张图片

你可能感兴趣的:(统一数据返回格式,统一异常处理,统一日志处理)