spring3升級到spring4通用異常處理返回jsonp多了/**/的解決辦法
阿新 • • 發佈:2018-08-03
static lte 彈出 protected rar temp model *** col
問題描述
在spring3中定義了通用的異常處理,具體代碼如下:
public class CommonExceptionHandler implements HandlerExceptionResolver { private static final Logger logger = LoggerFactory.getLogger(CommonExceptionHandler.class); @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ModelAndView mv= new ModelAndView(); Map<String,Object> model=new HashMap(); mv.addObject("code", 0); model.put("errorCode", 0); model.put("errorMessage", "系統異常"); logger.info("未捕獲處理異常日誌開始:"); logger.info(ex.toString()); logger.error("System error",ex); mv.addObject("model",model); return mv; } }
<bean id="exceptionResolver" class="com.******.exception.CommonExceptionHandler" />
因為項目前後端分離,前端使用jsonp讀取api數據,spring升級後發現如果出現異常前端js沒有彈出提示,調試發現返回的數據中多了/**/。
/**/jQuery172038147174217261703_1533279228074({******});
分析問題
跟蹤源代碼調試進入DispatcherServlet:
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception { boolean errorView = false; if (exception != null) { if (exception instanceof ModelAndViewDefiningException) { this.logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException)exception).getModelAndView(); } else { Object handler = mappedHandler != null ? mappedHandler.getHandler() : null; mv = this.processHandlerException(request, response, handler, exception); errorView = mv != null; } } if (mv != null && !mv.wasCleared()) { this.render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else if (this.logger.isDebugEnabled()) { this.logger.debug("Null ModelAndView returned to DispatcherServlet with name ‘" + this.getServletName() + "‘: assuming HandlerAdapter completed request handling"); } if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, (Exception)null); } } }
繼續跟蹤進入錯誤處理,然後進入render方法:
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { Locale locale = this.localeResolver.resolveLocale(request); response.setLocale(locale); View view; if (mv.isReference()) { view = this.resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException("Could not resolve view with name ‘" + mv.getViewName() + "‘ in servlet with name ‘" + this.getServletName() + "‘"); } } else { view = mv.getView(); if (view == null) { throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a View object in servlet with name ‘" + this.getServletName() + "‘"); } } if (this.logger.isDebugEnabled()) { this.logger.debug("Rendering view [" + view + "] in DispatcherServlet with name ‘" + this.getServletName() + "‘"); } try { if (mv.getStatus() != null) { response.setStatus(mv.getStatus().value()); } view.render(mv.getModelInternal(), request, response); } catch (Exception var7) { if (this.logger.isDebugEnabled()) { this.logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name ‘" + this.getServletName() + "‘", var7); } throw var7; } }
然後進入AbstractView裏面的render方法:
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { if (this.logger.isTraceEnabled()) { this.logger.trace("Rendering view with name ‘" + this.beanName + "‘ with model " + model + " and static attributes " + this.staticAttributes); } Map<String, Object> mergedModel = this.createMergedOutputModel(model, request, response); this.prepareResponse(request, response); this.renderMergedOutputModel(mergedModel, this.getRequestToExpose(request), response); }
this.renderMergedOutputModel發現是一個abstract方法,繼續追蹤實現類AbstractJackson2View:
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { OutputStream stream = this.updateContentLength ? this.createTemporaryOutputStream() : response.getOutputStream(); Object value = this.filterAndWrapModel(model, request); this.writeContent((OutputStream)stream, value); if (this.updateContentLength) { this.writeToResponse(response, (ByteArrayOutputStream)stream); } }
繼續跟蹤 this.writeContent:
protected void writeContent(OutputStream stream, Object object) throws IOException { JsonGenerator generator = this.objectMapper.getFactory().createGenerator(stream, this.encoding); this.writePrefix(generator, object); Class<?> serializationView = null; FilterProvider filters = null; Object value = object; if (object instanceof MappingJacksonValue) { MappingJacksonValue container = (MappingJacksonValue)object; value = container.getValue(); serializationView = container.getSerializationView(); filters = container.getFilters(); } if (serializationView != null) { this.objectMapper.writerWithView(serializationView).writeValue(generator, value); } else if (filters != null) { this.objectMapper.writer(filters).writeValue(generator, value); } else { this.objectMapper.writeValue(generator, value); } this.writeSuffix(generator, object); generator.flush(); }
繼續跟蹤 this.writePrefix,發現是一個未實現的方法,子類具有重寫,繼續跟蹤 MappingJackson2JsonView :
protected void writePrefix(JsonGenerator generator, Object object) throws IOException { if (this.jsonPrefix != null) { generator.writeRaw(this.jsonPrefix); } String jsonpFunction = null; if (object instanceof MappingJacksonValue) { jsonpFunction = ((MappingJacksonValue)object).getJsonpFunction(); } if (jsonpFunction != null) { generator.writeRaw("/**/"); generator.writeRaw(jsonpFunction + "("); } }
原來問題是出現在這裏
spring3升級到spring4通用異常處理返回jsonp多了/**/的解決辦法