前言

在之前的文章中我们有介绍过,如何更好、更简单的写好一个接口《接口返回值》,今天的这篇文章我们主要介绍,怎么统一处理下接口的返回格式问题。

SpringBoot实战 - 接口响应体统一封装

问题分析

我们先来分析下我们所面临的问题在哪里,然后接着给出解决方案。在写一个接口时,我们通常会先统一定义一下接口的返回格式是什么,然后在跟前端去对接,通常的返回格式大体两种(我们以保存用户为例):

1.成功/失败响应格式不一致(此种方式作为我们默认的接口响应方式)

保存用户成功,响应体:

  1. {
  2. "id": 10000,
  3. "pwd": "123123",
  4. "nickname": "nickname1",
  5. "img": "http://xxx.com/1.png",
  6. "status": "NORMAL",
  7. "createTime": 1517762718278
  8. }

失败响应体(下面的格式是 spring boot 默认的错误响应格式,只不过我们在其基础上增加了一个 code 字段用于解释更详细的错误码)

  1. {
  2. "status": 400,
  3. "error": "Bad Request",
  4. "message": "参数无效",
  5. "code": 10001,
  6. "path": "/user",
  7. "exception": "org.springframework.web.bind.MethodArgumentNotValidException",
  8. "errors": [
  9. {
  10. "fieldName": "status",
  11. "message": "值是无效的"
  12. }
  13. ],
  14. "timestamp": 1515076067369
  15. }

2.成功/失败响应体格式一致

保存用户成功,响应体:

  1. {
  2. "code": 1,
  3. "msg": "成功",
  4. "data": {
  5. "id": 10000,
  6. "pwd": "123123",
  7. "nickname": "nickname1",
  8. "img": "http://xxx.com/1.png",
  9. "status": "NORMAL",
  10. "createTime": 1515076287882
  11. }
  12. }

失败响应体:

  1. {
  2. "code": 10001,
  3. "msg": "参数无效",
  4. "data": [
  5. {
  6. "fieldName": "status",
  7. "message": "值是无效的"
  8. }
  9. ]
  10. }

那么如果我们想要的响应体格式是第二种,我们该如何写我们的代码呢?你可能想是这样么?

  1. @RestController
  2. @RequestMapping("/user")
  3. public class UserController {
  4. @PostMapping
  5. @ResponseStatus(HttpStatus.CREATED)
  6. public PlatformResult addUser(@Validated @RequestBody User user) {
  7. user.setId("10000");
  8. user.setCreateTime(new Date());
  9. return PlatformResult.success(user);
  10. }
  11. }

PlatformResult.success() 这段逻辑显然很多余,每个方法都要这样写一遍,所以上述方式并不是我们想要的,我们要的是

  1. @ResponseResult(PlatformResult.class)
  2. @RestController
  3. @RequestMapping("/users")
  4. public class UserController {
  5. @PostMapping
  6. @ResponseStatus(HttpStatus.CREATED)
  7. public User addUser(@Validated @RequestBody User user) {
  8. user.setId("10000");
  9. user.setCreateTime(new Date());
  10. return user;
  11. }
  12. }

我们加了一个自定义的注解 @ResponseResult(PlatformResult.class),参数 PlatformResult.class 告诉这个 Controller 类下的所有方法都以这个类 PlatformResult 的格式进行返回,这个注解可以标记在类或方法上,好了,我们的目的明朗了许多,要做的就是标记这个注解让它实现接口返回值格式控制这个功能,下面我们给出具体的实现方式。

实现思路

首先介绍下完成我们这次主要功能的几个类:

Result 是返回格式类的父接口(所有返回格式类都需要继承它)

PlatformResult 通用返回结果格式(我们上面说的第二种返回结果)

DefaultErrorResult 全局错误返回结果(我们上面说的第一种错误时的返回结果)

GlobalExceptionHandler 全局异常处理

ResponseResult 注解类(用于在Controller上指定返回值格式类)

ResponseResultInterceptor 拦截器(主要用于将 ResponseResult 注解类的标记信息传入 ResponseResultHandler 中)

ResponseResultHandler 响应体格式处理器(主要转换逻辑都在这里)

代码实现

下面将有一大片代码袭来,要顶住!哈哈~

