版本
Spring-boot:2.3.1
方案
使用拦截器
常量类
定义一个统一的标识
public class Constant {
public static final String RESPONSE_RESULT_ANNOTATION = "RESPONSE_RESULT_ANNOTATION";
}
返回体
import org.springframework.http.HttpStatus;
import java.io.Serializable;
/**
* 接口返回对象
*/
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
private static Result<Object> result = new Result<>();
/**
* 失败消息
*/
private String message;
/**
* 返回代码
*/
private Integer code;
/**
* 时间戳
*/
private long timestamp = System.currentTimeMillis();
/**
* 结果对象
*/
private T data;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
private Result() {}
public static Result success() {
Result result = new Result();
result.setCode(HttpStatus.OK.value());
return result;
}
public static Result<Object> success(Object data) {
result.setCode(HttpStatus.OK.value());
result.setData(data);
return result;
}
public static Result<Object> success(Object data, String message) {
result.setCode(HttpStatus.OK.value());
result.setData(data);
result.setMessage(message);
return result;
}
public static Result<Object> failure(String message) {
result.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
result.setMessage(message);
return result;
}
public static Result<Object> failure(Integer code, String message) {
result.setCode(code);
result.setMessage(message);
return result;
}
}
注解类
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface ResponseResult {
}
Retention指明可以通过反射读取
Target指明注解类可以注解到类,接口,枚举,方法
controller统一注解封装(可有可无)
import com.maintenance.response.ResponseResult;
import org.springframework.web.bind.annotation.RestController;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@RestController
@ResponseResult
public @interface BaseControllerAnnotation {
}
此注解的作用就是在Controller中只需要写BaseControllerAnnotation就行了,不需要在写@RestController和@ResponseResult,所以只是用来简化代码的
配置类
import com.maintenance.response.ResponseResultInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
/**
* 添加拦截器规则
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new ResponseResultInterceptor()).addPathPatterns("/**");
}
}
Configuration注解指明配置类,springboot自动扫描
addInterceptors中添加拦截器,可以添加多个,这里我们拦截了所有的请求
拦截器
import com.maintenance.pojo.BaseControllerAnnotation;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
public class ResponseResultInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(handler instanceof HandlerMethod) {
/* 反射获取类和方法 */
final HandlerMethod handlerMethod = (HandlerMethod) handler;
final Class<?> clazz = handlerMethod.getBeanType();
final Method method = handlerMethod.getMethod();
/* 校验类的注解和方法的注解,满足条件后,添加到attribute */
if(clazz.isAnnotationPresent(ResponseResult.class)) {
request.setAttribute(Constant.RESPONSE_RESULT_ANNOTATION, clazz.getAnnotation(ResponseResult.class));
} else if(method.isAnnotationPresent(ResponseResult.class)) {
request.setAttribute(Constant.RESPONSE_RESULT_ANNOTATION, method.getAnnotation(ResponseResult.class));
} else if(clazz.isAnnotationPresent(BaseControllerAnnotation.class)) {
request.setAttribute(Constant.RESPONSE_RESULT_ANNOTATION, clazz.getAnnotation(BaseControllerAnnotation.class));
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
增强器(处理返回)
import com.maintenance.excepion.RoleManagerException;
import com.maintenance.pojo.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
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.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
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;
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
private Logger logger = LoggerFactory.getLogger(ResponseResultHandler.class);
/**
* 判断组件支持的类型
* @param returnType
* @param converterType
* @return
*/
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
/* 判断是否需要统一包装,如果attribute中有,则表示需要处理,返回true */
Object annotation = request.getAttribute(Constant.RESPONSE_RESULT_ANNOTATION);
return !(annotation == null);
}
/**
* 处理返回体
* @param body
* @param returnType
* @param selectedContentType
* @param selectedConverterType
* @param request
* @param response
* @return
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if(!(body instanceof Result)) {
// 包装返回体
return Result.success(body);
}
return body;
}
/**
* 自定义异常
* @param e
* @return
*/
@ExceptionHandler(RoleManagerException.class)
@ResponseBody
public Result<?> exceptionHandler(RoleManagerException e) {
logger.error(e.getMessage(), e);
return Result.failure(e.getMessage());
}
/**
* 系统异常
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public Result<?> exceptionHandler(Exception e) {
logger.error(e.getMessage(), e);
return Result.failure(HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统异常,请联系管理员");
}
}
使用方法
在controller类上使用@ResponseResult或@BaseControllerAnnotation
在controller方法上使用@ResponseResult