springboot统⼀接⼝返回数据的实现⼀,没有异常的情况,正常返回数据
希望接⼝统⼀返回的数据格式如下:
{
"status": 0,
"msg": "成功",
"data": null
}
和接⼝数据对应的bean
/**
* 统⼀返回结果的实体
* @param <T>
*/
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
private int status;
/**
* 提⽰消息
*/
private String msg;
/
**
* 返回的数据体
*/
private T data;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
操作Result实体的⼯具类
/**
* ⽣成result的⼯具类,避免重复代码
*/
public class ResultUtils {
/**
* 成功时⽣成result的⽅法,有返回数据
*/
public static <T> Result<T> success(T t){
Result<T> result = new Result<>();
result.setStatus(Code());
result.setMsg(Msg());
result.setData(t);
return result;
}
/**
* 成功时⽣成result的⽅法,⽆返回数据
*/
public static <T> Result<T> success(){
return success(null);
}
/
**
* 失败时⽣成result的⽅法
*/
public static <T> Result<T> error(int status, String msg){
Result<T> result = new Result<>();
result.setStatus(status);
result.setMsg(msg);
return result;
}
}
封装错误码和错误消息的枚举类
/
**
* 所有返回结果的枚举
*/
public enum ResultEnum {
UNKNOWN_ERROR(-1, "未知错误"),
SUCCESS(0, "成功"),
BASIC_INFO_ID_IS_EMPTY(600, "基本信息中BasicInfoId为空"),
BASIC_INFO_ADD_TO_DATABASE_FAILURE(601, "向数据库添加基本信息失败"),
DETAILS_DATA_BASIC_INFO_ID_IS_EMPTY(602, "测试数据中BasicInfoId为空"),
DETAILS_DATA_ADD_TO_DATABASE_FAILURE(603, "向数据库添加测试数据失败");
ResultEnum(int code, String msg) {
this.msg = msg;
}
private int code;
private String msg;
public int getCode() {
return code;
}
public void setCode(int code) {
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return "ResultEnum{" +
"code=" + code +
", msg='" + msg + '\'' +
'}';
}
}
统⼀封装返回结果的切⾯
之所以需要这个切⾯,是为了避免每个Controller⽅法中都要调⽤ResultUtils.success()。有了这个切⾯,Controller可以和原来⼀样正常返回对象,字符串,void,在切⾯⾥⾯将结果封装成Result实
体,⽽不需要每个Controller⽅法都返回Result实体。
/**
* 统⼀处理返回结果的切⾯,避免每个controller⽅法⾥⾯都要调⽤ResultUtils.success()这句话
* 统⼀在这个切⾯⾥⾯调⽤
*/
@ControllerAdvice
public class MyResponseAdvice implements ResponseBodyAdvice<Object> {
@Autowired
private ObjectMapper objectMapper;
/**
* Whether this component supports the given controller method return type
* and the selected {@code HttpMessageConverter} type.
*
* @param returnType the return type
* @param converterType the selected converter type
* @return {@code true} if {@link #beforeBodyWrite} should be invoked;
* {@code false} otherwise
*/
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
/**
* Invoked after an {@code HttpMessageConverter} is selected and just before
* its write method is invoked.
*
* @param body the body to be written
* @param returnType the return type of the controller method
* @param selectedContentType the content type selected through content negotiation
* @param selectedConverterType the converter type selected to write to the response
* @param request the current request
* @param response the current response
* @return the body that was passed in or a modified (possibly new) instance
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if(body instanceof Result){ //发⽣异常之后,异常处理器⾥⾯返回的已经是Result了
return body;
}else if(body instanceof String){ //String属于特殊情况,需要单独处理,否则会报错
try {
return objectMapper.writeValueAsString(ResultUtils.success(body));
} catch (JsonProcessingException e) {
e.printStackTrace();
(ResultEnum.Code(), e.getMessage());
}
}
return ResultUtils.success(body);
}
}
⼆,有异常的情况下
service层为了⾃动回滚事务,会抛出⼀些⾃定义的RuntimeException。默认情况下,只有RuntimeException才会回滚事务。如果Controller⾥⾯直接处理service层抛出的异常,则Controller⾥⾯到处都是try catch块,代码会很难看。将异常集中在⼀个地⽅处理会好很多。
springboot中是通过@ControllerAdvice和@ExceptionHandler来完成统⼀异常处理的。这2个注解只能处理Controller和中抛出的异常,其他地⽅抛出的异常(⽐如Filter中抛出的异常),⽆法捕获。其他地⽅抛出的异常会转到/error的Controller⽅法来处理,默认是BasicErrorController来处理,为了能处理其他地⽅抛出的异常,我们会⾃定义ErrorController。
统⼀的异常处理类,处理Controller和抛出的异常
/**
* 统⼀的异常处理类
*/
@ControllerAdvice
public class MyExceptionHandler {
/**
* 转发到/error,表⽰由BasicErrorController处理,
* BasicErrorController是由springboot⾃动装配到容器中的
*/
/*@ExceptionHandler(BasicInfoException.class)
public String handleException(Exception ex, HttpServletRequest request){
request.setAttribute("status_code", 401);
request.setAttribute("exMsg", ex.getMessage());
return "forward:/error";
}*/
/
**
* 处理基本信息相关的异常
*/
@ExceptionHandler(BasicInfoException.class)
@ResponseBody
public Result handleBasicInfoException(BasicInfoException ex){
(ex.getCode(), ex.getMessage());
}
/**
* 处理测试数据相关的异常
*/
@ExceptionHandler(DetailsDataException.class)
@ResponseBody
public Result handleDetailsDataException(DetailsDataException ex){
(ex.getCode(), ex.getMessage());
}
/**
* 处理未知异常
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public Result handleUnKnowException(Exception ex){
(ResultEnum.Code(), ex.getMessage());
}
}
⾃定义的异常类⽰例
public class BasicInfoException extends RuntimeException {
private int code;
public BasicInfoException(int code, String msg){
super(msg);
}
public int getCode() {
return code;
}
}
处理其他地⽅抛出的异常(不是Controller和抛出的异常),⾃定义ErrorController /**
* ⾃定义ErrorController,处理其他地⽅抛出的异常(不是Controller和抛出的异常)
*/
@Controller
public class MyBasicErrorController extends AbstractErrorController {
private Logger logger = Class());
/**
* 可以通过@Value获取到
*/
@Value("${path}")
private String myPath;
private final ErrorProperties errorProperties;
private ErrorAttributes mErrorAttributes;
public MyBasicErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties) {
super(errorAttributes);
this.mErrorAttributes = errorAttributes;
}
//@RequestMapping(value = "/error")
@RequestMapping("${path}") //从properties⽂件中获取
@ResponseBody
public Result<Object> error(HttpServletRequest request) throws Throwable {
logger.debug("myPath = " + myPath);
//发⽣错误之后直接将异常抛出去,异常会到统⼀异常处理器中处理
WebRequest webRequest = new ServletWebRequest(request);
Throwable throwable = Error(webRequest).getCause();springboot和过滤器
throw throwable;
/*UserException ex;
if(throwable instanceof UserException){
ex = (UserException) throwable;
throw ex;
}else{
throw throwable;
}*/
/*HttpStatus status = getStatus(request);
if (status == HttpStatus.NO_CONTENT) {
(status.value(), status.name());
}
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); ((Integer) ("status"), (("message"));*/
}
/**
* Determine if the stacktrace attribute should be included.
* @param request the source request
* @param produces the media type produced (or {@code MediaType.ALL})
* @return if the stacktrace attribute should be included
*/
private boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) {
ErrorProperties.IncludeStacktrace include = getErrorProperties().getIncludeStacktrace();
if (include == ErrorProperties.IncludeStacktrace.ALWAYS) {
return true;
}
if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM) {
return getTraceParameter(request);
}
return false;
}
/**
* Provide access to the error properties.
* @return the error properties
*/
private ErrorProperties getErrorProperties() {
Properties;
}
/**
* Returns the path of the error page.
*
* @return the error path
*/
@Override
public String getErrorPath() {
Path();
}
}
⾃定义ErrorController中错误处理的⽅法中,也可以直接将异常抛出,这样异常就会交给统⼀异常处理器进⾏处理。
//@RequestMapping(value = "/error")
@RequestMapping("${path}") //从properties⽂件中获取
@ResponseBody
public Result<Object> error(HttpServletRequest request) throws Throwable {
logger.debug("myPath = " + myPath);
//发⽣错误之后直接将异常抛出去,异常会到统⼀异常处理器中处理
WebRequest webRequest = new ServletWebRequest(request);
Throwable throwable = Error(webRequest).getCause();
UserException ex;
if(throwable instanceof UserException){
ex = (UserException) throwable;
throw ex;
}else{
throw throwable;
}
/*HttpStatus status = getStatus(request);
if (status == HttpStatus.NO_CONTENT) {
(status.value(), status.name());
}
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
((Integer) ("status"), (("message"));*/
}
到此这篇关于springboot统⼀接⼝返回数据的实现的⽂章就介绍到这了,更多相关springboot统⼀接⼝返回数据内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论