首页 > 解决方案 > 是否可以在没有堆栈跟踪的情况下抛出自定义异常?

问题描述

在我的应用程序中,我使用 AngularJS 作为前端,使用 Java 作为后端。每当我需要在前端面板中显示自定义错误时,我都会使用自定义异常从 Java 中抛出,在 Angular 中,我将得到它作为响应并使用 javascript 构建消息。此自定义异常是一种常见异常,因此在服务器日志中,正在捕获整个堆栈跟踪。我处于应该存在 throw 并且不应该打印堆栈跟踪的情况。我想到了。但是,在抛出之后,当它需要在抛出后实际停止时,它会继续事务。有很多复杂的代码,我只在需要时粘贴必要的代码。

 List<GenericException> failedValidations = new ArrayList<>();
 if (CollectionUtils.isNotEmpty(failedValidations)) {
        String failedValidationErrorCode = Util.convertListToString(failedValidations.stream().map(GenericException::getCode).collect(Collectors.toList()));
        throw new ReservationException("Exception thrown with error codes :"+ failedValidationErrorCode, failedValidations);
    }

现在,当这个错误被抛出时,

com.abc.def.exceptions.ReservationException: Exception thrown with error codes :5965
at com.abc.def.service.impl.ReservationImpl.validateStepOne(ReservationImpl.java:1038)
at com.abc.def.service.impl.ReservationImpl.validateStepOne(ReservationImpl.java:3226)
at sun.reflect.GeneratedMethodAccessor7611.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy1629.validateStepOne(Unknown Source)
at com.abc.def.controller.ReservationController.validateStepOne(ReservationController.java:605)
at sun.reflect.GeneratedMethodAccessor7610.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:870)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:751)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:844)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:280)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:254)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:136)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:346)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at weblogic.websocket.tyrus.TyrusServletFilter.doFilter(TyrusServletFilter.java:215)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at weblogicx.servlet.gzip.filter.GZIPFilter.doFilter(GZIPFilter.java:70)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at com.abc.def.config.InboxFilter.doFilter(InboxFilter.java:42)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at com.abc.def.config.CorsFilter.doFilter(CorsFilter.java:38)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at com.abc.def.config.PFCLoginFilter.doFilter(PFCLoginFilter.java:132)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3456)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3422)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:323)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)
at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2280)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2196)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2174)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1632)
at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:256)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:311)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:263)> 

考虑在服务器日志中一天打印 1000 次。我只需要在服务器日志中打印第一行。那是,

 com.abc.def.exceptions.ReservationException: Exception thrown with error codes :5965

如果只有错误代码,那对于调试来说已经绰绰有余了。我知道这是一个很长的问题,请帮助我解决这个问题。

标签: javaspringjava-8

解决方案


您已经在使用 spring mvc(请参阅包含 spring mvc 类的堆栈跟踪)

如果是这样,最好的选择可能是在 Contoller Advice 级别或spring MVC 支持的任何其他异常处理机制级别捕获异常。

基本上堆栈跟踪仅在没有人(控制器、建议或服务)捕获它的情况下由 spring mvc 引擎本身打印。

从角度来看,没有例外。相反,您会使用一些默认 JSON 获得非 200 状态,这是 HTTP 格式的响应,不是例外,而只是某种特定类型的响应。所以我相信最好的办法是为到达客户端的消息建立一些协议,显然服务器堆栈跟踪不是要发送给客户端的东西。

这是一种约定,可能包括:

  1. HTTP 状态(非 200 以区分错误和常规答案)
  2. 预定义格式的 JSONmessage:
  • 异常 ID
  • 服务器上的时间
  • 信息
  • 客户端映射的参数
  • I18n 相关信息(如果与您的申请相关)。

长话短说:

  • 您创建一个控制器建议并在那里映射自定义异常
  • 映射方法将创建一个“协议”json 并将其返回给 angular。
  • 如果之前没有人捕获到异常,spring 会自动调用这个映射方法。
  • 由于映射方法将处理异常,因此它不会打印在服务器的控制台上,这正是您想要实现的。
  • 客户端将获取 json 并将创建一些处理所有消息的角度“基础设施”代码(可能在屏幕顶部显示消息,弹出任何内容)。

推荐阅读