Spring自定义异常

一、404

404错误进不了SpringMVC异常处理(ExceptionHandlerAdvice),会默认进入SpringBoot异常处理:BasicErrorController
1.自写一个ExceptionController类继承BasicErrorController,重写其两个方法
@RequestMapping(produces = "text/html")
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
      //浏览器直接输入url访问,会进入这里;这里可以返回json数据,也可以跳转到404.html、500.html
}

@RequestMapping
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
     //前端触发访问后端接口,会进入这里,直接返回json数据(code和messageText)
}

public class ExceptionController extends BasicErrorController{
    private static final Logger log = LoggerFactory.getLogger("ExceptionController");

    @Autowired
    private ApplicationContext applicationContext;
    private static class HtmlResourceView implements View {

        private Resource resource;

        HtmlResourceView(Resource resource) {
            this.resource = resource;
        }

        @Override
        public String getContentType() {
            return MediaType.TEXT_HTML_VALUE;
        }

        @Override
        public void render(Map<String, ?> model, HttpServletRequest request,
                           HttpServletResponse response) throws Exception {
            response.setContentType(getContentType());
            FileCopyUtils.copy(this.resource.getInputStream(),
                    response.getOutputStream());
        }

    }

    public ExceptionController(ErrorAttributes errorAttributes, ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) {
        super(errorAttributes, errorProperties, errorViewResolvers);
    }

    @Override
    @RequestMapping(produces = "text/html")
    public ModelAndView errorHtml(HttpServletRequest request,
                                  HttpServletResponse response) {
        //浏览器直接输入url访问,会进入这里;这里可以返回json数据,也可以跳转到404.html、500.html
        HttpStatus status = getStatus(request);
        Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
                request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());

        ModelAndView modelAndView = resolveErrorView(request, response, status, model);   //这里会去调用AbstractErrorController的方法
        //ModelAndView view = new ModelAndView("error", model);  //这里默认的页面必须写error
        //1.先去(前缀/resources):/META-INF/resources/error/、/resources/error/、/static/error/、/public/error/,按照顺序找404.html
        //2.如果没有则modelAndView = null,就会去找默认的页面:ErrorMvcAutoConfiguration的WhitelabelErrorViewConfiguration()

        ModelAndView defView = new ModelAndView();  //自定义跳转到哪里的页面
        String location = "classpath:/public/";
        String viewName = "static/";
        try {
            Resource resource = this.applicationContext.getResource(location);
            resource = resource.createRelative(viewName + status +".html");
            if (resource.exists()) {
                defView = new ModelAndView(new HtmlResourceView(resource), model);
            }
        } catch (Exception ex) {

        }

        return (modelAndView != null ? modelAndView : defView);
    }

    @Override
    @RequestMapping
    @ResponseBody
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        //前端触发访问后端接口,会进入这里,直接返回json数据(code和messageText)
        Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = getStatus(request);
        String message = body.get("message").toString();

        Map<String, Object> map = new HashMap<>();
        map.put("messageText", message);
        map.put("code", status.value() + "");

        return new ResponseEntity<>(map, status);
    }

}

2.定义完自己的ExceptionController之后,还需要一个配置类:
需定义一个自己的错误控制器:ExceptionControllerConfig,让其先进入自定义异常处理类

@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({Servlet.class, DispatcherServlet.class})
@AutoConfigureBefore(WebMvcAutoConfiguration.class)
@EnableConfigurationProperties(ResourceProperties.class)
public class ExceptionControllerConfig {

    private final ServerProperties serverProperties;
    private final List<ErrorViewResolver> errorViewResolvers;


    public ExceptionControllerConfig(ServerProperties serverProperties, ObjectProvider<List<ErrorViewResolver>> errorViewResolversProvider) {
        this.serverProperties = serverProperties;
        this.errorViewResolvers = errorViewResolversProvider.getIfAvailable();
    }

    @Bean
    public ExceptionController exceptionController(ErrorAttributes errorAttributes) {

        return new ExceptionController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers);
    }
}

二、500

1.会先进入ExceptionHandlerAdvice中,把捕获500的方法去掉,
就会进入BasicErrorController中,和404一样

三、我们可以自定义跳转到哪个文件夹,甚至哪个文件名

errorHtml方法中,跳转到404或500页面
具体跳转到哪个文件夹下:
分析源码所得:
1.先去(前缀/resources):/META-INF/resources/error/、/resources/error/、/static/error/、/public/error/,按照顺序找404.html
2.如果没有则modelAndView = null,就会去找默认的页面:ErrorMvcAutoConfiguration的WhitelabelErrorViewConfiguration()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值