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

Spring 中的 404 错误(java config / no web.xml)

Spring 中的 404 错误(java config / no web.xml)

红颜莎娜 2022-07-20 20:20:52
尝试在 Web 应用程序中提供自定义 404 错误页面,据我所知,该页面使用 Java Config(因此没有 web.xml)。我们有以下版本的相关库:spring ("5.1.2.RELEASE")、spring-security ("5.1.1.RELEASE")。免责声明我在 StackOverflow 中检查了不同的方法。请不要为 web.xml、Thymeleaf 或 Spring Boot 推荐结果。这不适用。其中; 我尝试了以下方法:@Controller注释(这里和这里)添加 web.xml没有产生预期的结果(即,仍然得到默认的网络服务器布局和错误)。
查看完整描述

3 回答

?
德玛西亚99

TA贡献1770条经验 获得超3个赞

虽然没有我想的那么清楚,但这是一种工作版本,至少可以为错误页面提供一些自定义。这是第一种方法,但希望可以帮助其他人。


处理的异常列表并不广泛,但主要解决 404 错误 ( NoHandlerFoundException) 和其他典型错误,例如InternalServerErrorExceptionand NullPointerException,尝试在最后捕获所有异常,并为所有其他是 a 的错误提供通用错误Exception)。


请注意,这不包括与例如 JSTL 模板中的错误语法相关的其他异常(org.apache.jasper.*; 显然无法在此处捕获的异常)。


这些是源库的相关更改和添加:


CustomSimpleMappingExceptionResolver.java(提供通用异常,但记录详细信息)


package ...;


import java.util.ArrayList;

import java.util.Arrays;

import java.util.Date;

import javax.ws.rs.InternalServerErrorException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import org.springframework.http.HttpStatus;

import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import org.springframework.web.servlet.ModelAndView;

import org.springframework.web.servlet.NoHandlerFoundException;


public class CustomSimpleMappingExceptionResolver extends SimpleMappingExceptionResolver {


    public CustomSimpleMappingExceptionResolver() {

        // Turn logging on by default

        setWarnLogCategory(getClass().getName());

    }


    @Override

    public String buildLogMessage(Exception e, HttpServletRequest req) {

        return "MVC exception: " + e.getLocalizedMessage();

    }


    @Override

    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response,

                                              Object handler, Exception ex) {


        // Log exception

        ex.printStackTrace();

        String exceptionCause = ex.toString();

        String exceptionType = ex.getClass().getCanonicalName();


        // Get the ModelAndView to use

        ModelAndView mav = super.doResolveException(request, response, handler, ex);


        // Make more information available to the view - note that SimpleMappingExceptionResolver adds the exception already

        mav.addObject("url", request.getRequestURL());

        mav.addObject("timestamp", new Date());


        ArrayList<String> exceptions404 = new ArrayList<String>(

                Arrays.asList(

                        NoHandlerFoundException.class.getName()

                        )

        );

        ArrayList<String> exceptions500 = new ArrayList<String>(

                Arrays.asList(

                        InternalServerErrorException.class.getName(),

                        NullPointerException.class.getName()

                        )

        );


        String userExceptionDetail = ex.toString();

        String errorHuman = "";

        String errorTech = "";


        if (exceptions404.contains(exceptionType)) {

            errorHuman = "We cannot find the page you are looking for";

            errorTech = "Page not found";

            userExceptionDetail = String.format("The page %s cannot be found", request.getRequestURL());

            mav.setViewName("/error/404");

            mav.addObject("status", HttpStatus.NOT_FOUND.value());

        } else if (exceptions500.contains(exceptionType)) {

            errorHuman = "We cannot currently serve the page you request";

            errorTech = "Internal error";

            userExceptionDetail = "The current page refuses to load due to an internal error";

            mav.setViewName("/error/500");

            mav.addObject("status", HttpStatus.INTERNAL_SERVER_ERROR.value());

        } else {

            errorHuman = "We cannot serve the current page";

            errorTech = "General error";

            userExceptionDetail = "A generic error prevents from serving the page";

            mav.setViewName("/error/generic");

            mav.addObject("status", response.getStatus());

        }


        Exception userException = new Exception(userExceptionDetail);

        mav.addObject("error_human", errorHuman);

        mav.addObject("error_tech", errorTech);

        mav.addObject("exception", userException);

        return mav;

    }

}

WebAppConfig.java(将自定义异常解析器注册为异常处理程序)


package ...;


import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.PropertySource;

import org.springframework.context.annotation.Scope;

import org.springframework.context.annotation.ScopedProxyMode;

import org.springframework.core.env.Environment;

import org.springframework.core.Ordered;

import org.springframework.http.HttpStatus;

import org.springframework.transaction.annotation.EnableTransactionManagement;

import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import org.springframework.web.servlet.HandlerExceptionResolver;

import org.springframework.web.servlet.NoHandlerFoundException;

import org.springframework.web.servlet.view.InternalResourceViewResolver;


import java.lang.ClassNotFoundException;

import java.lang.NullPointerException;

import javax.annotation.Resource;

import javax.ws.rs.InternalServerErrorException;

import java.util.Properties;


@Configuration

@ComponentScan("...")

@EnableWebMvc

@EnableTransactionManagement

@PropertySource("classpath:application.properties")

public class WebAppConfig extends WebMvcConfigurerAdapter {


    @Resource

    private Environment env;


    // ...


    @Bean

    HandlerExceptionResolver customExceptionResolver () {

        CustomSimpleMappingExceptionResolver resolver = new CustomSimpleMappingExceptionResolver();

        Properties mappings = new Properties();

        // Mapping Spring internal error NoHandlerFoundException to a view name

        mappings.setProperty(NoHandlerFoundException.class.getName(), "/error/404");

        mappings.setProperty(InternalServerErrorException.class.getName(), "/error/500");

        mappings.setProperty(NullPointerException.class.getName(), "/error/500");

        mappings.setProperty(ClassNotFoundException.class.getName(), "/error/500");

        mappings.setProperty(Exception.class.getName(), "/error/generic");

        resolver.setExceptionMappings(mappings);

        // Set specific HTTP codes

        resolver.addStatusCode("404", HttpStatus.NOT_FOUND.value());

        resolver.addStatusCode("500", HttpStatus.INTERNAL_SERVER_ERROR.value());

        resolver.setDefaultErrorView("/error/generic");

        resolver.setDefaultStatusCode(200);

        // This resolver will be processed before the default ones

        resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);

        resolver.setExceptionAttribute("exception");

        return resolver;

    }


    // ...


    @Bean

    public InternalResourceViewResolver setupViewResolver() {

        InternalResourceViewResolver resolver = new InternalResourceViewResolver();

        resolver.setPrefix("/WEB-INF/views");

        resolver.setSuffix(".jsp");

        resolver.setExposeContextBeansAsAttributes(true);

        return resolver;

    }


    @Override

    public void addViewControllers(ViewControllerRegistry registry) {

        super.addViewControllers(registry);

    }

}

Initializer.java(添加dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);;可能不需要)


package ...;


import org.springframework.web.WebApplicationInitializer;

import org.springframework.web.context.ContextLoaderListener;

import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

import org.springframework.web.servlet.DispatcherServlet;


import javax.servlet.ServletContext;

import javax.servlet.ServletException;

import javax.servlet.ServletRegistration;


public class Initializer implements WebApplicationInitializer {


    public void onStartup(ServletContext servletContext) throws ServletException {

        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();

        ctx.register(WebAppConfig.class);

        servletContext.addListener(new ContextLoaderListener(ctx));

        ctx.setServletContext(servletContext);

        DispatcherServlet dispatcherServlet = new DispatcherServlet(ctx);

        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);


