spring項目《接口響應體格式統一封裝》

前言
在之前的文章中我們有介紹過,如何更好、更簡單的寫好一個接口(接口返回值篇),今天的這篇文章我們主要介紹,怎麼統一處理下接口的返回格式問題。
問題分析
我們先來分析下我們所面臨的問題在哪裏,然後接着給出解決方案。在寫一個接口時,我們通常會先統一定義一下接口的返回格式是什麼,然後在跟前端去對接,通常的返回格式大體兩種(我們以保存用戶爲例):
1. 成功/失敗響應格式不一致(此種方式作爲我們默認的接口響應方式)

保存用戶成功,響應體

{
    "id": 10000,
    "pwd": "123456",
    "nickname": "小竹馬",
    "img": "http://avatar.csdn.net/0/E/9/1_aiyaya_.jpg",
    "status": "NORMAL",
    "createTime": 1515075974540
}
12345678

失敗響應體(下面的格式是spring boot默認的錯誤響應格式,只不過我們在其基礎上增加了一個code字段用於解釋更詳細的錯誤碼)

{
    "status": 400,
    "error": "Bad Request",
    "message": "參數無效",
    "code": 10001,
    "path": "/zhuma-demo/users",
    "exception": "org.springframework.web.bind.MethodArgumentNotValidException",
    "errors": [
        {
            "fieldName": "status",
            "message": "值是無效的"
        }
    ],
    "timestamp": 1515076067369
}
123456789101112131415
2.成功/失敗響應體格式一致

保存用戶成功,響應體

{
    "code": 1,
    "msg": "成功",
    "data": {
        "id": 10000,
        "pwd": "123456",
        "nickname": "小竹馬",
        "img": "http://avatar.csdn.net/0/E/9/1_aiyaya_.jpg",
        "status": "NORMAL",
        "createTime": 1515076287882
    }
}
123456789101112

失敗響應體

{
    "code": 10001,
    "msg": "參數無效",
    "data": [
        {
            "fieldName": "status",
            "message": "值是無效的"
        }
    ]
}
12345678910
那麼如果我們想要的響應體格式是第二種,我們該如何寫我們的代碼呢?你可能想是這樣麼?
@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public PlatformResult addUser(@Validated @RequestBody User user) {
        user.setId(10000L);
        user.setCreateTime(new Date());
        return PlatformResult.success(user);
    }

}
12345678910111213
PlatformResult.success()這段邏輯顯然很多餘,每個方法都要這樣寫一遍,所以上述方式並不是我們想要的,我們要的是
@ResponseResult(PlatformResult.class)
@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public User addUser(@Validated @RequestBody User user) {
        user.setId(10000L);
        user.setCreateTime(new Date());
        return user;
    }

}
1234567891011121314
我們加了一個自定義的註解@ResponseResult(PlatformResult.class),參數PlatformResult.class告訴這個Controller類下的所有方法都以這個類PlatformResult的格式進行返回,這個註解可以標記在類或方法上,好了,我們的目的明朗了許多,要做的就是標記這個註解讓它實現接口返回值格式控制這個功能,下面我們給出具體的實現方式。
實現思路
首先介紹下完成我們這次主要功能的幾個類:

Result 是返回格式類的父接口(所有返回格式類都需要繼承它)
PlatformResult 通用返回結果格式(我們上面說的第二種返回結果)
DefaultErrorResult 全局錯誤返回結果(我們上面說的第一種錯誤時的返回結果)
GlobalExceptionHandler全局異常處理
ResponseResult 註解類(用於在Controller上指定返回值格式類)
ResponseResultInterceptor 攔截器(主要用於將ResponseResult註解類的標記信息傳入ResponseResultHandler中)
ResponseResultHandler 響應體格式處理器(主要轉換邏輯都在這裏)

代碼實現
下面將有一大片代碼襲來,要頂住!O(∩_∩)O哈哈~
1. Result 接口類
package com.zhuma.demo.comm.result;

import java.io.Serializable;

/**
 * @desc 響應格式父接口
 *
 * @author zhumaer
 * @since 4/1/2018 3:00 PM
 */
