zoukankan      html  css  js  c++  java
  • 设计 API 接口 实现统一格式返回

    返回格式

    后端返回给前端我们一般用 JSON 体方式,定义如下:

    {
    	#返回状态码
    	code:integer,		
    	#返回信息描述
    	message:string,
    	#返回值
    	data:object
    }
    

    CODE 状态码

    code 返回状态码,一般小伙伴们是在开发的时候需要什么,就添加什么

    如接口要返回用户权限异常,我们加一个状态码为 101 吧,下一次又要加一个数据参数异常,就加一个 102 的状态码。这样虽然能够照常满足业务,但状态码太凌乱了

    我们应该可以参考 HTTP 请求返回的状态码

    :下面是常见的HTTP状态码:
    200 - 请求成功
    301 - 资源(网页等)被永久转移到其它URL
    404 - 请求的资源(网页等)不存在
    500 - 内部服务器错误
    

    HMJ7hW

    我们可以参考这样的设计,这样的好处就把错误类型归类到某个区间内,如果区间不够,可以设计成 4 位数。

    #1000~1999 区间表示参数错误
    #2000~2999 区间表示用户错误
    #3000~3999 区间表示接口异常
    

    这样前端开发人员在得到返回值后,根据状态码就可以知道,大概什么错误,再根据 message 相关的信息描述,可以快速定位。

    Message

    这个字段相对理解比较简单,就是发生错误时,如何友好的进行提示。一般的设计是和 code 状态码一起设计,如

    package com.xxtsoft.enumeration;
    
    /**
     * 状态码枚举
     * <p>
     * 常见的 http 状态码
     * 200 - 请求成功
     * 301 - 资源(网页等)被永久转移到其它URL
     * 404 - 请求的资源(网页等)不存在
     * 500 - 内部服务器错误
     * <p>
     * <p>
     * #1000~1999 区间表示参数错误
     * #2000~2999 区间表示用户错误
     * #3000~3999 区间表示接口异常
     *
     * @author yang
     * @version 1.0.0
     * @date 2020-11-18 09:22
     */
    public enum ResultCode {
    
        
        private Integer code;
        private String message;
        ResultCode(Integer code, String message) {
            this.code = code;
            this.message = message;
        }
    }
    

    再在枚举中定义,状态码

    package com.xxtsoft.enumeration;
    
    /**
     * 状态码枚举
     * <p>
     * 常见的 http 状态码
     * 200 - 请求成功
     * 301 - 资源(网页等)被永久转移到其它URL
     * 404 - 请求的资源(网页等)不存在
     * 500 - 内部服务器错误
     * <p>
     * <p>
     * #1000~1999 区间表示参数错误
     * #2000~2999 区间表示用户错误
     * #3000~3999 区间表示接口异常
     *
     * @author yang
     * @version 1.0.0
     * @date 2020-11-18 09:22
     */
    public enum ResultCode {
    
        /**
         * 成功状态码
         */
        SUCCESS(1, "成功"),
    
        /**
         * 参数错误 1001-1999
         */
        PARAM_IS_INVALID(1001, "参数无效"),
        /**
         * 参数错误 1001-1999
         */
        PARAM_IS_BLANK(1002, "参数为空"),
        /**
         * 参数错误 1001-1999
         */
        PARAM_TYPE_BIND_ERROR(1003, "参数类型错误"),
        /**
         * 参数错误 1001-1999
         */
        PARAM_NOT_COMPLETE(1004, "参数缺失"),
    
        /**
         * 用户错误 2001-2999
         */
        USER_NOT_LOGGED_IN(2001, "用户未登录,访问的路径需要验证,请登录"),
    
        /**
         * 用户错误 2001-2999
         */
        USER_L0GIN_ERROR(2002, "账号不存在或密码错误"),
    
        /**
         * 用户错误 2001-2999
         */
        USER_ACCOUNT_FORBIDDEN(2003, "账号已被禁用"),
    
        /**
         * 用户错误 2001-2999
         */
        USER_NOT_EXIST(2004, "用户不存在"),
        /**
         * 用户错误 2001-2999
         */
        USER_HAS_EXISTED(2005, "用户已存在"),
        /**
         * 服务器错误 没有此ID 3001
         */
        SERVER_NO_SUCH_ID(3001, "没有此ID");
    
        private Integer code;
        private String message;
    
        ResultCode() {
        }
    
        ResultCode(Integer code, String message) {
            this.code = code;
            this.message = message;
        }
    
        public Integer code() {
            return this.code;
        }
    
        public String message() {
            return this.message;
        }
    }
    

    状态码和信息就会一一对应,比较好维护。

    Data

    返回数据体,JSON 格式,根据不同的业务又不同的 JSON 体。

    我们要设计一个返回体类 Result

    package com.xxtsoft.entity;
    
    import com.xxtsoft.enumeration.ResultCode;
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.springframework.core.serializer.Serializer;
    
    import java.io.Serializable;
    
    /**
     * 返回体
     *
     * @author yang
     * @version 1.0.0
     * @date 2020-11-18 09:43
     */
    @Data
    public class Result implements Serializable {
        private Integer code;
        private String message;
        private Object data;
    
        public Result(Integer code, String message, Object data) {
            this.code = code;
            this.message = message;
            this.data = data;
        }
    
        public Result() {
        }
    
        public Result(ResultCode resultCode, Object data) {
            this.code = resultCode.code();
            this.message = resultCode.message();
            this.data = data;
        }
    
        public Result(ResultCode resultCode) {
            this.code = resultCode.code();
            this.message = resultCode.message();
        }
    
        public Result(Integer code, String message) {
            this.code = code;
            this.message = message;
        }
    
        /**
         * 返回成功!
         *
         * @return 成功
         */
        public static Result success() {
            final Result result = new Result();
            result.setResultCode(ResultCode.SUCCESS);
            return result;
        }
    
        /**
         * 返回成功!
         *
         * @param data 数据
         * @return Result,成功!
         */
        public static Result success(Object data) {
            final Result result = new Result();
            result.setResultCode(ResultCode.SUCCESS);
            result.setData(data);
            return result;
        }
    
        /**
         * 返回失败!
         *
         * @param resultCode 失败枚举
         * @return 失败!
         */
        public static Result failure(ResultCode resultCode) {
            final Result result = new Result();
            result.setResultCode(resultCode);
            return result;
        }
    
        public static Result failure(Integer code, String msg, Object data) {
            return new Result(code, msg, data);
        }
    
        public static Result failure(Integer code, String msg) {
            return new Result(code, msg);
        }
    
        /**
         * 返回失败!
         *
         * @param resultCode 失败枚举
         * @param data       失败数据
         * @return 失败!
         */
        public static Result failure(ResultCode resultCode, Object data) {
            final Result result = new Result();
            result.setResultCode(resultCode);
            result.setData(data);
            return result;
        }
    
    
        public void setResultCode(ResultCode resultCode) {
            this.code = resultCode.code();
            this.message = resultCode.message();
        }
    
    
    }
    

    优雅优化

    上面我们看到在 Result 类中增加了静态方法,使得业务处理代码简洁了。但小伙伴们有没有发现这样有几个问题:

    1、每个方法的返回都是 Result 封装对象,没有业务含义

    2、在业务代码中,成功的时候我们调用 Result.success,异常错误调用 Result.failure。是不是很多余

    3、上面的代码,判断 id 是否为 null,其实我们可以使用 hibernate validate 做校验,没有必要在方法体中做判断。

    我们最好的方式直接返回真实业务对象,最好不要改变之前的业务方式,如下图

    @RestController
    @RequestMapping("/RoleManagementController")
    @Validated
    @Slf4j
    public class RoleManagementController {
       @Autowired
        private ISysUserRoleService iSysUserRoleService;
         /**
         * 根据 角色 id,获取拥有所有该角色的用户
         *
         * @param id 角色 id,角色 id 必须是数字,且大于 0
         * @return 所有用户
         */
        @GetMapping("/listUsersByRoleId/{id}")
        public List<SysUser> listUsersByRoleId(@DecimalMin(value = "0", message = "角色 id 必须是数字,且大于 0") @PathVariable("id") Integer id) {
            final List<SysUser> sysUsers = iSysUserRoleService.listUsersByRoleId(id);
            if (Validator.isNull(sysUsers) || CollUtil.isEmpty(sysUsers)) {
                throw new ResultException(ResultCode.SERVER_NO_SUCH_ID);
            }
            return sysUsers;
        }
    }
    

    实现方案

    1、定义一个注解 @ResponseResult,表示这个接口返回的值需要包装一下

    2、拦截请求,判断此请求是否需要被 @ResponseResult 注解

    3、核心步骤就是实现接口 ResponseBodyAdvice 和 @ControllerAdvice,判断是否需要包装返回值,如果需要,就把 Controller 接口的返回值进行重写。

    注解类

    用来标记方法的返回值,是否需要包装

    package com.xxtsoft.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.ElementType.*;
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    
    import static java.lang.annotation.ElementType.METHOD;
    import static java.lang.annotation.ElementType.TYPE;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    
    /**
     * 用来标记方法的返回值,是否需要包装
     *
     * @author yang
     * @version 1.0.0
     * @date 2020-11-18 09:58
     */
    @Retention(RUNTIME)
    @Target({TYPE, METHOD})
    @Documented
    public @interface ResponseResult {
    }
    
    

    拦截器

    拦截请求,是否此请求返回的值需要包装,其实就是运行的时候,解析 @ResponseResult 注解

    package com.xxtsoft.interceptor;
    
    import cn.hutool.core.lang.Console;
    import com.xxtsoft.annotation.ResponseResult;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.lang.reflect.Method;
    
    /**
     * 拦截器
     * 拦截请求,是否此请求返回的值需要包装,其实就是运行的时候,解析 @ResponseResult 注解
     *
     * @author yang
     * @version 1.0.0
     * @date 2020-11-18 10:01
     */
    @Slf4j
    @Component
    public class ResponseResultInterceptor implements HandlerInterceptor {
        /**
         * 标记名称
         */
        public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";
    
        /**
         * 此代码核心思想,就是获取此请求,是否需要返回值包装,设置一个属性标记。
         *
         * @param request  request
         * @param response response
         * @param handler  handler
         * @return 包装
         * @throws Exception 异常
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.debug("进入 preHandle 方法");
            // 请求的方法
            if (handler instanceof HandlerMethod) {
                final HandlerMethod handlerMethod = (HandlerMethod) handler;
                final Class<?> beanType = handlerMethod.getBeanType();
                final Method method = handlerMethod.getMethod();
                //   判断是否在类对象上加了注解
                if (beanType.isAnnotationPresent(ResponseResult.class)) {
                    // 设置此请求返回体,需要包装,往下传递,在 ResponseBodyAdvice 接口进行判断
                    log.debug("此类有 ResponseResult 注解");
                    request.setAttribute(RESPONSE_RESULT_ANN, beanType.getAnnotation(ResponseResult.class));
                    // 方法上是否有注解
                } else if (method.isAnnotationPresent(ResponseResult.class)) {
                    log.debug("此方法有 ResponseResult 注解");
                    // 设置此请求返回体,需要包装,往下传递,在 ResponseBodyAdvice 接口进行判断
                    request.setAttribute(RESPONSE_RESULT_ANN, method.getAnnotation(ResponseResult.class));
                }
            }
            return true;
        }
    }
    
    

    此代码核心思想,就是获取此请求,是否需要返回值包装,设置一个属性标记。

    配置拦截器

    package com.xxtsoft.config;
    
    import com.xxtsoft.interceptor.ResponseResultInterceptor;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    /**
     * web 配置
     *
     * @author yang
     * @version 1.0.0
     * @date 2020-11-18 11:13
     */
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        @Autowired
        private ResponseResultInterceptor responseResultInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // 添加拦截器,配置拦截地址
            // 其中 /** 表示当前目录以及所有子目录(递归),/* 表示当前目录,不包括子目录。
            registry.addInterceptor(responseResultInterceptor).addPathPatterns("/**");
        }
    }
    
    

    重写返回体

    package com.xxtsoft.handler;
    
    import com.xxtsoft.annotation.ResponseResult;
    import com.xxtsoft.entity.Result;
    import com.xxtsoft.exception.ResultException;
    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.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
    
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * 重写返回体
     *
     * @author yang
     * @version 1.0.0
     * @date 2020-11-18 10:08
     */
    @Slf4j
    @ControllerAdvice
    public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
        /**
         * 标记名称
         */
        public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";
    
        /**
         * 是否请求 包含了 包装注解标记
         * ,没有就直接返回,不需要重写返回体
         *
         * @param returnType    returnType
         * @param converterType converterType
         * @return boolean
         */
        @Override
        public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
            log.debug("进入 supports 方法");
            final ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            assert sra != null;
            final HttpServletRequest request = sra.getRequest();
            // 判断请求是否有包装标记
            final ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANN);
            return responseResultAnn != null;
        }
    
        @Override
        public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
            log.debug("进入 返回体,重写格式 ,处理中!!!body {}", body);
            if (body instanceof Result) {
                // 是 Result 包转好的,说明是处理过异常的,直接返回
                return body;
            }
            return Result.success(body);
    
    
        }
    }
    
    

    上面代码就是判断是否需要返回值包装,如果需要就直接包装

    异常类

    package com.xxtsoft.exception;
    
    import com.xxtsoft.enumeration.ResultCode;
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    
    /**
     * 返回体 异常类
     *
     * @author yang
     * @version 1.0.0
     * @date 2020-11-18 10:25
     */
    @EqualsAndHashCode(callSuper = true)
    @Data
    public class ResultException extends RuntimeException {
        private Integer code;
        private String message;
        private Object data;
    
        public ResultException(ResultCode resultCode) {
            this.code = resultCode.code();
            this.message = resultCode.message();
        }
    
        public ResultException(ResultCode resultCode, Object data) {
            this.code = resultCode.code();
            this.message = resultCode.message();
            this.data = data;
        }
    }
    
    

    全局异常处理

    package com.xxtsoft.controller;
    
    import com.xxtsoft.entity.ResponseJson;
    import com.xxtsoft.entity.Result;
    import com.xxtsoft.enumeration.ResultCode;
    import com.xxtsoft.exception.ResultException;
    import com.xxtsoft.exception.SysDeptException;
    import com.xxtsoft.exception.SysRoleException;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    import javax.validation.ValidationException;
    
    /**
     * 系统级别的异常处理
     *
     * @author yang
     * @version 1.0.0
     * @date 2020-11-18 10:55
     */
    @RestControllerAdvice
    @Slf4j
    public class SystemExceptionHandler {
        /**
         * 捕获
         * ResultException
         *
         * @param exception ResultException
         * @return 对应的信息
         */
        @ExceptionHandler(value = {ResultException.class})
        public Result sysDeptException(ResultException exception) {
            log.debug("code {},message {},data {} ", exception.getCode(), exception.getMessage(), exception.getData());
            return Result.failure(exception.getCode(), exception.getMessage(), exception.getData());
        }
    
        /**
         * 处理 参数不合法异常
         *
         * @param validator ValidationException
         * @return Result
         */
        @ExceptionHandler(value = {ValidationException.class})
        public Result validationException(Exception validator) {
            log.debug("{}", validator.toString());
            return Result.failure(ResultCode.PARAM_IS_INVALID, validator.getMessage());
        }
    }
    
    

    重写 Controller

    package com.xxtsoft.controller.system.management;
    
    import cn.hutool.core.collection.CollUtil;
    import cn.hutool.core.lang.Validator;
    import cn.hutool.core.lang.tree.Tree;
    import com.xxtsoft.annotation.ResponseResult;
    import com.xxtsoft.entity.*;
    import com.xxtsoft.enumeration.ResultCode;
    import com.xxtsoft.exception.ResultException;
    import com.xxtsoft.exception.SysDeptException;
    import com.xxtsoft.exception.SysRoleException;
    import com.xxtsoft.service.*;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.ibatis.annotations.Delete;
    import org.hibernate.validator.constraints.Length;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;
    
    import javax.validation.constraints.DecimalMin;
    import javax.validation.constraints.NotBlank;
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.util.List;
    
    /**
     * 角色管理控制器
     * <p>
     * 获取权限树
     * <p>
     * 获取所有角色
     * <p>
     * 添加角色
     * 删除角色
     *
     * @author yang
     * @version 1.0.0
     * @date 2020-11-10 10:03
     */
    @RestController
    @RequestMapping("/RoleManagementController")
    @Validated
    @Slf4j
    public class RoleManagementController {
    
        @Autowired
        private ISysMenuService iSysMenuService;
    
        @Autowired
        private ISysUserService iSysUserService;
    
        @Autowired
        private ISysRoleService iSysRoleService;
    
        @Autowired
        private ISysRoleFunctionService iSysRoleFunctionService;
    
        @Autowired
        private ISysUserRoleService iSysUserRoleService;
    
    
        /**
         * 获取 菜单树
         *
         * @return 菜单树
         */
        @PostMapping("/treeList")
        public ResponseJson treeList() {
            final List<Tree<Integer>> trees = iSysMenuService.treeList();
            log.debug("trees {}", trees);
            return new ResponseJson().ok(trees).message("获取成功");
        }
    
        /**
         * 获取 所有的角色
         *
         * @return 所有的角色
         */
        @GetMapping("/roleList")
        public ResponseJson roleListResponseJson() {
            final List<SysRole> sysRoleList = iSysRoleService.list();
            log.debug("{}", sysRoleList);
            return new ResponseJson().ok(sysRoleList).message("获取成功");
        }
    
        /**
         * 根据 角色 id 获取对应的 (功能)权限
         *
         * @param id 角色 id
         * @return 功能(权限)
         */
        @GetMapping("/listFunctionByRoleId/{id}")
        public ResponseJson getJurisdiction(@DecimalMin(value = "0", message = "角色 id 必须是数字,且大于 0") @PathVariable("id") Integer id) {
            final List<SysFunction> sysFunctionList = iSysRoleFunctionService.listFunctionByRoleId(id);
            log.debug("id {},list {}", id, sysFunctionList);
            if (Validator.isNull(sysFunctionList) || CollUtil.isEmpty(sysFunctionList)) {
                throw new SysRoleException("没有此 id");
            }
            return new ResponseJson().ok(sysFunctionList).message("获取成功");
        }
    
        /**
         * 根据 角色 id,获取拥有所有该角色的用户
         *
         * @param id 角色 id,角色 id 必须是数字,且大于 0
         * @return 所有用户
         */
        @ResponseResult
        @GetMapping("/listUsersByRoleId/{id}")
        public List<SysUser> listUsersByRoleId(@DecimalMin(value = "0", message = "角色 id 必须是数字,且大于 0") @PathVariable("id") Integer id) {
            final List<SysUser> sysUsers = iSysUserRoleService.listUsersByRoleId(id);
            if (Validator.isNull(sysUsers) || CollUtil.isEmpty(sysUsers)) {
                throw new ResultException(ResultCode.SERVER_NO_SUCH_ID);
            }
            return sysUsers;
        }
    
    
        /**
         * 根据 角色 id 和 用户 ID 取消一条权限
         *
         * @param role 角色 id
         * @param user 用户 ID
         * @return 是否取成功
         */
        @ResponseResult
        @DeleteMapping("/cancelRoleByRoleIdAndUserId/{role}/{user}")
        public Boolean cancelRoleByRoleIdAndUserId(@DecimalMin(value = "0", message = "角色 id 必须是数字,且大于 0") @PathVariable("role") Integer role, @DecimalMin(value = "0", message = "用户 id 必须是数字,且大于 0") @PathVariable("user") Integer user) {
            log.debug(" role {},user {}", role, user);
            return iSysUserRoleService.cancelRoleByRoleIdAndUserId(role, user);
        }
    
        /**
         * 根据 角色 id
         * 删除一个角色
         *
         * @param roleId 角色 id
         * @return 是否成功!
         */
        @ResponseResult
        @DeleteMapping("/delRoleByRoleId/{roleId}")
        public Boolean delRoleByRoleId(@PathVariable("roleId") Integer roleId) {
            log.debug("roleId {}", roleId);
            // 删除一个角色
            final boolean b = iSysRoleService.removeById(roleId);
            // 根据 角色 去 角色功能表 删除角色对应的功能
            iSysRoleFunctionService.deleteByRoleId(roleId);
            return b;
        }
    
        /**
         * 添加一个角色
         *
         * @param roleName 角色名
         * @param roleDes  角色描述
         * @return 添加成功后的角色
         */
        @ResponseResult
        @PutMapping("/addRole/{roleName}/{roleDes}")
        public Boolean addRole(@NotBlank(message = "角色名称不能为空")
                               @Length(max = 50, min = 1, message = "角色名称长度限制 1 ~ 50") @PathVariable String roleName, @NotBlank(message = "角色描述不能为空")
                               @Length(max = 50, min = 1, message = "角色描述长度限制 1 ~ 50") @PathVariable String roleDes) {
            log.debug(" 角色名称 {} 角色描述 {}", roleName, roleDes);
    
    
            final SysRole sysRole = SysRole.builder()
                    .froleName(roleName)
                    .froleDesc(roleDes)
                    .fcreateLn(iSysUserService.getLoginUserName())
                    .fcreateDate(LocalDateTime.now())
                    .flastModifyLn(iSysUserService.getLoginUserName())
                    .flastModifyDate(LocalDateTime.now())
                    .fversion(LocalDate.now())
                    .build();
    
            return iSysRoleService.save(sysRole);
    
        }
    
        /**
         * 根据角色 id 变更权限
         *
         * @param roleId       角色 id
         * @param functionList 权限 数组
         * @return 是否成功
         */
        @ResponseResult
        @PutMapping("/AddPermissionByRoleId/{roleId}")
        public boolean addPermissionByRoleId(@PathVariable("roleId") Integer roleId, @RequestBody List<Integer> functionList) {
            log.debug(" roleId {}, functions {}", roleId, functionList);
            return iSysRoleFunctionService.addPermissionByRoleId(roleId, functionList);
        }
    
    }
    
    

    在控制器类上或者方法体上加上 @ResponseResult 注解,这样就 ok 了,简单吧。到此返回的设计思路完成,是不是又简洁,又优雅。

    总结

    这个方案还有没有别的优化空间,当然是有的。如:每次请求都要反射一下,获取请求的方法是否需要包装,其实可以做个缓存,不需要每次都需要解析

  • 相关阅读:
    js 提升
    omnipay支付--支付宝支付
    laravel 配置sql日志
    laravel monlog配置
    php openssl相关加密解密 验签代码
    laravel validator提示信息中文化
    opendevops_codo项目研究
    Python学习笔记
    shell编程总结
    关于JeeSite开源软件
  • 原文地址:https://www.cnblogs.com/javayanglei/p/14182703.html
Copyright © 2011-2022 走看看