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類型傳回值

void類型傳回值
自定義異常傳回值
其他異常傳回值