场景:今天查看本地的SpringBoot的项目,发现 后台请求没有做统一响应,于是我想基于Spring Aop 对Controller层做一层全局请求响应封装。
添加相关Jar包依赖:
<!--集成Spring Aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
相关功能代码片段:
统一请求响应结构体实体对象定义
package com.zzg.common.vo;
import cn.hutool.http.HttpStatus;
import com.zzg.enums.ResultCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Response <T> implements java.io.Serializable{
private int code;
private String msg;
private T data;
public static <T> Response<T> error(int code, String msg, T data){
return new Response<T>(code, msg, data);
}
public static <T> Response<T> error(String msg){
return new Response<T>(ResultCode.FAIL.getVal(), msg, null);
}
public static <T> Response<T> success(T data){
return new Response<T>(ResultCode.SUCCESS.getVal(), ResultCode.SUCCESS.getMsg(), data);
}
public static <T> Response<T> success(String msg){
return new Response<T>(ResultCode.SUCCESS.getVal(), msg, null);
}
public static <T> Response<T> success(String msg, T data){
return new Response<T>(ResultCode.SUCCESS.getVal(), msg, data);
}
@Override
public String toString() {
return "Response{" +
"code='" + code + '\'' +
", message='" + msg + '\'' +
", data=" + data +
'}';
}
}
请求枚举状态值定义:
package com.zzg.enums;
public enum ResultCode implements java.io.Serializable {
/** 操作成功 */
SUCCESS(200, "成功"),
/** 操作失败 */
FAIL(500, "操作失败"),
/** 空指针异常 */
NullpointerException(500, "空指针异常"),
/** token失效 */
TokenExpire(500,"token失效 ");
/* private static final Map<Integer, ResultCode> MAP = Arrays.stream(ResultCode.values()).collect(Collectors.toMap(ResultCode::getVal, Function.identity()));
public static ResultCode getResultCode(Integer code){
return MAP.get(code);
}*/
ResultCode(int value, String msg){
this.val = value;
this.msg = msg;
}
public int val() {
return val;
}
public String msg() {
return msg;
}
private int val;
private String msg;
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
aop 封装请求统一响应:
package com.zzg.aop;
import com.zzg.common.vo.Response;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* 统一响应aop
*/
@Aspect
@Component
public class ResponseAop {
/** 匹配com.zzg.controller 包及其子包下的所有方法 */
@Pointcut("execution(* com.zzg.controller..*.*(..))")
public void httpResponseAop(){
}
//环切
@Around("httpResponseAop()")
public Response handlerController(ProceedingJoinPoint proceedingJoinPoint) {
Response result = null;
try {
//获取方法的执行结果
Object proceed = proceedingJoinPoint.proceed();
//如果方法的执行结果是Result,则将该对象直接返回
if (proceed instanceof Response) {
result = (Response) proceed;
} else {
//否则,就要封装到Result的data中
result =Response.success(proceed);
}
} catch (Throwable throwable) {
//如果出现了异常,调用异常处理方法将错误信息封装到Result中并返回
result = handlerException(throwable);
}
return result;
}
//异常处理
private Response handlerException(Throwable throwable) {
Response result = null;
//这里需要注意,返回枚举类中的枚举在写的时候应该和异常的名称相对应,以便动态的获取异常代码和异常信息,我这边是统一返回500,msg存报的异常
//获取异常名称的方法
String errorName = throwable.toString();
errorName = errorName.substring(errorName.lastIndexOf(".") + 1);
result = Response.error(errorName);
return result;
}
}
postman 测试:
GitHub地址:GitHub - zhouzhiwengang/SpringBoot-Project
中的SmartUrban项目。