SpringMVC利用注解 规范http接口返回值

简介: SpringMVC利用注解 规范http接口返回值一般在项目构建时,会选择定义基础接口返回值规范实体,并直接规定返回实体,但在控制器上对实体的进行的实例化会产生多余代码,为了减少这一部门的冗余代码,部分项目会采用注解的方式或者直接全局使用切面来处理返回值。

SpringMVC利用注解 规范http接口返回值

一般在项目构建时,会选择定义基础接口返回值规范实体,并直接规定返回实体,但在控制器上对实体的进行的实例化会产生多余代码,为了减少这一部门的冗余代码,部分项目会采用注解的方式或者直接全局使用切面来处理返回值。以下我将介绍一下我的处理方案。

实现代码:

注解代码:

import java.lang.annotation.*;

/**
 * 如果该注解的方法出现异常,则会反馈标准的异常结果【ResponseMsg.java】给前端或者服务调用方
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyResponse {
}

返回值实体用于测试,具体的web应用,可以具体使用项目的规范,以下只是测试时使用的实体规范,具体应用时可以根据具体需要来拼装数据

import lombok.Data;

/**
 * 接口默认返回参数
 * lombok.Data 可以改成直接写入封装方法
 */
@Data
public class ResponseMsg {
    /**
     * 代码
     */
    private int code;
    /**
     * 消息
     */
    private String msg;
    /**
     * 是否成功
     */
    private boolean success;
    /**
     * 数据
     */
    private Object data;
}

自定义异常,用于测试,同理可根据具体项目需求改变

import lombok.Data;

@Data
public class MyException extends RuntimeException{
    private int code;
    /**
     * 构造
     */
    public MyException(int code, String msg) {
        super(msg);
        this.code = code;
    }
}

关键代码,返回值切面,JSON,Slf4j类根据具体项目依赖处理,此处为了减少代码增加了这个类。

实际就是利用切面获取返回值并拼装,处理Object及void类型,并通过捕捉切点的异常封装返回值。

建议将切面位置提前,保证其他切面的异常不影响返回值的规范。

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import self.aop.anno.MyResponse;
import self.aop.model.ResponseMsg;
import self.exception.MyException;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 使用AOP拦截出现异常的Controller的方法,并反馈标准的异常描述
 * 
 * @Slf4j可以去掉,换成手动的log
 */
@Order(1)
@Aspect
@Component
@Slf4j
public class ResponseAspect {

    private static final String VOID = "void";

    private static final int ERR_CODE = 500;

    @Around(value = "@annotation(catchErr)")
    public Object doAudit(ProceedingJoinPoint point, MyResponse catchErr) throws Throwable {
        Object returnVal;
        ResponseMsg resultMsg;
        try {
            returnVal = point.proceed();
        } catch (MyException ex) {
            resultMsg = new ResponseMsg();
            resultMsg.setCode(ex.getCode());
            resultMsg.setMsg(ex.getMessage());
            resultMsg.setSuccess(false);
            writeResultMessage2Writer(point, resultMsg);
            log.info("{}", ex);
            return resultMsg;
        } catch (Exception ex) {
            resultMsg = new ResponseMsg();
            resultMsg.setCode(ERR_CODE);
            resultMsg.setMsg(ex.getMessage());
            resultMsg.setSuccess(false);
            writeResultMessage2Writer(point, resultMsg);
            log.error("{}", ex);
            return resultMsg;
        }
        resultMsg = new ResponseMsg();
        resultMsg.setCode(200);
        resultMsg.setMsg("成功");
        resultMsg.setSuccess(true);
        Class returnType = ((MethodSignature) point.getSignature()).getReturnType();
        if (StringUtils.equals(returnType.getName(), VOID)) {
            writeResultMessage2Writer(point, resultMsg);
        }
        resultMsg.setData(returnVal);
        return resultMsg;
    }

    /**
     * 返回void情况下单独做response处理防止无法输出
     * @param point 切点
     * @param resultMsg 消息实体
     * @throws IOException io异常
     */
    private void writeResultMessage2Writer(ProceedingJoinPoint point, ResponseMsg resultMsg) throws IOException {
        Class returnType = ((MethodSignature) point.getSignature()).getReturnType();
        if (!StringUtils.equals(returnType.getName(), VOID)) {
            return;
        }
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();

        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-type", "application/json;charset=UTF-8");
        response.getWriter().write(JSON.toJSONString(resultMsg, SerializerFeature.PrettyFormat));
    }
}

以下是测试使用的web控制器

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import self.aop.anno.MyResponse;
import self.exception.MyException;

/**
 * 返回值规范测试控制器
 */
@Controller
@RequestMapping("response/msg")
public class ResponseMsgController {
    @PostMapping("/object")
    @MyResponse
    @ResponseBody
    public Object objectFunction(){
        return "data";
    }

    @PostMapping("/void")
    @MyResponse
    @ResponseBody
    public void voidFunction(){}

    @PostMapping("/my/exception")
    @MyResponse
    @ResponseBody
    public void myExceptionFunction(){
        throw new MyException(501,"手动抛自定义异常");
    }

    @PostMapping("/exception")
    @MyResponse
    @ResponseBody
    public void exceptionFunction(){
        throw new RuntimeException("手动抛其他异常");
    }
}

Object类型返回值

image

void类型返回值

image

自定义异常返回值

image

其他异常返回值

image

相关文章
|
18天前
|
Java API Spring
SpringBoot项目调用HTTP接口5种方式你了解多少?
SpringBoot项目调用HTTP接口5种方式你了解多少?
65 2
|
30天前
|
缓存 前端开发 Java
Spring MVC 面试题及答案整理,最新面试题
Spring MVC 面试题及答案整理,最新面试题
85 0
|
30天前
ssm(Spring+Spring mvc+mybatis)——updateDept.jsp
ssm(Spring+Spring mvc+mybatis)——updateDept.jsp
10 0
|
30天前
ssm(Spring+Spring mvc+mybatis)——showDept.jsp
ssm(Spring+Spring mvc+mybatis)——showDept.jsp
9 0
|
30天前
|
网络安全
ssh(Spring+Spring mvc+hibernate)——DeptDaoImpl.java
ssh(Spring+Spring mvc+hibernate)——DeptDaoImpl.java
11 0
|
30天前
|
网络安全
ssh(Spring+Spring mvc+hibernate)——BaseDaoImpl.java
ssh(Spring+Spring mvc+hibernate)——BaseDaoImpl.java
12 0
|
30天前
|
Shell
sh(Spring+Spring mvc+hibernate)——IEmpDao.java
sh(Spring+Spring mvc+hibernate)——IEmpDao.java
11 0
|
29天前
|
SQL JavaScript Java
springboot+springm vc+mybatis实现增删改查案例!
springboot+springm vc+mybatis实现增删改查案例!
23 0
|
29天前
|
SQL Java 数据库连接
挺详细的spring+springmvc+mybatis配置整合|含源代码
挺详细的spring+springmvc+mybatis配置整合|含源代码
35 1
|
7天前
|
数据采集 前端开发 Java
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
数据塑造:Spring MVC中@ModelAttribute的高级数据预处理技巧
21 3