为了账号安全,请及时绑定邮箱和手机立即绑定

SpringBoot项目实战(7):自定义异常处理界面

标签:
Java

在一般项目中都会有400、500和404这种的异常页面,针对每个异常页面都会设计相应的页面布局和样式,也只有这样的错误页面才会让普通用户看着容易接受,而不是程序出错后将异常代码暴露在页面上,这种的用户体验...额,这种压根就没有用户体验这一说!
比如:图片描述
和:图片描述

相对来说第二种对用户来说就显得没那么"害怕"了。(原谅我用害怕这个词)

其实在Springboot中,SB是默认把异常的处理都集中到了一个ModelAndView中
图片描述

上图是Springboot项目启动时各个路径的映射情况, 可以看到,默认是有两个error映射的,其中一个是针对json一个是针对html页面的。其中这些映射都是在BasicErrorController这个类下,如下图:
图片描述

它是统一跳转到error这个页面了。

再来看下我们本地的controller

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {

    @RequestMapping("/")
    public String home(Model model) {
        return "index";
    }

    @RequestMapping("/error500")
    public void index() {
        int a = 1 / 0;
        System.out.println(a);
    }

    @RequestMapping("/error400/{id}")
    public Object error400(@PathVariable("id") Integer id) {
        System.out.println(id);
        return id;
    }

}

如上图,在访问error500的时候一定会报500,在访问error400/a时一定会报400,
添加error页面(在error页面中已经指定了"这是默认的error页面"),
图片描述

那么在系统异常时就会跳到这个error页面:
图片描述
图片描述
图片描述

那么,应该怎么做才能让具体的异常处理页面分离开呢?

切入正题,SpringBoot中有ConfigurableEmbeddedServletContainer接口(它继承自ErrorPageRegistry),
图片描述
图片描述

ErrorPageRegistry
图片描述
上面两幅图是这个接口下的部分方法,可以看到,通过这个接口可以对SpringBoot程序进行很大程度的自定义控制,比如程序端口、session有效期等等。今天用到的就是上面最后一张图中的addErrorPages方法。

@Component
public class AppErrorPagesConfiguration {

    /**
     * 自定义异常处理路径
     * @return
     */
    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        return new EmbeddedServletContainerCustomizer() {
            @Override
            public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) {
                configurableEmbeddedServletContainer.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"));
                configurableEmbeddedServletContainer.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/error/400"));
                configurableEmbeddedServletContainer.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500"));
                configurableEmbeddedServletContainer.addErrorPages(new ErrorPage(java.lang.Throwable.class, "/error/500"));
            }
        };
    }
}

然后定义一个Controller去重写BasicErrorController的方法

/**
 * 特别注意:这个类中的代码一定不能有问题,否则,你的程序可能会陷入死循环
 */
@Controller
@RequestMapping("/error")
@EnableConfigurationProperties({ServerProperties.class})
public class ErrorPageController implements ErrorController {
    // 这儿只粘贴具体实现代码,关于项目源码会在最后附上git地址,需要的同学自行下载
    /**
     * 定义404的返回页面
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(produces = "text/html", value = "404")
    public ModelAndView errorHtml404(HttpServletRequest request,
                                     HttpServletResponse response) {
        response.setStatus(getStatus(request).value());
        Map<String, Object> model = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.TEXT_HTML));
        return new ModelAndView("error/404", model);
    }

    /**
     * 定义400的返回页面
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(produces = "text/html", value = "400")
    public ModelAndView errorHtml400(HttpServletRequest request,
                                     HttpServletResponse response) {
        response.setStatus(getStatus(request).value());
        Map<String, Object> model = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.TEXT_HTML));
        return new ModelAndView("error/400", model);
    }

    /**
     * 定义500的返回页面
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(produces = "text/html", value = "500")
    public ModelAndView errorHtml500(HttpServletRequest request,
                                     HttpServletResponse response) {
        response.setStatus(getStatus(request).value());
        Map<String, Object> model = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.TEXT_HTML));
        return new ModelAndView("error/500", model);
    }
    // 这儿只粘贴具体实现代码,关于项目源码会在最后附上git地址,需要的同学自行下载
}

然后新建三个页面,同时页面中分别标注一下具体的异常类型,如下图
图片描述
此时看下项目结构
图片描述

OK,测试访问效果
图片描述

这就实现了异常页面的分离,以便于定制各个异常页面信息。

Git源码

我可以对一个人无限的好,前提是值得。 ——慕冬雪

点击查看更多内容
12人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
全栈工程师
手记
粉丝
9132
获赞与收藏
5502

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消