public interface Result extends Serializable {
}

12345678910111213
說明
理論上所有的返回格式類都需要實現該接口才能被使用
2. PlatformResult 通用返回結果
package com.zhuma.demo.comm.result;

import com.zhuma.demo.enums.ResultCode;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @desc 平臺通用返回結果
 * 
 * @author zhumaer
 * @since 10/9/2017 3:00 PM
 */
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class PlatformResult implements Result {

    private static final long serialVersionUID = 874200365941306385L;

    private Integer code;

    private String msg;

    private Object data;

    public static PlatformResult success() {
        PlatformResult result = new PlatformResult();
        result.setResultCode(ResultCode.SUCCESS);
        return result;
    }

    public static PlatformResult success(Object data) {
        PlatformResult result = new PlatformResult();
        result.setResultCode(ResultCode.SUCCESS);
        result.setData(data);
        return result;
    }

    public static PlatformResult failure(ResultCode resultCode) {
        PlatformResult result = new PlatformResult();
        result.setResultCode(resultCode);
        return result;
    }

    public static PlatformResult failure(ResultCode resultCode, Object data) {
        PlatformResult result = new PlatformResult();
        result.setResultCode(resultCode);
        result.setData(data);
        return result;
    }

    public static PlatformResult failure(String message) {
        PlatformResult result = new PlatformResult();
        result.setCode(ResultCode.PARAM_IS_INVALID.code());
        result.setMsg(message);
        return result;
    }

    private void setResultCode(ResultCode code) {
        this.code = code.code();
        this.msg = code.message();
    }

}

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
3. DefaultErrorResult 默認全局錯誤返回格式
package com.zhuma.demo.comm.result;

import java.util.Date;

import com.zhuma.demo.enums.ExceptionEnum;
import com.zhuma.demo.exception.BusinessException;
import com.zhuma.demo.util.RequestContextHolderUtil;
import com.zhuma.demo.util.StringUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.autoconfigure.web.DefaultErrorAttributes;

import com.zhuma.demo.enums.ResultCode;
import org.springframework.http.HttpStatus;

/**
 * @desc 默認全局錯誤返回結果
 *       備註:該返回信息是spring boot的默認異常時返回結果{@link DefaultErrorAttributes},目前也是我們服務的默認的錯誤返回結果
 * 
 * @author zhumaer
 * @since 9/29/2017 3:00 PM
 */
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class DefaultErrorResult implements Result {

    private static final long serialVersionUID = 1899083570489722793L;

    /**
     * HTTP響應狀態碼 {@link org.springframework.http.HttpStatus}
     */
    private Integer status;

    /**
     * HTTP響應狀態碼的英文提示
     */
    private String error;

    /**
     * 異常堆棧的精簡信息
     * 
     */
    private String message;

    /**
     * 我們系統內部自定義的返回值編碼,{@link ResultCode} 它是對錯誤更加詳細的編碼
     * 
     * 備註:spring boot默認返回異常時,該字段爲null
     */
    private Integer code;

    /**
     * 調用接口路徑
     */
    private String path;

    /**
     * 異常的名字
     */
    private String exception;

    /**
     * 異常的錯誤傳遞的數據
     */
    private Object errors;

    /**
     * 時間戳
     */
    private Date timestamp;

    public static DefaultErrorResult failure(ResultCode resultCode, Throwable e, HttpStatus httpStatus, Object errors) {
        DefaultErrorResult result = DefaultErrorResult.failure(resultCode, e, httpStatus);
        result.setErrors(errors);
        return result;
    }

    public static DefaultErrorResult failure(ResultCode resultCode, Throwable e, HttpStatus httpStatus) {
        DefaultErrorResult result = new DefaultErrorResult();
        result.setCode(resultCode.code());
        result.setMessage(resultCode.message());
        result.setStatus(httpStatus.value());
        result.setError(httpStatus.getReasonPhrase());
        result.setException(e.getClass().getName());
        result.setPath(RequestContextHolderUtil.getRequest().getRequestURI());
        result.setTimestamp(new Date());
        return result;
    }

    public static DefaultErrorResult failure(BusinessException e) {
        ExceptionEnum ee = ExceptionEnum.getByEClass(e.getClass());
        if (ee != null) {
            return DefaultErrorResult.failure(ee.getResultCode(), e, ee.getHttpStatus(), e.getData());
        }

        DefaultErrorResult defaultErrorResult = DefaultErrorResult.failure(e.getResultCode() == null ? ResultCode.SUCCESS : e.getResultCode(), e, HttpStatus.OK, e.getData());
        if (StringUtil.isNotEmpty(e.getMessage())) {
            defaultErrorResult.setMessage(e.getMessage());
        }
        return defaultErrorResult;
    }

}

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
4. GlobalExceptionHandler 全局錯誤異常處理器
package com.zhuma.demo.handler;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;