Result 接口类

  1. package cn.notemi.demo.result;
  2. import java.io.Serializable;
  3. /**
  4. * @desc 响应格式父接口
  5. */
  6. public interface Result extends Serializable {
  7. }

说明

理论上所有的返回格式类都需要实现该接口才能被使用

PlatformResult 通用返回结果

  1. package cn.notemi.demo.result;
  2. import cn.notemi.demo.enums.ResultCode;
  3. import lombok.AllArgsConstructor;
  4. import lombok.Builder;
  5. import lombok.Data;
  6. import lombok.NoArgsConstructor;
  7. /**
  8. * @desc 平台通用返回结果
  9. */
  10. @Builder
  11. @NoArgsConstructor
  12. @AllArgsConstructor
  13. @Data
  14. public class PlatformResult implements Result {
  15. private static final long serialVersionUID = 874200365941306385L;
  16. private Integer code;
  17. private String msg;
  18. private Object data;
  19. public static PlatformResult success() {
  20. PlatformResult result = new PlatformResult();
  21. result.setResultCode(ResultCode.SUCCESS);
  22. return result;
  23. }
  24. public static PlatformResult success(Object data) {
  25. PlatformResult result = new PlatformResult();
  26. result.setResultCode(ResultCode.SUCCESS);
  27. result.setData(data);
  28. return result;
  29. }
  30. public static PlatformResult failure(ResultCode resultCode) {
  31. PlatformResult result = new PlatformResult();
  32. result.setResultCode(resultCode);
  33. return result;
  34. }
  35. public static PlatformResult failure(ResultCode resultCode, Object data) {
  36. PlatformResult result = new PlatformResult();
  37. result.setResultCode(resultCode);
  38. result.setData(data);
  39. return result;
  40. }
  41. public static PlatformResult failure(String message) {
  42. PlatformResult result = new PlatformResult();
  43. result.setCode(ResultCode.PARAM_IS_INVALID.code());
  44. result.setMsg(message);
  45. return result;
  46. }
  47. private void setResultCode(ResultCode code) {
  48. this.code = code.code();
  49. this.msg = code.message();
  50. }
  51. }

DefaultErrorResult 默认全局错误返回格式

  1. package cn.notemi.demo.result;
  2. import cn.notemi.demo.enums.BusinessExceptionEnum;
  3. import cn.notemi.demo.enums.ResultCode;
  4. import cn.notemi.demo.exceptions.BusinessException;
  5. import cn.notemi.demo.util.RequestContextUtil;
  6. import cn.notemi.demo.util.StringUtil;
  7. import lombok.AllArgsConstructor;
  8. import lombok.Builder;
  9. import lombok.Data;
  10. import lombok.NoArgsConstructor;
  11. import org.springframework.http.HttpStatus;
  12. import java.util.Date;
  13. /**
  14. * @desc 默认全局错误返回结果
  15. * 备注:该返回信息是spring boot的默认异常时返回结果,目前也是我们服务的默认返回结果
  16. */
  17. @Builder
  18. @AllArgsConstructor
  19. @NoArgsConstructor
  20. @Data
  21. public class DefaultErrorResult implements Result {
  22. private static final long serialVersionUID = 1899083570489722793L;
  23. /**
  24. * HTTP响应状态码 {@link HttpStatus}
  25. */
  26. private Integer status;
  27. /**
  28. * HTTP响应状态码的英文提示
  29. */
  30. private String error;
  31. /**
  32. * 异常堆栈的精简信息
  33. *
  34. */
  35. private String message;
  36. /**
  37. * 我们系统内部自定义的返回值编码,{@link ResultCode} 它是对错误更加详细的编码
  38. *
  39. * 备注:spring boot默认返回异常时,该字段为null
  40. */
  41. private Integer code;
  42. /**
  43. * 调用接口路径
  44. */
  45. private String path;
  46. /**
  47. * 异常的名字
  48. */
  49. private String exception;
  50. /**
  51. * 异常的错误传递的数据
  52. */
  53. private Object errors;
  54. /**
  55. * 时间戳
  56. */
  57. private Date timestamp;
  58. public static DefaultErrorResult failure(ResultCode resultCode, Throwable e, HttpStatus httpStatus, Object errors) {
  59. DefaultErrorResult result = DefaultErrorResult.failure(resultCode, e, httpStatus);
  60. result.setErrors(errors);
  61. return result;
  62. }
  63. public static DefaultErrorResult failure(ResultCode resultCode, Throwable e, HttpStatus httpStatus) {
  64. DefaultErrorResult result = new DefaultErrorResult();
  65. result.setCode(resultCode.code());
  66. result.setMessage(resultCode.message());
  67. result.setStatus(httpStatus.value());
  68. result.setError(httpStatus.getReasonPhrase());
  69. result.setException(e.getClass().getName());
  70. String path = RequestContextUtil.getRequest().getRequestURI();
  71. result.setPath(path);
  72. result.setTimestamp(new Date());
  73. return result;
  74. }
  75. public static DefaultErrorResult failure(BusinessException e) {
  76. BusinessExceptionEnum ee = BusinessExceptionEnum.getByEClass(e.getClass());
  77. if (ee != null) {
  78. return DefaultErrorResult.failure(ee.getResultCode(), e, ee.getHttpStatus(), e.getData());
  79. }
  80. DefaultErrorResult defaultErrorResult = DefaultErrorResult.failure(e.getResultCode() == null ? ResultCode.SUCCESS : e.getResultCode(), e, HttpStatus.OK, e.getData());
  81. if (StringUtil.isNotEmpty(e.getMessage())) {
  82. defaultErrorResult.setMessage(e.getMessage());
  83. }
  84. return defaultErrorResult;
  85. }
  86. }