        // Add the dispatcher servlet mapping manually and make it initialize automatically

        ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", dispatcherServlet);

        servlet.addMapping("/");

        servlet.addMapping("*.png");

        servlet.addMapping("*.jpg");

        servlet.addMapping("*.css");

        servlet.addMapping("*.js");

        servlet.addMapping("*.txt");

        servlet.setLoadOnStartup(1);


        // ...


    }

}

与错误类相关的视图和标签的结构:


    src/main/webapp/WEB-INF/

    ├── tags

    │   └── error.tag

    └── views

        ├── error

        │   ├── 404.jsp

        │   ├── 500.jsp

        └────── generic.jsp

src/main/webapp/WEB-INF/tags/error.tag


<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>


<!DOCTYPE html>

<head>

    <title>Error page</title>

</head>

<body>

<div class="container">

    <h3><c:out value="${error_human}" /></h3>


    <p><br/><br/></p>


    <div class="panel panel-primary">

        <div class="panel-heading">

            <c:out value="${error_tech}" />

        </div>

        <div class="panel-body">

            <p><c:out value="${exception_message}" /></p>

        </div>

    </div>

</div>

</body>

</html>

src/main/webapp/WEB-INF/views/error/404.jsp


<%@ page language="java" contentType="text/html; charset=utf-8"

         pageEncoding="utf-8" isErrorPage="true" %>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%@ taglib tagdir="/WEB-INF/tags/" prefix="g" %>


<c:set var = "error_human" scope = "session" value = "We cannot find the page you are looking for"/>

<c:set var = "error_tech" scope = "session" value = "Page not found"/>

<c:set var = "exception_message" scope = "session" value = "The current page cannot be found"/>

<g:error />

src/main/webapp/WEB-INF/views/error/500.jsp


<%@ page language="java" contentType="text/html; charset=utf-8"

         pageEncoding="utf-8" isErrorPage="true" %>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%@ taglib tagdir="/WEB-INF/tags/" prefix="g" %>


<c:set var = "error_human" scope = "session" value = "We cannot currently serve the page you request"/>

<c:set var = "error_tech" scope = "session" value = "Internal error"/>

<c:set var = "exception_message" scope = "session" value = "The current page refuses to load due to an internal error"/>

<g:error />

src/main/webapp/WEB-INF/views/error/generic.jsp


<%@ page language="java" contentType="text/html; charset=utf-8"

         pageEncoding="utf-8" isErrorPage="true" %>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%@ taglib tagdir="/WEB-INF/tags/" prefix="g" %>


<c:set var = "error_human" scope = "session" value = "We cannot serve the current page"/>

<c:set var = "error_tech" scope = "session" value = "General error"/>

<c:set var = "exception_message" scope = "session" value = "A generic error prevents from serving the page"/>

<g:error />


查看完整回答
反对 回复 2022-07-20
?
斯蒂芬大帝

TA贡献1827条经验 获得超8个赞

阅读 Spring Boot 文档,这对我有用:


  @Bean

   public ErrorPageRegistrar errorPageRegistrar() {

     return registry -> registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/index.html"));  }

这相当于 web.xml。


查看完整回答
反对 回复 2022-07-20
?
慕桂英546537

TA贡献1848条经验 获得超10个赞

确保您可以访问 404 页面,然后添加这些代码。


@ControllerAdvice

public class GlobalExceptionHandler {


    @ResponseStatus(HttpStatus.NOT_FOUND)

    @ExceptionHandler(NoHandlerFoundException.class)

    public String handle404(Model model, HttpServletRequest req, Exception ex) {

        return "/404";

    }

}

应用程序.yaml


spring:

  mvc:

    throwExceptionIfNoHandlerFound: true # if page not found, it will throw error, and then ControllerAdvice will catch the error.

PS:springBoot版本=2.4.2;爪哇=15


查看完整回答
反对 回复 2022-07-20
  • 3 回答
  • 0 关注
  • 163 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号