import com.zhuma.demo.comm.handler.BaseGlobalExceptionHandler;
import com.zhuma.demo.comm.result.DefaultErrorResult;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.zhuma.demo.exception.BusinessException;

/**
 * @desc 統一異常處理器
 * 
 * @author zhumaer
 * @since 8/31/2017 3:00 PM
 */
@RestController
@ControllerAdvice
public class GlobalExceptionHandler extends BaseGlobalExceptionHandler {

    /* 處理400類異常 */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(ConstraintViolationException.class)
    public DefaultErrorResult handleConstraintViolationException(ConstraintViolationException e, HttpServletRequest request) {
        return super.handleConstraintViolationException(e, request);
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public DefaultErrorResult handleConstraintViolationException(HttpMessageNotReadableException e, HttpServletRequest request) {
        return super.handleConstraintViolationException(e, request);
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(BindException.class)
    public DefaultErrorResult handleBindException(BindException e, HttpServletRequest request) {
        return super.handleBindException(e, request);
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public DefaultErrorResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
        return super.handleMethodArgumentNotValidException(e, request);
    }

    /* 處理自定義異常 */
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<DefaultErrorResult> handleBusinessException(BusinessException e, HttpServletRequest request) {
        return super.handleBusinessException(e, request);
    }

    /** 處理運行時異常 */
    @Override
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Throwable.class)
    public DefaultErrorResult handleThrowable(Throwable e, HttpServletRequest request) {
        //TODO 可通過郵件、微信公衆號等方式發送信息至開發人員、記錄存檔等操作
        return super.handleThrowable(e, request);
    }
    
}

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
BaseGlobalExceptionHandler 全局異常處理基礎類
package com.zhuma.demo.comm.handler;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;

import com.zhuma.demo.comm.result.DefaultErrorResult;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;

import com.zhuma.demo.comm.result.ParameterInvalidItem;
import com.zhuma.demo.enums.ResultCode;
import com.zhuma.demo.exception.BusinessException;
import com.zhuma.demo.util.ConvertUtil;

/**
 * @desc 全局異常處理基礎類
 * 
 * @author zhumaer
 * @since 10/10/2017 9:54 AM
 */
@Slf4j
public class BaseGlobalExceptionHandler {

    /**
     * 違反約束異常
     */
    protected DefaultErrorResult handleConstraintViolationException(ConstraintViolationException e, HttpServletRequest request) {
        log.info("handleConstraintViolationException start, uri:{}, caused by: ", request.getRequestURI(), e);
        List<ParameterInvalidItem> parameterInvalidItemList = ConvertUtil.convertCVSetToParameterInvalidItemList(e.getConstraintViolations());
        return DefaultErrorResult.failure(ResultCode.PARAM_IS_INVALID, e, HttpStatus.BAD_REQUEST, parameterInvalidItemList);
    }

    /**
     * 處理驗證參數封裝錯誤時異常
     */
    protected DefaultErrorResult handleConstraintViolationException(HttpMessageNotReadableException e, HttpServletRequest request) {
        log.info("handleConstraintViolationException start, uri:{}, caused by: ", request.getRequestURI(), e);
        return DefaultErrorResult.failure(ResultCode.PARAM_IS_INVALID, e, HttpStatus.BAD_REQUEST);
    }