GlobalExceptionHandler 全局错误异常处理器

  1. package cn.notemi.demo.handler;
  2. import cn.notemi.demo.exceptions.BusinessException;
  3. import cn.notemi.demo.result.DefaultErrorResult;
  4. import org.springframework.http.HttpStatus;
  5. import org.springframework.http.ResponseEntity;
  6. import org.springframework.http.converter.HttpMessageNotReadableException;
  7. import org.springframework.validation.BindException;
  8. import org.springframework.web.bind.MethodArgumentNotValidException;
  9. import org.springframework.web.bind.annotation.ControllerAdvice;
  10. import org.springframework.web.bind.annotation.ExceptionHandler;
  11. import org.springframework.web.bind.annotation.ResponseStatus;
  12. import org.springframework.web.bind.annotation.RestController;
  13. import javax.servlet.http.HttpServletRequest;
  14. import javax.validation.ConstraintViolationException;
  15. /**
  16. * @desc 统一异常处理器
  17. */
  18. @RestController
  19. @ControllerAdvice
  20. public class GlobalExceptionHandler extends BaseGlobalExceptionHandler {
  21. /** 处理400类异常 */
  22. @Override
  23. @ResponseStatus(HttpStatus.BAD_REQUEST)
  24. @ExceptionHandler(ConstraintViolationException.class)
  25. public DefaultErrorResult handleConstraintViolationException(ConstraintViolationException e, HttpServletRequest request) {
  26. return super.handleConstraintViolationException(e, request);
  27. }
  28. @Override
  29. @ResponseStatus(HttpStatus.BAD_REQUEST)
  30. @ExceptionHandler(HttpMessageNotReadableException.class)
  31. public DefaultErrorResult handleConstraintViolationException(HttpMessageNotReadableException e, HttpServletRequest request) {
  32. return super.handleConstraintViolationException(e, request);
  33. }
  34. @Override
  35. @ResponseStatus(HttpStatus.BAD_REQUEST)
  36. @ExceptionHandler(BindException.class)
  37. public DefaultErrorResult handleBindException(BindException e, HttpServletRequest request) {
  38. return super.handleBindException(e, request);
  39. }
  40. @Override
  41. @ResponseStatus(HttpStatus.BAD_REQUEST)
  42. @ExceptionHandler(MethodArgumentNotValidException.class)
  43. public DefaultErrorResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
  44. return super.handleMethodArgumentNotValidException(e, request);
  45. }
  46. /** 处理自定义异常 */
  47. @Override
  48. @ExceptionHandler(BusinessException.class)
  49. public ResponseEntity<DefaultErrorResult> handleBusinessException(BusinessException e, HttpServletRequest request) {
  50. return super.handleBusinessException(e, request);
  51. }
  52. /** 处理运行时异常 */
  53. @Override
  54. @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  55. @ExceptionHandler(Throwable.class)
  56. public DefaultErrorResult handleThrowable(Throwable e, HttpServletRequest request) {
  57. //TODO 可通过邮件、微信公众号等方式发送信息至开发人员、记录存档等操作
  58. return super.handleThrowable(e, request);
  59. }
  60. }

