springboot统一ajax返回数据格式,并且jquery ajax success函数修改
服务端代码:
package com.zhqn.sc.cfg; import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.zhqn.sc.entity.dto.ErrorModal; import com.zhqn.sc.entity.dto.ResponseInfo; import com.zhqn.sc.entity.dto.ScException; @ControllerAdvice public class ScResponseAdvise implements ResponseBodyAdvice<Object>{ @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { ResponseInfo responseInfo = new ResponseInfo(); if(body instanceof ErrorModal) { responseInfo.setSuccess(false); }else { responseInfo.setSuccess(true); } responseInfo.setData(body); if(selectedConverterType.equals(StringHttpMessageConverter.class)) { return handleString(responseInfo, response); } return responseInfo; } Object handleString(ResponseInfo responseInfo, ServerHttpResponse response) { ObjectMapper mapper = new ObjectMapper(); response.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8"); try { return mapper.writeValueAsString(responseInfo); } catch (JsonProcessingException e) { e.printStackTrace(); ScException.error(e.getMessage()); } return null; } }
package com.zhqn.sc.entity.dto; public class ResponseInfo { private boolean success; private Object data; public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } }
package com.zhqn.sc.entity.dto; import java.util.Date; public class ErrorModal { private Date date; private Integer code; private String errorStr; public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getErrorStr() { return errorStr; } public void setErrorStr(String errorStr) { this.errorStr = errorStr; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }
返回的数据格式是
{success : true , data : ResponseInfo}代表没有异常时的数据,
{success : false , data : ErrorModal}代表异常时的数据,有全局异常处理器处理返回的,这一步可以参考网上的教程。
这一切看似很完美,但是不管发生不发生异常,response的status都是200,前端jquery ajax函数都走的是success方法,这个函数设计初衷就是处理成功时的数据,失败应该走error方法,因此需要修改jquery ajax方法,可以用js aop思路处理,代码如下:
(function(win){ var ajax = $.ajax; $.ajax = function(a) { var oldSuccess = a && a.success && (typeof a.success == "function") ? a.success : null; var oldError = a && a.error && (typeof a.error == "function") ? a.error : null; var success = function(response) { if(response && "data" in response && "success" in response) { var res = response; arguments[0] = response.data; if(res.success == true) { oldSuccess && oldSuccess.apply(this, arguments); }else if(oldError){ oldError.apply(this, arguments); }else { alertError(res.data); } }else { arguments[0] = {errorStr : "数据格式错误!"}; } }; var error = function(data) { alertError(data); } if(a) { a.success = success; a.error = error; }else { arguments[0] = { success : success, error : error }; } ajax.apply(this, arguments); } function alertError(data) { if("status" in data && data.status == 403) { return; } alert(data.errorStr || data.responseJSON && data.responseJSON.errorStr || data.responseText || "服务器连接失败"); } $(document).ajaxError(function(event,xhr,options,exc){ if(xhr.status == 403 && xhr.getResponseHeader("redirectUrl")) { window.top.location.href = xhr.getResponseHeader("redirectUrl"); } }); })(window);
只要引入这段代码,原先的success,error都可以正常使用,另外$.get,$.post,$.getJSON,$.getScript都不会有问题,因为它们最后都要调用$.ajax。