常规的写法,就是使用@ControllerAdvice,这个Spring与SpringBoot通用。
@ControllerAdvice实际上是有参数的,可以选择指定的包名,或许,你希望异常切面直接作用于全局,那么,你也可以尝试使用HandlerExceptionResolver。
/** * Controller异常切面 * * @author postm */ @ControllerAdvice(basePackages = "cn.seaboot.admin") public class ControllerExceptionHandler { private Logger logger = LoggerFactory.getLogger(ControllerExceptionHandler.class); /** * Handler ServiceException * * @param request - * @param response - * @param ex ServiceException * @return ModelAndView * @throws IOException If an input or output exception occurs * @see BindException */ @ExceptionHandler public ModelAndView exceptionHandler(HttpServletRequest request, HttpServletResponse response, ServiceException ex) throws IOException { loggerError(request, ex); if (CommonUtils.isAjax(request)) { return new Result(0, ex.getMessage()).toView(); } else { response.sendRedirect(request.getContextPath() + "/error/500.html"); return null; } } }
在一些不成熟的框架中开发,你有可能会遇到这种情况,访问后端的接口后,响应状态为400,然后返回一个错误页面(如下)。
这个问题主要是DefaultHandlerExceptionResolver引起的,在SpringBoot中,HandlerExceptionResolver默认的实现类是DefaultHandlerExceptionResolver,如果我们并未处理代码中的异常,就会默认返回400页面,
对异常的处理,也可以通过改写其中的代码实现。我们不需要完整地实现HandlerExceptionResolver,继承DefaultHandlerExceptionResolver,重写我们需要的代码即可。
import cn.seaboot.admin.others.Jackson.Result; import org.springframework.lang.Nullable; import org.springframework.validation.BindException; import org.springframework.validation.BindingResult; import org.springframework.validation.ObjectError; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; public class ApplicationHandlerExceptionResolver extends DefaultHandlerExceptionResolver { /** * {{@link DefaultHandlerExceptionResolver#handleBindException}} * Override this method, a error json is sent back to the client. * * @param request current HTTP request * @param response current HTTP response * @param handler the executed handler * @return an empty ModelAndView indicating the exception was handled * @throws IOException potentially thrown from {@link HttpServletResponse#sendError} * @author Mr.css */ @Override protected ModelAndView handleBindException(BindException ex, HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException { BindingResult result = ex.getBindingResult(); if (result.hasErrors()) { List<ObjectError> errors = result.getAllErrors(); Map<String, Object> object = new HashMap<>(errors.size()); for (ObjectError error : errors) { object.put(error.getObjectName(), error.getDefaultMessage()); } return new Result(3, object).toView(); } else { return Result.failed("数据验证中发生了未知的异常!").toView(); } } }
在SpringBoot中的注册方式如下
/** * 异常处理机制 * * @param resolvers - */ @Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { if (!resolvers.isEmpty()) { resolvers.removeIf(resolver -> resolver instanceof DefaultHandlerExceptionResolver); } resolvers.add(0, new ApplicationHandlerExceptionResolver()); }