BaseGlobalExceptionHandler 全局异常处理基础类

  1. package cn.notemi.demo.handler;
  2. import cn.notemi.demo.enums.ResultCode;
  3. import cn.notemi.demo.exceptions.BusinessException;
  4. import cn.notemi.demo.helper.ParameterInvalidItemHelper;
  5. import cn.notemi.demo.model.bo.ParameterInvalidItem;
  6. import cn.notemi.demo.result.DefaultErrorResult;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.http.HttpStatus;
  9. import org.springframework.http.ResponseEntity;
  10. import org.springframework.http.converter.HttpMessageNotReadableException;
  11. import org.springframework.validation.BindException;
  12. import org.springframework.web.bind.MethodArgumentNotValidException;
  13. import javax.servlet.http.HttpServletRequest;
  14. import javax.validation.ConstraintViolationException;
  15. import java.util.List;
  16. /**
  17. * @desc 全局异常处理基础类
  18. */
  19. @Slf4j
  20. public abstract class BaseGlobalExceptionHandler {
  21. /**
  22. * 违反约束异常
  23. */
  24. protected DefaultErrorResult handleConstraintViolationException(ConstraintViolationException e, HttpServletRequest request) {
  25. log.info("handleConstraintViolationException start, uri:{}, caused by: ", request.getRequestURI(), e);
  26. List<ParameterInvalidItem> parameterInvalidItemList = ParameterInvalidItemHelper.convertCVSetToParameterInvalidItemList(e.getConstraintViolations());
  27. return DefaultErrorResult.failure(ResultCode.PARAM_IS_INVALID, e, HttpStatus.BAD_REQUEST, parameterInvalidItemList);
  28. }
  29. /**
  30. * 处理验证参数封装错误时异常
  31. */
  32. protected DefaultErrorResult handleConstraintViolationException(HttpMessageNotReadableException e, HttpServletRequest request) {
  33. log.info("handleConstraintViolationException start, uri:{}, caused by: ", request.getRequestURI(), e);
  34. return DefaultErrorResult.failure(ResultCode.PARAM_IS_INVALID, e, HttpStatus.BAD_REQUEST);
  35. }
  36. /**
  37. * 处理参数绑定时异常(反400错误码)
  38. */
  39. protected DefaultErrorResult handleBindException(BindException e, HttpServletRequest request) {
  40. log.info("handleBindException start, uri:{}, caused by: ", request.getRequestURI(), e);
  41. List<ParameterInvalidItem> parameterInvalidItemList = ParameterInvalidItemHelper.convertBindingResultToMapParameterInvalidItemList(e.getBindingResult());
  42. return DefaultErrorResult.failure(ResultCode.PARAM_IS_INVALID, e, HttpStatus.BAD_REQUEST, parameterInvalidItemList);
  43. }
  44. /**
  45. * 处理使用@Validated注解时,参数验证错误异常(反400错误码)
  46. */
  47. protected DefaultErrorResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
  48. log.info("handleMethodArgumentNotValidException start, uri:{}, caused by: ", request.getRequestURI(), e);
  49. List<ParameterInvalidItem> parameterInvalidItemList = ParameterInvalidItemHelper.convertBindingResultToMapParameterInvalidItemList(e.getBindingResult());
  50. return DefaultErrorResult.failure(ResultCode.PARAM_IS_INVALID, e, HttpStatus.BAD_REQUEST, parameterInvalidItemList);
  51. }
  52. /**
  53. * 处理通用自定义业务异常
  54. */
  55. protected ResponseEntity<DefaultErrorResult> handleBusinessException(BusinessException e, HttpServletRequest request) {
  56. log.info("handleBusinessException start, uri:{}, exception:{}, caused by: {}", request.getRequestURI(), e.getClass(), e.getMessage());
  57. DefaultErrorResult defaultErrorResult = DefaultErrorResult.failure(e);
  58. return ResponseEntity
  59. .status(HttpStatus.valueOf(defaultErrorResult.getStatus()))
  60. .body(defaultErrorResult);
  61. }
  62. /**
  63. * 处理未预测到的其他错误(反500错误码)
  64. */
  65. protected DefaultErrorResult handleThrowable(Throwable e, HttpServletRequest request) {
  66. log.error("handleThrowable start, uri:{}, caused by: ", request.getRequestURI(), e);
  67. return DefaultErrorResult.failure(ResultCode.SYSTEM_INNER_ERROR, e, HttpStatus.INTERNAL_SERVER_ERROR);
  68. }
  69. }

