spring統一返回處理和統一異常處理


使用場景

我們在編寫代碼時候,可能需要給前端一個相對統一的格式,所以經常用一個Result類來封裝結果。

    @GetMapping("result")
    public Result get1() {
        return Result.success(new Person("tom"));
    }

采用以下方式處理,就不用每次調用Result.success方法了

使用方法

1、定義注解,組合@ResponseBody


@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@ResponseBody//繼承
public @interface ResponseResultBody {

}

2、實現ResponseBodyAdvice接口
這里也包含了統一異常處理

import com.lexiaoyao.controlleradvice_.annos.ResponseResultBody;
import com.lexiaoyao.controlleradvice_.model.Result;
import com.lexiaoyao.controlleradvice_.model.ResultException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.annotation.Annotation;

@RestControllerAdvice
@Slf4j
public class ResponseResultBodyAdvice implements ResponseBodyAdvice<Object> {

    private static final Class<? extends Annotation> ANNOTATION_TYPE = ResponseResultBody.class;

    /**
     * 判斷類或者方法是否使用了 @ResponseResultBody
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ANNOTATION_TYPE) || returnType.hasMethodAnnotation(ANNOTATION_TYPE);
    }

    /**
     * 當類或者方法使用了 @ResponseResultBody 就會調用這個方法
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        // 防止重復包裹的問題出現
        if (body instanceof Result) {
            return body;
        }
        return Result.success(body);
    }

    /**
     * 提供對標准Spring MVC異常的處理
     *
     * @param ex the target exception
     */
    @ExceptionHandler(Exception.class)
    public final ResponseEntity<Result<?>> exceptionHandler(Exception ex) {
        log.error("ExceptionHandler: {}", ex.getMessage());
        HttpHeaders headers = new HttpHeaders();
        if (ex instanceof ResultException) {
            return this.handleResultException((ResultException) ex, headers);
        }
        // TODO: 這里可以自定義其他的異常攔截
        return this.handleException(ex, headers);
    }

    /**
     * 對ResultException類返回返回結果的處理
     */
    private ResponseEntity<Result<?>> handleResultException(ResultException ex, HttpHeaders headers) {
        Result<?> body = Result.failure(ex.getResultStatus());
        HttpStatus status = ex.getResultStatus().getHttpStatus();
        return this.handleExceptionInternal(ex, body, headers, status);
    }

    /**
     * 異常類的統一處理
     */
    private ResponseEntity<Result<?>> handleException(Exception ex, HttpHeaders headers) {
        Result<?> body = Result.failure();
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        return this.handleExceptionInternal(ex, body, headers, status);
    }

    private ResponseEntity<Result<?>> handleExceptionInternal(
            Exception ex, Result<?> body, HttpHeaders headers, HttpStatus status) {
        return new ResponseEntity<>(body, headers, status);
    }

}

3、在需要包裝的controller上加上注解


@RestController
@ResponseResultBody//自定義的統一處理注解
public class AppController {

    /**
     * 會被自動包裝為result
     *
     * @return
     */
    @GetMapping
    public Person get() {
        return new Person("tom");
    }

    @GetMapping("result")
    public Result get1() {
        return Result.success(new Person("tom"));
    }

    @PostMapping
    public void post() {
        throw new ResultException(ResultStatus.INTERNAL_SERVER_ERROR);
    }

}

git

https://github.com/lexiaoyao1995/springreturn


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM