现在所在公司没有大哥,所以格式全凭开发人员自己写,一点开发规范都没有,所以看到统一格式就立马记录一下。
SpringBoot 后台返回给前台固定的数据格式:
{
code:integer, #返回状态码
message:string, #返回信息描述
data:object #返回值
}
返回码ResultCode类
public enum ResultCode {
//成功状态码
SUCCESS(200,"成功"),
//失败 状态码
FAIL(400,"失败"),
//参数错误 1001-1999
PARAM_IS_INVALID(1001,"参数无效"),
PARAM_IS_BLANK(1002,"参数为空"),
PARAM_TYPE_BIND_ERROR(1003,"参数类型错误"),
//用户错误 2001-2999
USER_NOT_LOGGED_IN(2001,"用户未登陆,访问路径需要验证,请登陆"),
USER_LOGIN_ERROR(2002,"账号不存在");
private Integer code;
private String message;
ResultCode(Integer code,String message){
this.code=code;
this.message=message;
}
public Integer code() {
return this.code;
}
public String message() {
return this.message;
}
}
返回结果封装Result
/**
* 结果实体类
*/
public class Result {
/**
* 响应状态码
*/
private int code;
/**
* 响应提示信息
*/
private String message;
/**
* 响应结果对象
*/
private Object data;
public Result(ResultCode resultCode, Object data) {
this.code = resultCode.code();
this.message = resultCode.message();
this.data = data;
}
public Result(){
}
public Result(int code,String message, Object data) {
this.code = code;
this.message = message;
this.data = data;
}
public static Result success(){
Result result=new Result();
result.setMessage("success");
result.setCode(ResultCode.SUCCESS.code());
return result;
}
public static Result success(Object data){
Result result=new Result();
result.setCode(ResultCode.SUCCESS.code());
result.setMessage("success");
result.setData(data);
return result;
}
public static Result failure(){
Result result=new Result();
result.setMessage("failure");
result.setCode(ResultCode.FAIL.code());
return result;
}
public static Result failure(Object data){
Result result=new Result();
result.setMessage("failure");
result.setCode(ResultCode.FAIL.code());
result.setData(data);
return result;
}
public static Result getResult(ResultCode resultCode,Object data){
Result result=new Result();
result.setData(data);
result.setCode(resultCode.USER_NOT_LOGGED_IN.code());
result.setMessage(resultCode.USER_NOT_LOGGED_IN.message());
return result;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
Controller层编写
/*
*文件名: TestResultCodeController
*创建者: xiaozhan
*创建时间:2020/10/31 16:23
*描述: 这是一个示例
*/
import com.bigdata.bigdata.entity.result.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/testResultCode")
public class TestResultCodeController {
@GetMapping("/{id}")
public Result getResult(@PathVariable("id") Integer id){
if(id==null){
return null;
}
List<String> resultList=new ArrayList<>();
resultList.add("肖战");
resultList.add("王一博");
resultList.add("赵丽颖");
resultList.add("李易峰");
return Result.success(resultList);
}
}
此时,若是已经开发好的后台接口,若是需要调整返回结果格式,需要调整接口逻辑,不建议调整之前逻辑,因为会存在一些雷。
所以 这时需要 全局统一格式即可。
请求拦截器 标记是否类/方法上有@ResponseResult标记
请求拦截器 标记是否类/方法上有@ResponseResult标记
package com.bigdata.bigdata.component;
import com.bigdata.bigdata.annotations.ResponseResult;
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;
/**
* @Description: 请求拦截器 标记是否类/方法上有@ResponseResult标记
*/
@Component
public class ResponseResultInterceptor implements HandlerInterceptor {
//标记名称
public static final String RESPONSE_RESULT_ANN="RESPONSE_RESULT_ANN";
@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();
//判断是否在类对象上加注解
if(clazz.isAnnotationPresent(ResponseResult.class)){
request.setAttribute(RESPONSE_RESULT_ANN,clazz.getAnnotation(ResponseResult.class));
}else if(method.isAnnotationPresent(ResponseResult.class)){ //方法上是否有注解
request.setAttribute(RESPONSE_RESULT_ANN,method.getAnnotation(ResponseResult.class));
}
}
return true;
}
}
对数据格式统一处理
package com.bigdata.bigdata.component;
import com.bigdata.bigdata.annotations.ResponseResult;
import com.bigdata.bigdata.entity.result.ErrorResult;
import com.bigdata.bigdata.entity.result.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/**
* @Description: 对数据格式统一
*/
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
private final static Logger logger= LoggerFactory.getLogger(ResponseResultHandler.class);
//标记名称
public static final String RESPONSE_RESULT_ANN="RESPONSE_RESULT_ANN";
//是否请求包含了 包装注解标记 没有 直接返回,不需要重写返回体
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
ServletRequestAttributes requestAttributes =(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
//判断请求中是否包含 包装标记
ResponseResult responseResultAnn = (ResponseResult)request.getAttribute(RESPONSE_RESULT_ANN);
return responseResultAnn==null?false:true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
logger.info("进入返回体 重写格式处理中");
//方法体报异常 判断body是否为异常类
if(body instanceof ErrorResult){
logger.info("返回值异常 做包装 处理中");
ErrorResult errorResult=(ErrorResult)body;
return Result.failure(errorResult.getCode(),errorResult.getMessage(),errorResult.getData());
}
return Result.success(body);
}
}
拦截器的配置
package com.bigdata.bigdata.config;
import com.bigdata.bigdata.component.ResponseResultInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Description: 请求拦截器 拦截路径 配置
*/
@Configuration
public class HandlerInterceptorConfig implements WebMvcConfigurer {
@Autowired
private ResponseResultInterceptor interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor).addPathPatterns("/testResultAnnotation/**")
.excludePathPatterns("/test");
}
}
controller测试
package com.bigdata.bigdata.controller;
import com.bigdata.bigdata.annotations.ResponseResult;
import com.bigdata.bigdata.entity.result.ErrorResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: 测试使用注解的返回值 格式统一化
*/
@RestController
@RequestMapping("/testResultAnnotation")
@ResponseResult
public class TestResultAnnotationController {
@GetMapping("/{id}")
public List<String> getResult(@PathVariable("id") Integer id){
if(id==null){
return null;
}
List<String> resultList=new ArrayList<>();
resultList.add("肖战");
resultList.add("王一博");
resultList.add("赵丽颖");
resultList.add("李易峰");
return resultList;
}
@GetMapping("getResultError")
public ErrorResult getResultError(){
return new ErrorResult(500,"网络超时",null);
}
}
ErrorResult类
package com.bigdata.bigdata.entity.result;
/**
* @Description: 错误返回结果实体类
*/
public class ErrorResult{
/**
* 响应状态码
*/
private int code;
/**
* 响应提示信息
*/
private String message;
/**
* 响应结果对象
*/
private Object data;
public ErrorResult(int code, String message, Object data) {
this.code=code;
this.message=message;
this.data=data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}