Commit a48eb8ce authored by trumansdo's avatar trumansdo
Browse files

调整统一异常输出

预计重新处理分页查询
parent 7e972199
......@@ -165,7 +165,6 @@ public class UserConsoleController {
@Function("user.query")
@ResponseBody
public JsonResult<PageQuery<CoreUser>> index(UserQuery condtion) {
PageQuery<CoreUser> page = condtion.getPageQuery();
userConsoleService.queryByCondtion(page);
return JsonResult.success(page);
......
......@@ -3,30 +3,45 @@ package com.ibeetl.admin.core.conf;
import static cn.hutool.system.SystemUtil.LINE_SEPRATOR;
import static java.lang.String.format;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.dialect.Props;
import cn.hutool.system.SystemUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ibeetl.admin.core.util.FormFieldException;
import com.ibeetl.admin.core.util.PlatformException;
import com.ibeetl.admin.core.web.JsonResult;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;
/**
......@@ -41,63 +56,138 @@ public class CustomErrorController extends AbstractErrorController {
private Logger logger = LoggerFactory.getLogger(CustomErrorController.class);
private final DefaultErrorAttributes defaultErrorAttributes;
@Autowired ObjectMapper objectMapper;
public CustomErrorController() {
super(new DefaultErrorAttributes());
public CustomErrorController(DefaultErrorAttributes defaultErrorAttributes) {
super(defaultErrorAttributes);
this.defaultErrorAttributes = defaultErrorAttributes;
}
@RequestMapping(ERROR_PATH)
public ModelAndView getErrorPath(HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(request, false));
Throwable cause = getCause(request);
int status = (Integer) model.get("status");
// 错误信息
// String message = (String) model.get("message");
// 友好提示
String errorMessage = getErrorMessage(cause);
String requestPath = (String) model.get("path");
/*参数错误*/
List<FieldError> filedErrors = this.getFieldError(model, cause);
Throwable cause = getRealException(request);
Map<String, Object> errorInfo = wrapErrorInfo(request);
// 后台打印日志信息方方便查错
prettyLog(model, cause, filedErrors);
response.setStatus(status);
if (!isJsonRequest(request)) {
ModelAndView view = new ModelAndView("/error.html");
view.addAllObjects(model);
view.addObject("errorMessage", errorMessage);
view.addObject("filedErrors", filedErrors);
view.addObject("cause", cause);
view.addObject("requestPath", requestPath);
return view;
prettyLog(errorInfo);
response.setStatus(Convert.toInt(errorInfo.get("status")));
if (cause instanceof PlatformException) {
return hanlderPlatformException(errorInfo, response);
} else if (cause instanceof ConstraintViolationException) {
return hanlderConstraintViolationException(errorInfo, request, response);
} else {
if (filedErrors == null) {
if (status == 404) {
writeJson(response, JsonResult.http404(requestPath));
} else {
writeJson(response, JsonResult.failMessage(getErrorMessage(cause)));
}
return hanlderGeneralException(errorInfo, response);
}
}
private ModelAndView hanlderGeneralException(
Map<String, Object> errorInfo, HttpServletResponse response) {
ModelAndView modelAndView = handlerHtml(errorInfo);
if (modelAndView != null) {
modelAndView.addObject("errorMessage", "服务器内部错误,请联系管理员");
} else {
handlerAjax(errorInfo, response);
}
return modelAndView;
}
private ModelAndView hanlderConstraintViolationException(
Map<String, Object> errorInfo, HttpServletRequest request, HttpServletResponse response) {
ModelAndView modelAndView = handlerHtml(errorInfo);
if (modelAndView != null) {
modelAndView.addObject("errorMessage", "服务器内部错误,请联系管理员");
logger.error("方法参数校验失败,请查看上述详细信息");
} else {
if (Convert.toInt(errorInfo.get("status")).equals(HttpStatus.NOT_FOUND.value())) {
writeJson(response, JsonResult.http404(errorInfo.get("path")));
} else {
writeJson(response, JsonResult.fail(this.wrapFieldErrors(filedErrors)));
ConstraintViolationException constraintViolationException =
(ConstraintViolationException) getRealException(request);
Set<ConstraintViolation<?>> constraintViolations =
constraintViolationException.getConstraintViolations();
List<String> messages = CollUtil.<String>newArrayList();
for (ConstraintViolation<?> violation : constraintViolations) {
String msg = violation.getPropertyPath().toString() + violation.getMessage();
messages.add(msg);
}
writeJson(response, JsonResult.fail(messages));
}
return null;
}
return modelAndView;
}
private ModelAndView hanlderPlatformException(
Map<String, Object> errorInfo, HttpServletResponse response) {
ModelAndView modelAndView = handlerHtml(errorInfo);
if (modelAndView != null) {
modelAndView.addObject("errorMessage", errorInfo.get("message"));
} else {
handlerAjax(errorInfo, response);
}
return modelAndView;
}
/**
* 通用处理页面请求方法
*
* @param errorInfo
* @return
*/
protected ModelAndView handlerHtml(Map<String, Object> errorInfo) {
ModelAndView view = null;
if (!Convert.toBool(errorInfo.get("isAjax"))) {
view = new ModelAndView("/error.html");
view.addAllObjects(errorInfo);
view.addObject("filedErrors", errorInfo.get("errors"));
view.addObject("cause", errorInfo.get("exception"));
view.addObject("requestPath", errorInfo.get("path"));
}
return view;
}
protected void handlerAjax(Map<String, Object> errorInfo, HttpServletResponse response) {
if (Convert.toInt(errorInfo.get("status")).equals(HttpStatus.NOT_FOUND.value())) {
writeJson(response, JsonResult.http404(errorInfo.get("path")));
} else {
writeJson(
response, JsonResult.failMessage(errorInfo.getOrDefault("message", "无错误信息").toString()));
}
}
protected void prettyLog(Map model, Throwable cause, List<FieldError> filedErrors) {
Object path = model.get("path");
Object status = model.get("status");
Object message = model.get("message");
/**
* 提取errorAttributes 中的错误信息,包括:<br>
* timestamp:时间<br>
* status:http响应码<br>
* error:响应码的原因<br>
* exception:异常类名<br>
* errors:controller可能的校验错误对象集合<br>
* message:controller的错误信息<br>
* trace: 异常的堆栈信息<br>
* path:请求路径<br>
*
* @param request
* @return
*/
protected Map<String, Object> wrapErrorInfo(HttpServletRequest request) {
Map<String, Object> errorAttributes = super.getErrorAttributes(request, true);
errorAttributes.put("isAjax", isJsonRequest(request));
return Collections.unmodifiableMap(errorAttributes);
}
protected void prettyLog(Map errorInfo) {
Object path = errorInfo.get("path");
Object status = errorInfo.get("status");
Object message = errorInfo.get("message");
Object errors = errorInfo.get("errors");
Object cause = errorInfo.get("exception");
StringBuilder log = new StringBuilder();
log.append(SystemUtil.get(LINE_SEPRATOR))
.append(StrUtil.format("┏━━━━ response status: <{}> ━━━━", status))
.append(SystemUtil.get(LINE_SEPRATOR))
.append(StrUtil.format("┣━━━━ error message: <{}> ━━━━", message))
.append(SystemUtil.get(LINE_SEPRATOR))
.append(StrUtil.format("┣━━━━ error fileds: <{}> ━━━━", filedErrors))
.append(StrUtil.format("┣━━━━ error fileds: <{}> ━━━━", errors))
.append(SystemUtil.get(LINE_SEPRATOR))
.append(StrUtil.format("┗━━━━ error cause: <{}> ━━━━", cause))
.append(SystemUtil.get(LINE_SEPRATOR))
......@@ -105,29 +195,6 @@ public class CustomErrorController extends AbstractErrorController {
logger.error(log.toString());
}
protected List<FieldError> getFieldError(Map<String, Object> model, Throwable cause) {
List<FieldError> filedErrors = (List<FieldError>) model.get("errors");
if (filedErrors != null) {
return filedErrors;
}
if (cause instanceof FormFieldException) {
FormFieldException fe = (FormFieldException) cause;
return fe.getErrors();
}
return null;
}
protected List<Map<String, String>> wrapFieldErrors(List<FieldError> errors) {
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
for (FieldError e : errors) {
Map<String, String> error = new HashMap<String, String>();
error.put("field", e.getField());
error.put("message", e.getDefaultMessage());
list.add(error);
}
return list;
}
/**
* json请求,要么是.json后缀的请求,要么是http请求报文中规定的json请求
*
......@@ -145,8 +212,15 @@ public class CustomErrorController extends AbstractErrorController {
}
}
/**
* json响应的输出流方式
*
* @param response
* @param error
*/
protected void writeJson(HttpServletResponse response, JsonResult error) {
response.setContentType("application/json;charset=utf-8");
response.addHeader(HttpHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE);
response.addHeader(HttpHeaders.ACCEPT_CHARSET, CharsetUtil.UTF_8);
try {
response.getWriter().write(objectMapper.writeValueAsString(error));
} catch (IOException e) {
......@@ -154,16 +228,13 @@ public class CustomErrorController extends AbstractErrorController {
}
}
protected String getErrorMessage(Throwable ex) {
if (ex instanceof PlatformException) {
return ex.getMessage();
} else {
return "服务器错误,请联系管理员";
}
}
protected Throwable getCause(HttpServletRequest request) {
/**
* 获取真正的异常,而不是被tomcat等包装的异常
*
* @param request
* @return
*/
protected Throwable getRealException(HttpServletRequest request) {
Throwable error = (Throwable) request.getAttribute("javax.servlet.error.exception");
if (error != null) {
while (error instanceof ServletException && error.getCause() != null) {
......
......@@ -112,7 +112,9 @@ class CustomJsonResultSerializer extends JsonSerializer<JsonResult> {
Object data = value.getData();
if (data instanceof PageQuery) {
PageQuery query = (PageQuery) (data);
/*可能叫法不一样,所以返回两种命名*/
gen.writeNumberField("count", query.getTotalRow());
gen.writeNumberField("total", query.getTotalRow());
gen.writeObjectField("data", query.getList());
} else {
gen.writeObjectField("data", data);
......
......@@ -3,8 +3,10 @@ package com.ibeetl.admin.core.conf;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.apache.commons.digester3.RegexRules;
import org.hibernate.validator.HibernateValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
......@@ -39,4 +41,10 @@ public class SpringConfiguration {
postProcessor.setValidator(validator);
return postProcessor;
}
@Bean
public DefaultErrorAttributes defaultErrorAttributes(){
DefaultErrorAttributes defaultErrorAttributes = new DefaultErrorAttributes(true);
return defaultErrorAttributes;
}
}
......@@ -48,6 +48,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
/**
* 切勿在此配置类中向SpringMVC中添加bean。
* 也就是不要 @Bean这类方法。
* 会出现无法ServletContext注入null,因为父接口的原因
* */
@Configuration
public class SpringWebMvcConfigurer implements WebMvcConfigurer, InitializingBean {
......
<!--
* @Author: 一日看尽长安花
* @since: 2019-10-12 16:14:37
* @LastEditTime: 2019-10-27 23:14:25
* @LastEditTime: 2019-11-04 21:06:33
* @LastEditors: 一日看尽长安花
* @Description:
-->
......@@ -113,6 +113,10 @@ export default {
cloneTableData: null
};
},
updated() {
console.log(this.metedata);
console.log(this.tabledata);
},
methods: {
searchTable() {
// 要用一个临时数据将当前页面的数据保存下来,不然 $emit 会将原数据修改
......
<!--
* @Author: 一日看尽长安花
* @since: 2019-10-12 15:43:18
* @LastEditTime: 2019-10-19 20:49:38
* @LastEditTime: 2019-11-04 21:00:21
* @LastEditors: 一日看尽长安花
* @Description:
-->
......
<!--
* @Author: 一日看尽长安花
* @since: 2019-10-12 15:43:18
* @LastEditTime: 2019-10-27 22:49:20
* @LastEditTime: 2019-11-04 23:25:52
* @LastEditors: 一日看尽长安花
* @Description:
-->
......@@ -43,7 +43,7 @@ export default {
computed: {},
mounted() {
this.obtainMetedata();
this.obtainData();
this.obtainData({ page: 1, limit: 10 });
},
methods: {
obtainMetedata() {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment