gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 09:49:02 24 4
gpt4 key购买 nike

尝试在 Web 应用程序中提供自定义 404 错误页面,据我所知,该应用程序使用 Java Config(因此没有 web.xml)。

我们有以下版本的相关库:spring(“5.1.2.RELEASE”)、spring-security(“5.1.1.RELEASE”)。

免责声明

I have checked different approaches here in StackOverflow. Please don't suggest results for web.xml, Thymeleaf or Spring Boot. This is not applicable.

其中;我尝试了以下方法:

  • @Controller 注解( herehere )
  • 添加 web.xml

没有一个产生预期的结果(即仍然获得默认的网络服务器布局和错误)。

Controller 注解方式

  • 异常包

    package ...;

    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.servlet.NoHandlerFoundException;

    @ControllerAdvice
    public class GlobalExceptionHandler {

    // Option A (used as an alternative to option B)
    //@ExceptionHandler(Exception.class)
    //public String handle(Exception ex) {
    // return "redirect:/404";
    //}

    @RequestMapping(value = {"/404"}, method = RequestMethod.GET)
    public String NotFoundPage() {
    return "404";
    }

    // Option B (used as an alternative to option A)
    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleNoHandlerFoundException(GlobalExceptionHandler ex) {
    ResponseEntity responseEntity = new ResponseEntity<>(new RestClientException("Testing exception"),
    HttpStatus.NOT_FOUND);
    return responseEntity;
    }
    }
  • 初始化类

    package ...;

    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    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.bind.annotation.ExceptionHandler;
    import org.springframework.http.ResponseEntity;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.servlet.NoHandlerFoundException;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;

    @Configuration
    @ComponentScan("...")
    @EnableWebMvc
    @EnableTransactionManagement
    @PropertySource("classpath:application.properties")
    public class WebAppConfig extends WebMvcConfigurerAdapter {

    @ExceptionHandler({ Exception.class })
    public ResponseEntity<RestClientException> handle(NoHandlerFoundException e) {
    return new ResponseEntity<>(new RestClientException("Testing exception"), HttpStatus.NOT_FOUND);
    }

    ...

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    super.addViewControllers(registry);
    registry.addViewController("/404.jsp").setViewName("404");
    }
    }

还有一个 Initializer 类(public class Initializer Implements WebApplicationInitializer),它似乎与一些建议选项(已定义 herehere )冲突;所以 webapp-init 类没有被修改。

web.xml 方法

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="ROOT" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">

<error-page>
<error-code>404</error-code>
<location>/error</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/error</location>
</error-page>

</web-app>

放置 404.jsp404.html 文件(当前在以下所有位置用于测试目的):

    src/main/resources
├── ...
├── error
│   └── 404.html
├── public
│   ├── 404.html
│   └── error
│   └── 404.html
├── templates
│   └── 404.html
└── ...

src/main/webapp/WEB-INF/
├── error.jsp
├── tags
│   └── ...
└── views
├── 404.html
├── 404.jsp
├── error.jsp
└── ...

知道缺少或错误的内容吗?

最佳答案

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

已处理异常的列表并不广泛,但主要解决 404 错误 (NoHandlerFoundException) 和其他典型错误,例如 InternalServerErrorExceptionNullPointerException,尝试最终捕获所有错误,并为其他所有 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);

// ...

}
}

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

    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 />

关于java - Spring 中的 404 错误(java config/no web.xml),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55028538/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com