说明

上面用到了一些自定义异常基类(BusinessException),对于这个类它会有很多子类去继承它,例如:
参数异常、数据已存在异常、无权限异常等等,这些类大家可以根据自己的业务扩展

ResponseResult 注解类

  1. package cn.notemi.demo.annotations;
  2. import cn.notemi.demo.result.PlatformResult;
  3. import cn.notemi.demo.result.Result;
  4. import java.lang.annotation.*;
  5. /**
  6. * @desc 接口返回结果增强 会通过拦截器拦截后放入标记,在WebResponseBodyHandler进行结果处理
  7. */
  8. @Target({ ElementType.TYPE, ElementType.METHOD })
  9. @Retention(RetentionPolicy.RUNTIME)
  10. @Documented
  11. public @interface ResponseResult {
  12. Class<? extends Result> value() default PlatformResult.class;
  13. }

说明

这里我们默认 PlatformResult 使用这个类作为返回格式,所以@ResponseResult 等价于@ResponseResult(PlatformResult.class)

ResponseResultInterceptor 拦截器

  1. package cn.notemi.demo.intercepter;
  2. import cn.notemi.demo.annotations.ResponseResult;
  3. import org.springframework.web.method.HandlerMethod;
  4. import org.springframework.web.servlet.HandlerInterceptor;
  5. import org.springframework.web.servlet.ModelAndView;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.lang.reflect.Method;
  9. /**
  10. * @desc 接口响应体控制拦截器
  11. */
  12. public class ResponseResultInterceptor implements HandlerInterceptor {
  13. public static final String RESPONSE_RESULT = "RESPONSE-RESULT";
  14. @Override
  15. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  16. if (handler instanceof HandlerMethod) {
  17. final HandlerMethod handlerMethod = (HandlerMethod) handler;
  18. final Class<?> clazz = handlerMethod.getBeanType();
  19. final Method method = handlerMethod.getMethod();
  20. if (clazz.isAnnotationPresent(ResponseResult.class)) {
  21. request.setAttribute(RESPONSE_RESULT, clazz.getAnnotation(ResponseResult.class));
  22. } else if (method.isAnnotationPresent(ResponseResult.class)) {
  23. request.setAttribute(RESPONSE_RESULT, method.getAnnotation(ResponseResult.class));
  24. }
  25. }
  26. return true;
  27. }
  28. @Override
  29. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  30. // nothing to do
  31. }
  32. @Override
  33. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  34. // nothing to do
  35. }
  36. }

开启拦截器配置

  1. package cn.notemi.demo.config;
  2. import cn.notemi.demo.intercepter.HeaderParamsCheckInterceptor;
  3. import cn.notemi.demo.intercepter.LoginAuthInterceptor;
  4. import cn.notemi.demo.intercepter.ResponseResultInterceptor;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  8. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  9. @Configuration
  10. public class InterceptorConfig extends WebMvcConfigurerAdapter {
  11. @Bean
  12. public ResponseResultInterceptor responseResultInterceptor() {
  13. return new ResponseResultInterceptor();
  14. }
  15. @Override
  16. public void addInterceptors(InterceptorRegistry registry) {
  17. //响应结果控制拦截
  18. registry.addInterceptor(responseResultInterceptor()).addPathPatterns("/**");
  19. }
  20. }

