Spring Boot学习(一) 配置自定义错误页面的几种方式

第一种 实现ErrorPageRegistrar

创建配置类 ,注册错误页面

@Configuration
public class ErrorCodePageHandler implements ErrorPageRegistrar {
    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        ErrorPage[] errorPages = new ErrorPage[2];
        // 添加错误页面进行映射 当404时会跳转到/error/404的请求
        errorPages[0] = new ErrorPage(HttpStatus.NOT_FOUND,"/error/404");
        errorPages[1] = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");
        registry.addErrorPages(errorPages);
    }
}

在控制器中添加处理

package com.learn.security.func.app.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@Slf4j
@Controller
@EnableConfigurationProperties({ServerProperties.class})
public class ErrorPagesController implements ErrorController{

    private final ErrorAttributes errorAttributes;

    private final ServerProperties serverProperties;

    public ErrorPagesController(ErrorAttributes errorAttributes, ServerProperties serverProperties) {
        this.errorAttributes=errorAttributes;
        this.serverProperties=serverProperties;
    }

    @RequestMapping("/404")
    public ModelAndView errorHtml404(HttpServletRequest request, HttpServletResponse response, WebRequest webRequest) {
        response.setStatus(HttpStatus.NOT_FOUND.value());
        Map<String, Object> model = getErrorAttributes(webRequest, getErrorAttributeOptions());
        model.put("queryString", request.getQueryString());
        return new ModelAndView("error/404", model);
    }

    @RequestMapping("/403")
    public ModelAndView errorHtml403(HttpServletRequest request, HttpServletResponse response, WebRequest webRequest) {
        response.setStatus(HttpStatus.FORBIDDEN.value());
        Map<String, Object> model = getErrorAttributes(webRequest, getErrorAttributeOptions());
        model.put("queryString", request.getQueryString());
        if (!String.valueOf(model.get("path")).contains(".")) {
            model.put("status", HttpStatus.FORBIDDEN.value());
        }
        return new ModelAndView("error/403", model);
    }

    @RequestMapping("/400")
    public ModelAndView errorHtml400(HttpServletRequest request, HttpServletResponse response, WebRequest webRequest) {
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        Map<String, Object> model = getErrorAttributes(webRequest, getErrorAttributeOptions());
        model.put("queryString", request.getQueryString());
        return new ModelAndView("error/400", model);
    }

    @RequestMapping("/401")
    public ModelAndView errorHtml401(HttpServletRequest request, HttpServletResponse response, WebRequest webRequest) {
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        Map<String, Object> model = getErrorAttributes(webRequest, getErrorAttributeOptions());
        model.put("queryString", request.getQueryString());
        return new ModelAndView("error/401", model);
    }

    @RequestMapping("/500")
    public ModelAndView errorHtml500(HttpServletRequest request, HttpServletResponse response, WebRequest webRequest) {
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        Map<String, Object> model = getErrorAttributes(webRequest, getErrorAttributeOptions());
        model.put("queryString", request.getQueryString());
        return new ModelAndView("error/500", model);
    }

    /**
     *
     * @return ErrorAttributeOptions
     */
    protected ErrorAttributeOptions getErrorAttributeOptions() {
        Set<ErrorAttributeOptions.Include> includes = new HashSet<>();
        ErrorProperties error = this.serverProperties.getError();
        if (error.getIncludeStacktrace() == ErrorProperties.IncludeAttribute.ALWAYS) {
            includes.add(ErrorAttributeOptions.Include.STACK_TRACE);
        }
        if(error.getIncludeMessage() == ErrorProperties.IncludeAttribute.ALWAYS){
            includes.add(ErrorAttributeOptions.Include.MESSAGE);
        }
        if(error.isIncludeException()){
            includes.add(ErrorAttributeOptions.Include.EXCEPTION);
        }
        if(error.getIncludeBindingErrors() == ErrorProperties.IncludeAttribute.ALWAYS){
            includes.add(ErrorAttributeOptions.Include.BINDING_ERRORS);
        }
        return ErrorAttributeOptions.of(includes);
    }

    /**
     * 获取错误的信息
     *
     * @param webRequest
     *      web请求
     * @param options
     *      错误参数选项
     * @return  Map 错误参数
     */
    private Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
        return this.errorAttributes.getErrorAttributes(webRequest, options);
    }
}

第二种 使用BasicErrorController

方式一,使用默认的路径
在templates下创建error.html界面即可
方式二,使用自定义路径,继承BasicErrorController重写errorHtml方法使其映射到自己定义的视图

mport lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.Map;

@Slf4j
@Controller
@EnableConfigurationProperties({ServerProperties.class})
public class ErrorPagesController extends BasicErrorController{

    @Autowired
    public ErrorPagesController(ErrorAttributes errorAttributes, ServerProperties serverProperties) {
        super(errorAttributes, serverProperties.getError());
    }

    @Override
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = this.getStatus(request);
        // 获取内置信息,包含timestamp,status,message,exception,trace,errors
        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.getErrorAttributeOptions(request, MediaType.TEXT_HTML)));
        int code = status.value();
        response.setStatus(code);
        ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
        // 使用模版引擎,根据错误代码映射错误页面。如 404 会跳转到/error/404.html页面500会跳到/error/500.html页面
        return modelAndView != null ? modelAndView : new ModelAndView("error/"+code, model);
    }


}


第三种 继承HandlerInterceptorAdapter

/**
 * @author hgs
 * @version ErrorPageInterceptor.java, v 0.1 2018/03/04 20:52 hgs Exp $
 * <p>
 * 错误页面拦截器
 * 替代EmbeddedServletContainerCustomizer在war中不起作用的方法
 */
@Component
public class ErrorPageInterceptor extends HandlerInterceptorAdapter {
    private List<Integer> errorCodeList = Arrays.asList(404, 403, 500, 501);
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws
        Exception {
       if (errorCodeList.contains(response.getStatus())) {
            response.sendRedirect("/error/" + response.getStatus());
            return false;
        }
        return super.preHandle(request, response, handler);
    }
}
// 原文: https://blog.csdn.net/lh87270202/article/details/79925951

在配置类中添加拦截

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(errorPageInterceptor);//.addPathPatterns("/action/**", "/mine/**");默认所有
    super.addInterceptors(registry);
  }
}

第四种 配置EmbeddedServletContainerCustomizer

注册错误页面

/**
 * 配置默认错误页面(仅用于内嵌tomcat启动时)
 * 使用这种方式,在打包为war后不起作用 
 * @return
 */  
@Bean
public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer () {
  return container -> {
      ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");
      ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");
      container.addErrorPages(error404Page, error500Page);
};
// 原文: https://blog.csdn.net/lh87270202/article/details/79925951

在控制器中添加处理, 可以参考第一种

参考:
https://blog.csdn.net/TreeShu321/article/details/117391210
https://blog.csdn.net/lh87270202/article/details/79925951

posted @ 2021-06-17 17:25  青青一笑很倾城  阅读(1728)  评论(0)    收藏  举报