@Override protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object _handler, Exception ex) { HandlerMethod handler = (HandlerMethod) _handler; if (handler == null) { return null; } Method method = handler.getMethod(); if (method.isAnnotationPresent(JsonBody.class) && ex != null) { logger.error("server is error", ex); Object value = null; if (ex instanceof ServiceException) { value = new JsonResult<Object>(((ServiceException) ex).getCode(), ex.getMessage()); } else { value = new JsonResult<Object>(-1, ex.getMessage()); } try { JsonUtil.writeValue(response.getWriter(), value); } catch (IOException e) { Throwables.propagateIfPossible(e); } return ModelAndViewResolver.UNRESOLVED; } return null; }
@Test public void mavResolver() throws ServletException, IOException { initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() { @Override public void initialize(GenericWebApplicationContext wac) { RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class); ModelAndViewResolver[] mavResolvers = new ModelAndViewResolver[] {new MyModelAndViewResolver()}; adapterDef.getPropertyValues().add("modelAndViewResolvers", mavResolvers); wac.registerBeanDefinition("handlerAdapter", adapterDef); } }, ModelAndViewResolverController.class); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); MockHttpServletResponse response = new MockHttpServletResponse(); getServlet().service(request, response); assertEquals("myValue", response.getContentAsString()); }
@Override protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object _handler, Exception ex) { LOGGER.info("jsonBody exception...."); HandlerMethod handler = (HandlerMethod) _handler; if (handler == null) { // like 'GET' not supported return null; } Method method = handler.getMethod(); if (method.isAnnotationPresent(JsonBody.class)) { // String config = super.determineViewName(ex, request); // Object value = Strings.isNullOrEmpty(config) ? ex : JsonSerializer.parseConfig(config, ex); JsonSerializer.write(ex, method, request, response); // skip other resolver and view render return ModelAndViewResolver.UNRESOLVED; } return null; }
@Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { if (this.mavResolvers != null) { for (ModelAndViewResolver mavResolver : this.mavResolvers) { Class<?> handlerType = returnType.getContainingClass(); Method method = returnType.getMethod(); ExtendedModelMap model = (ExtendedModelMap) mavContainer.getModel(); ModelAndView mav = mavResolver.resolveModelAndView(method, handlerType, returnValue, model, webRequest); if (mav != ModelAndViewResolver.UNRESOLVED) { mavContainer.addAllAttributes(mav.getModel()); mavContainer.setViewName(mav.getViewName()); if (!mav.isReference()) { mavContainer.setView(mav.getView()); } return; } } } // No suitable ModelAndViewResolver... if (this.modelAttributeProcessor.supportsReturnType(returnType)) { this.modelAttributeProcessor.handleReturnValue(returnValue, returnType, mavContainer, webRequest); } else { throw new UnsupportedOperationException("Unexpected return type: " + returnType.getParameterType().getName() + " in method: " + returnType.getMethod()); } }
@Before public void setUp() { mavResolvers = new ArrayList<ModelAndViewResolver>(); handler = new ModelAndViewResolverMethodReturnValueHandler(mavResolvers); mavContainer = new ModelAndViewContainer(); request = new ServletWebRequest(new MockHttpServletRequest()); }
@Override @SuppressWarnings("rawtypes") public ModelAndView resolveModelAndView(Method method, Class handlerType, Object returnValue, ExtendedModelMap model, NativeWebRequest request) { if (returnValue != null && returnValue.getClass().equals(returnValueType)) { return new ModelAndView("viewName", "modelAttrName", returnValue); } else { return ModelAndViewResolver.UNRESOLVED; } }
public void handleReturnValue( Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest request) throws Exception { if (this.mavResolvers != null) { for (ModelAndViewResolver mavResolver : this.mavResolvers) { Class<?> handlerType = returnType.getDeclaringClass(); Method method = returnType.getMethod(); ExtendedModelMap model = (ExtendedModelMap) mavContainer.getModel(); ModelAndView mav = mavResolver.resolveModelAndView(method, handlerType, returnValue, model, request); if (mav != ModelAndViewResolver.UNRESOLVED) { mavContainer.addAllAttributes(mav.getModel()); mavContainer.setViewName(mav.getViewName()); if (!mav.isReference()) { mavContainer.setView(mav.getView()); } return; } } } // No suitable ModelAndViewResolver.. if (this.modelAttributeProcessor.supportsReturnType(returnType)) { this.modelAttributeProcessor.handleReturnValue(returnValue, returnType, mavContainer, request); } else { throw new UnsupportedOperationException("Unexpected return type: " + returnType.getParameterType().getName() + " in method: " + returnType.getMethod()); } }
/** * Return the configured {@link ModelAndViewResolver}s, or {@code null}. */ public List<ModelAndViewResolver> getModelAndViewResolvers() { return modelAndViewResolvers; }
/** * Create a new instance. */ public ModelAndViewResolverMethodReturnValueHandler(List<ModelAndViewResolver> mavResolvers) { this.mavResolvers = mavResolvers; }
/** * Set a custom ModelAndViewResolvers to use for special method return types. * Such a custom ModelAndViewResolver will kick in first, having a chance to * resolve an return value before the standard ModelAndView handling kicks in. */ public void setCustomModelAndViewResolver(ModelAndViewResolver customModelAndViewResolver) { this.customModelAndViewResolvers = new ModelAndViewResolver[]{customModelAndViewResolver}; }
/** * Set one or more custom ModelAndViewResolvers to use for special method return types. * Any such custom ModelAndViewResolver will kick in first, having a chance to * resolve an return value before the standard ModelAndView handling kicks in. */ public void setCustomModelAndViewResolvers(ModelAndViewResolver... customModelAndViewResolvers) { this.customModelAndViewResolvers = customModelAndViewResolvers; }
/** * Provide custom {@link ModelAndViewResolver}s. * <p><strong>Note:</strong> This method is available for backwards * compatibility only. However, it is recommended to re-write a * {@code ModelAndViewResolver} as {@link HandlerMethodReturnValueHandler}. * An adapter between the two interfaces is not possible since the * {@link HandlerMethodReturnValueHandler#supportsReturnType} method * cannot be implemented. Hence {@code ModelAndViewResolver}s are limited * to always being invoked at the end after all other return value * handlers have been given a chance. * <p>A {@code HandlerMethodReturnValueHandler} provides better access to * the return type and controller method information and can be ordered * freely relative to other return value handlers. */ public void setModelAndViewResolvers(List<ModelAndViewResolver> modelAndViewResolvers) { this.modelAndViewResolvers = modelAndViewResolvers; }
/** * Set one or more custom ModelAndViewResolvers to use for special method return types. * Any such custom ModelAndViewResolver will kick in first, having a chance to * resolve an return value before the standard ModelAndView handling kicks in. */ public void setCustomModelAndViewResolvers(ModelAndViewResolver[] customModelAndViewResolvers) { this.customModelAndViewResolvers = customModelAndViewResolvers; }
/** * Set a custom ModelAndViewResolvers to use for special method return * types. * <p> * Such a custom ModelAndViewResolver will kick in first, having a chance to * resolve a return value before the standard ModelAndView handling kicks * in. */ public void setCustomModelAndViewResolver( ModelAndViewResolver customModelAndViewResolver) { this.customModelAndViewResolvers = new ModelAndViewResolver[] { customModelAndViewResolver }; }
/** * Set one or more custom ModelAndViewResolvers to use for special method * return types. * <p> * Any such custom ModelAndViewResolver will kick in first, having a chance * to resolve a return value before the standard ModelAndView handling kicks * in. */ public void setCustomModelAndViewResolvers( ModelAndViewResolver[] customModelAndViewResolvers) { this.customModelAndViewResolvers = customModelAndViewResolvers; }