后端返回数据全局处理

原创 2018年04月14日 22:44:58

返回值全局拦截

前言

现在项目中,软件开发采用前后端分离模式是越来越普遍,后端人员更加专注数据,前端(包括html和app开发人员)更加注重数据展示和部分前端逻辑控制。目前跟前端人员约定的数据返回格式如下:

  {
    "code": "200",
    "message": "成功",
    "data": T
  }

我们生成一个实体类,命名BaseResponse,如下:

@Data
public class BaseResponse<T>(){
  private int code;
  private String message;
  private T data;
}

无全局拦截

代码逻辑很混乱,重用性很低…
下面的代码基于SpringBoot1.0的框架。跟spring+springmvc差别不大。
这是controller层:

/**
 * function :用户控制器
 * @author :mayao
 * @date :2018/4/14
 */
@RestController
@RequestMapping("/user")
public class UserCtrl extends BaseCtrl {

    @Autowired
    private IUserService iUserService;

    @PostMapping("/add")
    public BaseResponse<Integer> addUser(User user){
        return iUserService.addUser(user);
    }
}

1.一直清楚ctrl里面不能里面有太多逻辑,所以在service层进行了数据的封装处理,那么问题来了,我service的返回结果都是BaseResponse…如下,返回的数据结构辨识度就下降了不少:

public interface IUserService {
    BaseResponse<Integer> addUser(User user);
    BaseResponse<List<User>> userList(User user);
    int updateUserInfo(User user);
}

2.我的service实现里面还要判断各种逻辑业务逻辑混乱,并封装,是不是有种吐血的冲动….,如下:

@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public BaseResponse<Integer> addUser(User user) {
        BaseResponse baseResponse = new BaseResponse();
        //判断参数缺失
        if(StringUtils.isEmpty(user.getUserName())){
            baseResponse.setCode(40001);
            baseResponse.setMessage("参数缺失");
            baseResponse.setData(0);
            return baseResponse;
        }
        //异常捕捉
        int code;
        String msg;
        int data=0;
        try{
            data = userMapper.addUser(user);
            code=200;
            msg="成功";
        }catch (Exception e){
            code=500;
            msg="服务器异常";
        }
        baseResponse.setCode(code);
        baseResponse.setMessage(msg);
        baseResponse.setData(data);
        return baseResponse;
    }
} 

3.更有甚者,不按约定来的也有,不是返回的BaseResponse,返回其他类型的(第一种)。
4.不易于扩展。后面数据结构需要调整的话,改起来也是费神。
5.其他…

注:隐去了部分相关注释,其实有些重复代码也可以再封装一下什么的,就不多去追究了,重点不在那。上面的代码点夸张的嫌疑,但是的确有这种接口开发的存在。虽然我不想承认几年前我真的干过,那时候前后端分离开发还没这么普及….

采用全局拦截

统一拦截,大家其实很容易想到的是AOP和拦截器做,其实更倾向于AOP,其实是可以做的。但是!Spring已经提供了一个类用于处理这种事情,就是:ResponseBodyAdvice,全包名:org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;意思很明确:返回体建议。

就直接上代码了:

@RestController
@RequestMapping("/user")
public class UserCtrl extends BaseCtrl {

    @Autowired
    private IUserService iUserService;

    @PostMapping("/add")
    public int addUser(User user){
        return iUserService.addUser(user);
    }

    @PostMapping("/list")
    public BaseResponse<List<User>> userList(User user){
        return iUserService.userList(user);
    }

}
@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public int addUser(User user) {
        return userMapper.addUser(user);
    }

    @Override
    public BaseResponse<List<User>> userList(User user) {
        BaseResponse<List<User>> baseResponse = new BaseResponse<>();
        baseResponse.setCode(200);
        baseResponse.setData(userMapper.userList(user));
        baseResponse.setMessage("成功");
        return baseResponse;
    }
}  

拦截返回体:

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
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;

/**
 * function :返回值拦截自定义
 * @author :mayao
 * @date :2018/4/14
 */
@Slf4j
@ControllerAdvice(basePackages = { "com.mayao.ctrls"})
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        //判断支持的类型,因为我们定义的BaseResponse 里面的data可能是任何类型,这里就不判断统一放过
        //如果你想对执行的返回体进行操作,可将上方的Object换成你自己的类型
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest,
                                            ServerHttpResponse serverHttpResponse) {

        //注解@Slf4j所带,属于非常推荐的lombok项目,可以去看看我的idea插件去了解一下
        log.info("请求返回数据类型class={}",body.getClass().getName());
        BaseResponse result=null;
        //兼容原来的接口返回
        if(body instanceof BaseResponse){
            result=(BaseResponse)body;
        }else{
            result=new BaseResponse();
            if(null!=body&&!"".equals(body)){
                result.setCode(200);
                result.setMessage("成功");
                result.setData(body);
            }
        }
        if(log.isDebugEnabled()){
            log.debug("响应参数:{} ", JSONUtil.toJson(result));
        }
        return result;
    }
}

末:
这里,全局统一拦截返回兼容了原来的老接口的返回。
至于接口异常的情况。异常的自定义,及异常的全局处理就是必不可少了的。
自定义异常及异常全局处理;

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/my_nice_life/article/details/79945279

后端返回数据全局处理

返回值全局拦截 前言 现在项目中,软件开发采用前后端分离模式是越来越普遍,后端人员更加专注数据,前端(包括html和app开发人员)更加注重数据展示和部分前端逻辑控制。目前跟前端人员约定的数据返回...
  • my_nice_life
  • my_nice_life
  • 2018-04-14 22:44:58
  • 16

JAVA项目做API,SpringMVC拦截异常并返回Json

public class ExceptionHandler implements HandlerExceptionResolver { @Override public ModelAndView ...
  • jsyhello
  • jsyhello
  • 2016-06-13 16:14:55
  • 1854

jquery ajax处理后端传回数据

文档加载准备好之前传回数据,一般采用json来处理。 $.ajax({ type: "POST",//以什么方式请求 url: 'FolderAction!saveInformSetti...
  • u013086392
  • u013086392
  • 2016-05-23 19:33:10
  • 1786

过滤后端返回的数组每条连续重复一遍问题

刚碰到问题以及解决办法的思路: 后端返回的数组变成类似[{1,1},{1,1},{2,2},{2,2},{3,3},{3,3}.....] 每条数据后面都跟前面一条一模一样。 现在我们要过...
  • u012138137
  • u012138137
  • 2017-06-16 09:58:50
  • 420

后台权限管理控制shiro+jsonMenu

在学习后台的权限控制,自己参考了各种资料后的新手demo,ui框架选型为大家可以参照网上的,项目架构为spring mvc + spring+mybatis,简单易用好上手!搭建好框架后开始了第一个任...
  • u014799292
  • u014799292
  • 2016-04-26 12:26:45
  • 12703

REST风格框架实战:从MVC到前后端分离(附完整Demo)

摘要:   本人在前辈《从MVC到前后端分离(REST-个人也认为是目前比较流行和比较好的方式)》一文的基础上,实现了一个基于Spring的符合REST风格的完整Demo,具有MVC分层结构并实现前...
  • justloveyou_
  • justloveyou_
  • 2017-07-05 10:04:01
  • 21121

vue开发:axios前后端数据处理

目前主流的 Vue 项目,都选择 axios 来完成 ajax 请求,而大型项目都会使用 Vuex 来管理数据。 前言:  使用 cnpm 安装 axios cnpm i...
  • Generon
  • Generon
  • 2017-06-02 21:52:07
  • 6040

日期的计算多少天 多少月 多少年后 前台通过了ajax调用后台处理获取返回值

需求是因为要做一个日期联动 通过日期控件的选择的日期值通过调用axjx传值到后台  前台文本框: class="Wdate" onClick="WdatePicker({readOnly:true,...
  • dxjcsdnbk
  • dxjcsdnbk
  • 2017-05-24 15:27:45
  • 669

js eval方法解析java后台传来的json字符串

在前端做图表展示时,往往会遇到后台传来的一大串数据,一般要转成数组形式,在前端展示,特别是百度的Echarts!这里使用eval解决此问题。 对于服务器返回的JSON字符串,如果POST请求没做类型...
  • jintiaozhuang
  • jintiaozhuang
  • 2015-10-23 18:26:32
  • 2331

java restful 后端 Exception 的处理架构总结

本文主要结合实现的restfuljava 后端,总结Exception 的处理架构。 1.    exception 的分类和处理方法 异常是面向对象语言非常重要的一个特性,良好的异常设计对程序的可扩...
  • jingshuaizh
  • jingshuaizh
  • 2015-01-12 18:50:15
  • 11205
收藏助手
不良信息举报
您举报文章:后端返回数据全局处理
举报原因:
原因补充:

(最多只允许输入30个字)