ResponseResultHandler 响应体格式处理器

  1. package cn.notemi.demo.handler;
  2. import cn.notemi.demo.annotations.ResponseResult;
  3. import cn.notemi.demo.constant.HeaderConstants;
  4. import cn.notemi.demo.enums.ApiStyleEnum;
  5. import cn.notemi.demo.intercepter.ResponseResultInterceptor;
  6. import cn.notemi.demo.result.DefaultErrorResult;
  7. import cn.notemi.demo.result.PlatformResult;
  8. import cn.notemi.demo.result.Result;
  9. import cn.notemi.demo.util.JsonUtil;
  10. import cn.notemi.demo.util.RequestContextUtil;
  11. import org.springframework.core.MethodParameter;
  12. import org.springframework.http.MediaType;
  13. import org.springframework.http.converter.HttpMessageConverter;
  14. import org.springframework.http.server.ServerHttpRequest;
  15. import org.springframework.http.server.ServerHttpResponse;
  16. import org.springframework.web.bind.annotation.ControllerAdvice;
  17. import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
  18. import javax.servlet.http.HttpServletRequest;
  19. /**
  20. * @desc 接口响应体处理器
  21. */
  22. @ControllerAdvice
  23. public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
  24. @Override
  25. public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
  26. HttpServletRequest request = RequestContextUtil.getRequest();
  27. ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(ResponseResultInterceptor.RESPONSE_RESULT);
  28. return responseResultAnn != null && !ApiStyleEnum.NONE.name().equalsIgnoreCase(request.getHeader(HeaderConstants.API_STYLE));
  29. }
  30. @Override
  31. public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
  32. ResponseResult responseResultAnn = (ResponseResult) RequestContextUtil.getRequest().getAttribute(ResponseResultInterceptor.RESPONSE_RESULT);
  33. Class<? extends Result> resultClazz = responseResultAnn.value();
  34. if (resultClazz.isAssignableFrom(PlatformResult.class)) {
  35. if (body instanceof DefaultErrorResult) {
  36. DefaultErrorResult defaultErrorResult = (DefaultErrorResult) body;
  37. return PlatformResult.builder()
  38. .code(defaultErrorResult.getCode())
  39. .msg(defaultErrorResult.getMessage())
  40. .data(defaultErrorResult.getErrors())
  41. .build();
  42. } else if (body instanceof String) {
  43. return JsonUtil.object2Json(PlatformResult.success(body));
  44. }
  45. return PlatformResult.success(body);
  46. }
  47. return body;
  48. }
  49. }

说明

上述代码用到了一个工具类(RequestContextHolderUtil)用于获取request对象,如果感兴趣可以看下这篇文章 工具类分享之《RequestContextHolderUtil》

@ControllerAdvice、ResponseBodyAdvice 这两个类是本功能的关键使用类,用于接口的响应体增强,其中 supports 方法用于判断是否需要做增强转化,beforeBodyWrite 方法用于增加逻辑实现

supports 方法中,加了个小功能,当调用人员不想要封装结果时,可以在 header 上设置参数 Api-Style=none

测试

  1. package cn.notemi.demo.controller;
  2. import cn.notemi.demo.annotations.LoginAuth;
  3. import cn.notemi.demo.annotations.ResponseResult;
  4. import cn.notemi.demo.model.bo.LoginUser;
  5. import cn.notemi.demo.model.po.User;
  6. import cn.notemi.demo.model.qo.LoginQO;
  7. import cn.notemi.demo.model.vo.LoginVO;
  8. import cn.notemi.demo.repository.UserRepository;
  9. import cn.notemi.demo.service.LoginService;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.http.HttpStatus;
  12. import org.springframework.web.bind.annotation.*;
  13. import javax.validation.Valid;
  14. import java.util.Date;
  15. import java.util.List;
  16. import java.util.UUID;
  17. /**
  18. * Title:UserController
  19. **/
  20. @RestController
  21. @RequestMapping("/api/user")
  22. @ResponseResult
  23. public class UserController {
  24. @Autowired
  25. private UserRepository userRepository;
  26. @GetMapping("/all")
  27. public List<User> users() {
  28. return userRepository.findAll();
  29. }
  30. }

SpringBoot实战 - 接口响应体统一封装

结束语

接口响应体统一格式转化,这个功能就完成了,这样的封装可以少些很多重复且无用的代码,何乐而不为呢?

GitHub地址:https://github.com/FlickerMi/notemi-demo