我开发了一个日志系统和错误处理,想记录请求响应日志、业务层日志和错误日志,但是当我加入上传过程时,出现了一个错误,提示我类型转换失败,另外,像这样设计日志和错误处理是正确的吗,比如把请求响应放在拦截器中统一的返回值和错误处理使用controlleradvice
下面是我实现的代码
这是过滤器
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
filterChain.doFilter(requestWrapper,responseWrapper);
responseWrapper.copyBodyToResponse();
}
这个loginterceptor
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.sss");
String dateFormat = format.format(date);
makeLog(dateFormat, request, (ContentCachingResponseWrapper) response);
return true;
}
private void makeLog(String date,HttpServletRequest request,ContentCachingResponseWrapper response) throws IOException {
String responseData = new String(response.getContentAsByteArray());
LogInfo logInfo = new LogInfo();
logInfo.setUri(request.getRequestURI());
logInfo.setCreateTime(date);
logInfo.setRequest(request.getInputStream().readAllBytes());
logInfo.setResponse(responseData);
logInfo.setClientIP(request.getRemoteAddr());
log.info("logData:{}",logInfo);
loggerService.insert(logInfo);
}
这是exceptioncontroller
public class ExceptionAdvice {
@ExceptionHandler(DataAccessException.class)
public ResultVO sqlHandler(DataAccessException e){
Throwable cause = e.getCause();
ResultVO resultVO = new ResultVO();
if (cause instanceof SQLException sqlException){
log.error(sqlException.getMessage());
resultVO.setCode(sqlException.getSQLState());
resultVO.setMessage(sqlException.getMessage());
}else {
resultVO.setMessage(cause.getMessage());
}
return resultVO;
}
@ExceptionHandler(BusinessException.class)
public ResultVO businessHandler(BusinessException e){
log.error(e.getMessage());
ResultVO resultVO = new ResultVO();
resultVO.setCode(e.getErrCode().getCode());
resultVO.setMessage(e.getErrCode().getMsg());
return resultVO;
}
@ExceptionHandler(Exception.class)
public ResultVO err(Exception e){
log.error(e.getMessage());
e.printStackTrace();
ResultVO resultVO = new ResultVO();
resultVO.setCode("500");
resultVO.setMessage(e.getMessage());
return resultVO;
}
这是结果
public class ResultAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
//System.out.println("====================================================supports");
return !returnType.getParameterType().equals(ResultVO.class);
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
System.out.println("====================================================beforeBodyWrite");
ResultVO resultVO = new ResultVO(body);
resultVO.setCode("1");
resultVO.setMessage("success!!");
return resultVO;
}
当我在运行时,他的错误是没有预料到的,比如数据库连接失败,他从mybatis报告了一个错误“org. springframework. jdbc. CannotGetJdbcConnectionException:无法获取JDBC连接r n # #错误可能存在于com/kert/compute/dao/LogMapper. java(最佳猜测)”\r\n###错误可能涉及com.kert.compute.dao.LogMapper.insert\r\n###执行更新时出错\r\n###原因:无法获取数据库连接异常:无法获取JDBC连接”,
上传文件时,报告“class org. apache. Catalina . connector. ResponseFacade cannot be cast to class org. springframework. web. util. ContentCachingResponseWrapper(org. apache. catalina. connector. ResponseFacade and org. springframework. web. util. ContentCachingResponseWrapper are in unnamed module of loader 'app')”消息
1条答案
按热度按时间omhiaaxx1#
关于您遇到的错误的第一个问题,该错误似乎是由尝试将ResponseFacade强制转换为ContentCachingResponseWrapper时的类型转换失败引起的。这可能是因为ResponseFacade类与ContentCachingResponseWrapper类不兼容,或者因为ContentCachingResponseWrapper类在拦截器中使用之前未正确示例化。要解决此问题,您可能需要检查您的实现,并确保使用了适当的类并正确地示例化。
至于你的第二个问题,关于你的日志系统和错误处理的设计,你的方法似乎是合理的。将请求响应放置在拦截器中,并在业务层使用AOP进行处理,是日志和错误处理的常见模式。使用控制器通知进行统一的返回值和错误处理也是一个很好的实践。然而确保你的实现是模块化的并且易于维护是很重要的。你也可以考虑使用一个日志框架,比如Log4j或者Logback来简化你的日志实现,并提供更高级的特性。