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

时间:2013-11-22 22:03:59

标签: 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>

使用完整的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>

1 个答案:

答案 0 :(得分:3)

问题可能是你的web.xml直接指向你的jsp页面,而不是指向一个弹簧控制器,然后可以指向适当的视图。

我很想知道你的rootContext.xml是如何设置你的视图解析器的。原因可能是春天变得混乱...... App Container(JBoss)最终只会处理错误的几种方式,即如果请求甚至不匹配Spring上下文servlet或者没有错误生成错误类型的处理程序(是否有可能处理“asdlfasdf.jsp”的尝试最终导致另一种类型的异常未被记录,然后被抛到JBoss并作为404处理?)。

但是你要有比较的东西 - 这就是我设置的方式:

我在views目录中有一个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>

然后,我有一个基本的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";
}

然后,我设置类似于你的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>

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

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

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

<http pattern="/error/**" security="none" />

我将它与注释样式异常处理程序结合起来进行所有服务器异常处理(使用json错误响应处理数据请求和使用html错误页面处理html / view请求),因为您只需注释控制器方法来处理异常或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;
}

这也是一种很好的方法,可以确保您有机会记录通过控制器的异常,而无需将异常处理放入每个控制器中。

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