是否有可能引发没有堆栈跟踪的自定义异常?

时间:2020-07-14 10:47:42

标签: java spring java-8

在我的应用程序中,我使用AngularJS作为前端,使用Java作为后端。每当我需要在前端面板中显示自定义错误时,我都会使用Custom Exception从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

如果仅存在错误代码,则对于调试而言已绰绰有余。 我知道这是一个很长的问题,请帮助我解决这个问题。

3 个答案:

答案 0 :(得分:3)

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

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

基本上,只有在没有人(控制器,建议或服务)抓住它的情况下,Spring mvc引擎才会打印堆栈跟踪。

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

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

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

长话短说:

  • 您创建控制器建议并在其中映射自定义异常
  • 映射方法将创建一个“协议” json,并将其返回为angular。
  • 如果之前没有人捕获到异常,spring将自动调用此映射方法。
  • 由于映射方法将处理异常,因此不会在服务器的控制台上打印出来,这是您要达到的目的。
  • 客户端将获取json并将创建用于处理所有消息的有角度的“基础结构”代码(也许将消息显示在屏幕顶部,然后弹出)。

答案 1 :(得分:1)

您可以用一个空数组替换stacktrace。

public ReservationException(String message, List<GenericException> failedValidations) {
    super(message);
    this.setStackTrace(new StackTraceElement[0]);

    // Alternative: Keep the method where the exception was thrown.
 // this.setStackTrace(Arrays.copyOf(this.getStackTrace(), 1)); 
}

仅打印

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

调用Throwable::printStackTrace()时。

但是,最好按照Mark Bramnik的建议,将记录器或弹簧配置为不打印堆栈跟踪信息,因为您会通过删除堆栈跟踪信息而失去进行故障排除的宝贵信息。

答案 2 :(得分:0)

尝试创建自定义异常处理程序,您可以决定在抛出指定的异常后应该记录什么。

https://www.baeldung.com/exception-handling-for-rest-with-spring