    /**
     * 處理參數綁定時異常(反400錯誤碼)
     */
    protected DefaultErrorResult handleBindException(BindException e, HttpServletRequest request) {
        log.info("handleBindException start, uri:{}, caused by: ", request.getRequestURI(), e);
        List<ParameterInvalidItem> parameterInvalidItemList = ConvertUtil.convertBindingResultToMapParameterInvalidItemList(e.getBindingResult());
        return DefaultErrorResult.failure(ResultCode.PARAM_IS_INVALID, e, HttpStatus.BAD_REQUEST, parameterInvalidItemList);
    }

    /**
     * 處理使用@Validated註解時,參數驗證錯誤異常(反400錯誤碼)
     */
    protected DefaultErrorResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
        log.info("handleMethodArgumentNotValidException start, uri:{}, caused by: ", request.getRequestURI(), e);
        List<ParameterInvalidItem> parameterInvalidItemList = ConvertUtil.convertBindingResultToMapParameterInvalidItemList(e.getBindingResult());
        return DefaultErrorResult.failure(ResultCode.PARAM_IS_INVALID, e, HttpStatus.BAD_REQUEST, parameterInvalidItemList);
    }

    /**
     * 處理通用自定義業務異常
     */
    protected ResponseEntity<DefaultErrorResult> handleBusinessException(BusinessException e, HttpServletRequest request) {
        log.info("handleBusinessException start, uri:{}, exception:{}, caused by: {}", request.getRequestURI(), e.getClass(), e.getMessage());

        DefaultErrorResult defaultErrorResult = DefaultErrorResult.failure(e);
        return ResponseEntity
                .status(HttpStatus.valueOf(defaultErrorResult.getStatus()))
                .body(defaultErrorResult);
    }

    /**
     * 處理運行時系統異常(反500錯誤碼)
     */
    protected DefaultErrorResult handleRuntimeException(RuntimeException e, HttpServletRequest request) {
        log.error("handleRuntimeException start, uri:{}, caused by: ", request.getRequestURI(), e);
        return DefaultErrorResult.failure(ResultCode.SYSTEM_INNER_ERROR, e, HttpStatus.INTERNAL_SERVER_ERROR);
    }

}

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
說明
上面用到了一些自定義異常基類(BusinessException),對於這個類它會有很多子類去繼承它,例如:
參數異常、數據已存在異常、無權限異常等等,這些類我們會在後面的文章給大家分享下
5. ResponseResult 註解類
package com.zhuma.demo.annotation;

import com.zhuma.demo.comm.result.PlatformResult;
import com.zhuma.demo.comm.result.Result;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @desc 接口返回結果增強  會通過攔截器攔截後放入標記,在ResponseResultHandler 進行結果處理
 *
 * @author zhumaer
 * @since 4/1/2018 3:00 PM
 */
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseResult {

    Class<? extends Result>  value() default PlatformResult.class;

}

1234567891011121314151617181920212223242526
說明
這裏我們默認PlatformResult使用這個類作爲返回格式,所以@ResponseResult 等價於@ResponseResult(PlatformResult.class)
6. ResponseResultInterceptor 攔截器
package com.zhuma.demo.interceptor;

import com.zhuma.demo.annotation.ResponseResult;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;


/**
 * @desc 接口響應體控制攔截器
 * 
 * @author zhumaer
 * @since 4/1/2018 3:00 PM
 */
@Component
public class ResponseResultInterceptor implements HandlerInterceptor {

    public static final String RESPONSE_RESULT = "RESPONSE-RESULT";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            final HandlerMethod handlerMethod = (HandlerMethod) handler;
            final Class<?> clazz = handlerMethod.getBeanType();
            final Method method = handlerMethod.getMethod();
            if (clazz.isAnnotationPresent(ResponseResult.class)) {
                request.setAttribute(RESPONSE_RESULT, clazz.getAnnotation(ResponseResult.class));
            } else if (method.isAnnotationPresent(ResponseResult.class)) {
                request.setAttribute(RESPONSE_RESULT, method.getAnnotation(ResponseResult.class));
            }
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // nothing to do
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // nothing to do
    }

}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
開啓攔截器
package com.zhuma.demo.config.web;

