如何使用弹簧404页面制作以.jsp结尾的无效网址?

ooj*_*joe 6 spring jsp spring-mvc

404页面在我的网站上正常运行所有网址,除非它以.jsp结尾.在这种情况下,我得到通用的jboss 404页面而不是我的样式的Spring 404页面.

我的web.xml中有以下内容:

<error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/error/404.jsp</location>
</error-page>
Run Code Online (Sandbox Code Playgroud)

使用完整的web.xml编辑:

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

    <servlet>
        <servlet-name>mainServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mainServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/root-context.xml,
            /WEB-INF/spring-security.xml
        </param-value>
    </context-param>

    <welcome-file-list>
        <welcome-file></welcome-file>
    </welcome-file-list>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>
            org.springframework.web.filter.DelegatingFilterProxy
        </filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <error-page>
        <error-code>400</error-code>
        <location>/WEB-INF/error/400.jsp</location>
    </error-page>

    <error-page>
        <error-code>403</error-code>
        <location>/WEB-INF/error/403.jsp</location>
    </error-page>

    <error-page>
        <error-code>404</error-code>
        <location>/WEB-INF/error/404.jsp</location>
    </error-page>

    <error-page>
        <error-code>405</error-code>
        <location>/WEB-INF/error/405.jsp</location>
    </error-page>

    <error-page>
        <exception-type>java.lang.Exception</exception-type>
        <location>/WEB-INF/error/error.jsp</location>
    </error-page>

    <context-param>
        <param-name>defaultHtmlEscape</param-name>
        <param-value>true</param-value>
    </context-param>
</web-app>
Run Code Online (Sandbox Code Playgroud)

reb*_*ace 3

问题可能是您的 web.xml 直接指向您的 jsp 页面,而不是指向可以指向适当视图的 spring 控制器。

我很想看看您的 rootContext.xml 以了解您如何设置视图解析器。因为也许 spring 变得很困惑......应用程序容器(JBoss)最终只有几种方法来处理错误,那就是请求甚至与 Spring 上下文 servlet 不匹配或者没有错误生成的错误类型的处理程序(是否有可能尝试处理“asdlfasdf.jsp”最终导致另一种类型的异常没有被记录,然后被扔到 JBoss 并作为 404 处理?)。

但是你有一些可以比较的东西 - 这是我的设置方式:

我的视图目录中有一个 error.jsp 页面,并设置类似于以下内容的视图解析器:

<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>
Run Code Online (Sandbox Code Playgroud)

然后,我有一个基本的 PageController 类,我为所有其他“面向用户”的控制器类扩展了该类。该类有一个处理“/error/404”、“/error/403”样式错误页面模式的方法:

@RequestMapping(value = "/error/{code}")
public String errorPage(Principal principal, Model model, @PathVariable("code") int code) {
    model.addAttribute("code", code);
    return "error";
}
Run Code Online (Sandbox Code Playgroud)

然后,我设置与您类似的 web.xml,仅重定向到 spring 控制器端点以及适当的代码:

<error-page>
    <error-code>404</error-code>
    <location>/error/404</location>
</error-page>

<error-page>
    <error-code>403</error-code>
    <location>/error/403</location>
</error-page>
Run Code Online (Sandbox Code Playgroud)

现在,我不知道这是否是最好的方法,但它对我来说非常有效。Web 容器将这些错误类型路由到 /error/code 页面,该页面仅调用控制器方法,然后控制器方法生成 error.jsp 页面(通过返回视图名称“error”)。

由于它将错误代码放入模型中,因此我有一个处理多种错误类型的 jsp,我只是放置了一个根据错误代码呈现不同用户消息的条件。换句话说,“找不到页面:(”与“您无权查看此页面!”

然后我在 spring 安全配置中执行此操作,以确保未经身份验证的用户可以看到错误页面(您可能已经获得了这部分,因为您可以看到 jsp 页面):

<http pattern="/error/**" security="none" />
Run Code Online (Sandbox Code Playgroud)

我将其与注释样式异常处理程序结合起来执行所有服务器异常处理(处理带有 json 错误响应的数据请求和带有 html 错误页面的 html/view 请求),因为您只需注释控制器方法即可处理 Exception 或 RuntimeException。我建议您也检查一下这个方法,因为它非常强大,并且使记录和处理异常变得更加容易:

@ExceptionHandler(Exception.class)
public ModelAndView exceptionHandler(Exception e){
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.getModelMap().addAttribute("code", HttpStatus.INTERNAL_SERVER_ERROR);
    modelAndView.setViewName("error");

    logger.error("Error handling page request.", e);
    return modelAndView;
}
Run Code Online (Sandbox Code Playgroud)

这也是确保您有机会记录通过控制器的异常的好方法,而不必将异常处理放入每个控制器中。

我制作了两个基类...一个用于我的页面控制器,一个用于我的其余数据控制器。基本页面控制器返回 jsp 视图,该视图为用户呈现一个漂亮的错误页面。基本剩余数据控制器返回一条 json 消息,其中包含模型中的错误信息,然后 jsp 将打印完整堆栈或仅打印一般错误,具体取决于服务器是否在开发模式或生产模式下运行。