SpringMVC異常統一処理データまたはビュービュービューを返す
28961 ワード
実装方法はSpringMVCブロッキングHandlerInterceptorブロッキング後に返されるデータまたはビューViewと一致しています.ここでは、コードリファレンスを貼ります.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
import org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
/**
* @author obiteaaron
* @since 2019/12/27
*/
@Component
public class SpringMvcExceptionHandlerResolver extends AbstractHandlerExceptionResolver implements ApplicationContextAware {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringMvcExceptionHandlerResolver.class);
private ApplicationContext applicationContext;
@Autowired
SpringMvcExceptionHandlerResolver.ExceptionHandler exceptionHandler = new SpringMvcExceptionHandlerResolver.ExceptionHandler() {
private String EXCEPTION_VIEW = "error";
@Override
public String getViewName(Exception ex) {
//
return EXCEPTION_VIEW;
}
@Override
public Object getResponseBody(Exception ex) {
//
if (ex instanceof IllegalArgumentException) {
throw new UnsupportedOperationException();
} else if (ex instanceof UnsupportedOperationException) {
throw new UnsupportedOperationException();
} else {
throw new UnsupportedOperationException();
}
}
};
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
try {
// ,
if (((HandlerMethod) handler).getMethodAnnotation(ResponseBody.class) != null) {
// json
HandlerMethod handlerMethod = new HandlerMethod(((HandlerMethod) handler).getBean(), ((HandlerMethod) handler).getMethod());
Object returnValue = exceptionHandler.getResponseBody(ex);
MethodParameter returnValueType = handlerMethod.getReturnValueType(returnValue);
applicationContext.getBean(RequestMappingHandlerAdapter.class).getReturnValueHandlers();
RequestResponseBodyMethodProcessor requestResponseBodyMethodProcessor = findRequestResponseBodyMethodProcessor();
requestResponseBodyMethodProcessor.handleReturnValue(returnValue, returnValueType, new ModelAndViewContainer(), new ServletWebRequest(request, response));
return new ModelAndView();
// end
} else {
//
HandlerMethod handlerMethod = new HandlerMethod(((HandlerMethod) handler).getBean(), ((HandlerMethod) handler).getMethod());
String viewName = exceptionHandler.getViewName(ex);
MethodParameter returnValueType = handlerMethod.getReturnValueType(viewName);
ViewNameMethodReturnValueHandler viewNameMethodReturnValueHandler = findViewNameMethodReturnValueHandler();
ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();
// viewNameMethodReturnValueHandler , , new ModelAndViewContainer() 。
viewNameMethodReturnValueHandler.handleReturnValue(viewName, returnValueType, modelAndViewContainer, new ServletWebRequest(request, response));
// ModelAndView Spring
ModelMap model = modelAndViewContainer.getModel();
ModelAndView modelAndView = new ModelAndView(modelAndViewContainer.getViewName(), model, modelAndViewContainer.getStatus());
exceptionHandler.fillModelAndView(ex, modelAndView);
return modelAndView;
// end
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private RequestResponseBodyMethodProcessor findRequestResponseBodyMethodProcessor() {
RequestMappingHandlerAdapter requestMappingHandlerAdapter = applicationContext.getBean(RequestMappingHandlerAdapter.class);
for (HandlerMethodReturnValueHandler value : Objects.requireNonNull(requestMappingHandlerAdapter.getReturnValueHandlers())) {
if (value instanceof RequestResponseBodyMethodProcessor) {
return (RequestResponseBodyMethodProcessor) value;
}
}
// SpringMVC
throw new UnsupportedOperationException("cannot find RequestResponseBodyMethodProcessor from RequestMappingHandlerAdapter by Spring Context.");
}
private ViewNameMethodReturnValueHandler findViewNameMethodReturnValueHandler() {
RequestMappingHandlerAdapter requestMappingHandlerAdapter = applicationContext.getBean(RequestMappingHandlerAdapter.class);
for (HandlerMethodReturnValueHandler value : Objects.requireNonNull(requestMappingHandlerAdapter.getReturnValueHandlers())) {
if (value instanceof ViewNameMethodReturnValueHandler) {
return (ViewNameMethodReturnValueHandler) value;
}
}
// SpringMVC
throw new UnsupportedOperationException("cannot find ViewNameMethodReturnValueHandler from RequestMappingHandlerAdapter by Spring Context.");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public interface ExceptionHandler {
/**
*
*
* @param ex
* @see ModelAndView
* @see ViewNameMethodReturnValueHandler
*/
String getViewName(Exception ex);
/**
*
*
* @param ex
* @see ModelAndView
* @see ViewNameMethodReturnValueHandler
*/
default void fillModelAndView(Exception ex, ModelAndView modelAndView) {
}
/**
*
*
* @param ex
* @see ResponseBody
* @see RequestResponseBodyMethodProcessor
*/
Object getResponseBody(Exception ex);
}
}