使用springmvc时处理404的方法

如何定义404

404,说白了就是找不到页面,那么如何定义“找不到”呢? 我们可以通过源代码看看Spring MVC如何定义“404”的:

在DispatcherServlet中的doDispatch方法中有

// Determine handler for the current request.
    mappedHandler = getHandler(processedRequest);
    if (mappedHandler == null || mappedHandler.getHandler() == null) {            noHandlerFound(processedRequest, response);
            return;
    }

getHandler是根据请求的url,通过handleMapping来匹配到Controller的过程。 如果匹配不到,那么就执行noHandlerFound方法。这个方法很简单,返回一个404的错误代码。 我们的web容器,比如tomcat,会根据这个错误代码来生成一个错误界面给用户。 那么,我们如何定义这个界面呢?

重写noHandlerFound方法

最先想到的肯定是重写noHandlerFound方法,这个方法是protected,可以重写

那么就自己定义一个MyDispatcherServlet类继承DispatcherServlet并重写noHandlerFound方法

    @Override
    protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.sendRedirect(request.getContextPath() + "/error.jsp");
    }

或者重定向到一个定义好的@Controller上

@Controller
@RequestMapping("/test/")
public class TestController {

    @RequestMapping("get3")
    @ResponseBody
    public String get3(HttpServletRequest request) {
        String contextPath = request.getContextPath();
        return contextPath + "/a/b/c";
    }
}
    @Override
    protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.sendRedirect(request.getContextPath() + "/test/get3");
    }

利用web容器提供的error-page

还记得之前提到的web容器会提供一个404的默认界面吗?
其实我们完全可以替换成我们自己的界面,那么看起来这种方法应该是最简单的了。
只需要在web.xml文件中写上如下代码就可以了

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

注:/error.jsp 这个资源文件一定要以/开头要不然tomcat会报错,并启动不起来

注:这里配置的location其实会被当成一个请求来访问。那么我们的DispatcherServlet会拦截这个请求而造成无法访问,此时的结果是用户界面一片空白。所以这里的404.htm其实是一个静态资源,我们需要访问静态资源的方式去访问。

实际上DispatcherServlet不会拦截,因为当返回404的错误时,实际上是由tomcat在次重定向到配置的<location>...<location>的资源的。

如配置成如下

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

访问一个不存在的资源时得到如下的页面

利用Spring Mvc的最精确匹配

Spring MVC对于url的匹配采用的是一种叫做“最精确匹配的方式”,举个例子

比如我们同时定义了“/test/a”, "/test/*", 那么若请求的url结尾是"/test/a",那么则会匹配精确的那个,也就是"/test/a"

我们是不是可以利用这个特点来找到那此找不到的页面?

  • 首先我们定义一个拦截所有url的规则@RequestMapping("*"),那么实际不存在找不到的页面了,也就是永远不会进入noHandlerFound方法体内
  • 后面的步骤和平时一样,为别的请求配置上@RequestMapping 那么请求过来,要么进入我们精确匹配的method(也就是找到的),要么进入@RequestMapping("*")拦截的方法体内(也就是找不到的)

@Controller
public class ErrorController {

    @RequestMapping("/*")
    @ResponseBody
    public String get2() {
        return "/*";
    }

    @RequestMapping("/**")
    @ResponseBody
    public String get() {
        return "str str";
    }
}

会与下面的配置冲突

<mvc:resources mapping="/resources/**" location="/resources/"/>

在这里我不推荐使用

results matching ""

    No results matching ""