import com.zhuma.demo.interceptor.ResponseResultInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private ResponseResultInterceptor responseResultInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        String apiUri = "/**";
        //響應結果控制攔截
        registry.addInterceptor(responseResultInterceptor).addPathPatterns(apiUri);
    }

}

1234567891011121314151617181920212223
7. ResponseResultHandler 響應體格式處理器
package com.zhuma.demo.handler;

import com.zhuma.demo.annotation.ResponseResult;
import com.zhuma.demo.comm.result.DefaultErrorResult;
import com.zhuma.demo.comm.result.Result;
import com.zhuma.demo.interceptor.ResponseResultInterceptor;
import com.zhuma.demo.util.RequestContextHolderUtil;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import com.zhuma.demo.comm.result.PlatformResult;

/**
 * @desc 接口響應體處理器
 * 
 * @author zhumaer
 * @since 4/1/2018 3:00 PM
 */
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        HttpServletRequest request = RequestContextUtil.getRequest();
        ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(ResponseResultInterceptor.RESPONSE_RESULT);
        return responseResultAnn != null && !ApiStyleEnum.NONE.name().equalsIgnoreCase(request.getHeader(HeaderConstants.API_STYLE));
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        ResponseResult responseResultAnn = (ResponseResult) RequestContextHolderUtil.getRequest().getAttribute(ResponseResultInterceptor.RESPONSE_RESULT);

        Class<? extends Result> resultClazz = responseResultAnn.value();

        if (resultClazz.isAssignableFrom(PlatformResult.class)) {
            if (body instanceof DefaultErrorResult) {
                DefaultErrorResult defaultErrorResult = (DefaultErrorResult) body;
                return PlatformResult.builder()
                        .code(Integer.valueOf(defaultErrorResult.getCode()))
                        .msg(defaultErrorResult.getMessage())
                        .data(defaultErrorResult.getErrors())
                        .build();
            } else if (body instanceof String) {
                return JsonUtil.object2Json(PlatformResult.success(body));
            }

            return PlatformResult.success(body);
        }

        return body;
    }

}

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
說明

上述代碼用到了一個工具類(RequestContextHolderUtil)用於獲取request對象,如果感興趣可以看下這篇文章 工具類分享之《RequestContextHolderUtil》
@ControllerAdvice、ResponseBodyAdvice這兩個類是本功能的關鍵使用類,用於接口的響應體增強,其中supports方法用於判斷是否需要做增強轉化,beforeBodyWrite方法用於增加邏輯實現
supports方法中,加了個小功能,當調用人員不想要封裝結果時,可以在header上設置參數Api-Style=none

最後我們寫一個創建用戶的Controller層方法:
package com.zhuma.demo.web.user;

import java.util.Date;

import com.zhuma.demo.annotation.ResponseResult;
import com.zhuma.demo.comm.result.DefaultErrorResult;
import com.zhuma.demo.comm.result.PlatformResult;
import com.zhuma.demo.comm.result.Result;
import com.zhuma.demo.exception.BusinessException;
import com.zhuma.demo.exception.UserNotLoginException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.zhuma.demo.model.po.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @desc 用戶管理控制器
 * 
 * @author zhumaer
 * @since 6/20/2017 16:37 PM
 */
@ResponseResult
@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public User addUser(@Validated @RequestBody User user) {
        user.setId(10000L);
        user.setCreateTime(new Date());
        return user;
    }

}
12345678910111213141516171819202122232425262728293031323334353637383940414243
結束語
接口響應體統一格式轉化,這個功能解說完啦,因爲本次貼出來的基本算是完整的代碼,如果你能看完也真心不容易,哈哈,哪裏不懂的可以直接留言或關注微信公衆號,來和我一起討論吧O(∩_∩)O~
源碼github地址:https://github.com/zhumaer/zhuma
--------------------- 
作者:築碼-井哥 
來源:CSDN 
原文:https://blog.csdn.net/aiyaya_/article/details/78976759 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章