使用java配置在Spring中进行404错误重定向

时间:2022-11-29 13:53:33

As you know, in XML, the way to configure this is:

如您所知,在XML中,配置它的方法是:

<error-page>
    <error-code>404</error-code>
    <location>/my-custom-page-not-found.html</location>
</error-page>

But I haven't found a way to do it in Java config. The first way I tried was:

但我还没有找到一种方法在Java配置中执行此操作。我尝试的第一种方式是:

@RequestMapping(value = "/**")
public String Error(){
    return "error";
}

And it appeared to work, but it has conflicts retrieving the resources.

它似乎工作,但它检索资源有冲突。

Is there a way to do it?

有办法吗?

7 个解决方案

#1


18  

In Spring Framework, there are number of ways of handing exceptions (and particularly 404 error). Here is a documentation link.

在Spring Framework中,有许多处理异常的方法(尤其是404错误)。这是一个文档链接。

  • First, you can still use error-page tag in web.xml, and customize error page. Here is an example.
  • 首先,您仍然可以在web.xml中使用error-page标记,并自定义错误页面。这是一个例子。
  • Second, you can use one @ExceptionHandler for all controllers, like this:

    其次,您可以为所有控制器使用一个@ExceptionHandler,如下所示:

    @ControllerAdvice
    public class ControllerAdvisor {
    
         @ExceptionHandler(NoHandlerFoundException.class)
         public String handle(Exception ex) {
    
            return "404";//this is view name
        }
    }
    

    For this to work, set throwExceptionIfNoHandlerFound property to true for DispatcherServlet in web.xml:

    为此,请将webEx中的DispatcherServlet的throwExceptionIfNoHandlerFound属性设置为true:

    <init-param>
        <param-name>throwExceptionIfNoHandlerFound</param-name>
        <param-value>true</param-value>
    </init-param>
    

    You can also pass some objects to error view, see javadoc for this.

    您也可以将一些对象传递给错误视图,请参阅javadoc。

#2


10  

The most clean solution since spring 4.2 RC3 is using the new createDispatcherServlet hook within the class extending AbstractDispatcherServletInitializer (or indirectly through extending AbstractAnnotationConfigDispatcherServletInitializer) like this:

自Spring 4.2 RC3以来最干净的解决方案是在扩展AbstractDispatcherServletInitializer(或间接通过扩展AbstractAnnotationConfigDispatcherServletInitializer)的类中使用新的createDispatcherServlet钩子,如下所示:

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    /* ... */

    @Override
    protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
        final DispatcherServlet dispatcherServlet = super.createDispatcherServlet(servletAppContext);
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
        return dispatcherServlet;
    }
}

Then you can use a global @ControllerAdvice (a class that is annotated with @ControllerAdvice) as described in the reference docs. Within the advice you can handle the NoHandlerFoundException with an @ExceptionHandler as described here.

然后,您可以使用全局@ControllerAdvice(使用@ControllerAdvice注释的类),如参考文档中所述。在建议中,您可以使用@ExceptionHandler处理NoHandlerFoundException,如此处所述。

This could look something like this:

这看起来像这样:

@ControllerAdvice
public class NoHandlerFoundControllerAdvice {

    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<String> handleNoHandlerFoundException(NoHandlerFoundException ex) {
        // prepare responseEntity
        return responseEntity;
    }

}

#3


4  

Use code-based Servlet container initialization as described in the doc and override registerDispatcherServlet method to set throwExceptionIfNoHandlerFound property to true:

使用doc和覆盖registerDispatcherServlet方法中描述的基于代码的Servlet容器初始化将throwExceptionIfNoHandlerFound属性设置为true:

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

    @Override
    protected void registerDispatcherServlet(ServletContext servletContext) {
        String servletName = getServletName();
        Assert.hasLength(servletName, "getServletName() may not return empty or null");

        WebApplicationContext servletAppContext = createServletApplicationContext();
        Assert.notNull(servletAppContext,
            "createServletApplicationContext() did not return an application " +
                    "context for servlet [" + servletName + "]");

        DispatcherServlet dispatcherServlet = new DispatcherServlet(servletAppContext);

        // throw NoHandlerFoundException to Controller
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);

        ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
        Assert.notNull(registration,
            "Failed to register servlet with name '" + servletName + "'." +
                    "Check if there is another servlet registered under the same name.");

        registration.setLoadOnStartup(1);
        registration.addMapping(getServletMappings());
        registration.setAsyncSupported(isAsyncSupported());

        Filter[] filters = getServletFilters();
        if (!ObjectUtils.isEmpty(filters)) {
            for (Filter filter : filters) {
                registerServletFilter(servletContext, filter);
            }
        }

        customizeRegistration(registration);
    }
}    

Then create an exception handler:

然后创建一个异常处理程序

@ControllerAdvice
public class ExceptionHandlerController {
    @ExceptionHandler(Exception.class)
    public String handleException(Exception e) {
        return "404";// view name for 404 error
    }   
}

Don't forget about using @EnableWebMvc annotation on your Spring configuration file:

不要忘记在Spring配置文件中使用@EnableWebMvc注释:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages= {"org.project.etc"})
public class WebConfig extends WebMvcConfigurerAdapter {
    ...
}

#4


3  

Simple answer for 100% free xml:

100%免费xml的简单答案:

  1. Set properties for DispatcherServlet

    设置DispatcherServlet的属性

    public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[] { RootConfig.class  };
        }
    
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class[] {AppConfig.class  };
        }
    
        @Override
        protected String[] getServletMappings() {
            return new String[] { "/" };
        }
    
        @Override
        protected void customizeRegistration(ServletRegistration.Dynamic registration) {
            boolean done = registration.setInitParameter("throwExceptionIfNoHandlerFound", "true"); // -> true
            if(!done) throw new RuntimeException();
        }
    
    }
    
  2. Create @ControllerAdvice:

    创建@ControllerAdvice:

    @ControllerAdvice
    public class AdviceController {
    
        @ExceptionHandler(NoHandlerFoundException.class)
        public String handle(Exception ex) {
            return "redirect:/404";
        }
    
        @RequestMapping(value = {"/404"}, method = RequestMethod.GET)
        public String NotFoudPage() {
            return "404";
    
        }
    }
    

#5


3  

In your web configuration class,

在您的Web配置类中,

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter 

Declare a bean as follows,

声明一个bean如下,

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {

  return new EmbeddedServletContainerCustomizer() {
    @Override
    public void customize(ConfigurableEmbeddedServletContainer container)       
    {
      ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/401.html");
      ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
      ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html");

      container.addErrorPages(error401Page,error404Page,error500Page);
    }
  };
}

Add the mentioned html files(401.html .etc) to /src/main/resources/static/ folder.

将提到的html文件(401.html .etc)添加到/ src / main / resources / static /文件夹。

Hope this helps

希望这可以帮助

#6


3  

For Java config there is a method setThrowExceptionIfNoHandlerFound(boolean throwExceptionIfNoHandlerFound) in DispatcherServlet. By settting it to true I guess you are doing same thing

对于Java配置,DispatcherServlet中有一个方法setThrowExceptionIfNoHandlerFound(boolean throwExceptionIfNoHandlerFound)。通过将其设置为真,我猜你做的是同样的事情

<init-param>
    <param-name>throwExceptionIfNoHandlerFound</param-name>
    <param-value>true</param-value>
</init-param>

then you can can this NoHandlerFoundException.class in controller advice as stated in above answer

那么你可以在控制器建议中使用这个NoHandlerFoundException.class,如上面的答案中所述

it will be like something

它会像某样东西

public class WebXml implements WebApplicationInitializer{

    public void onStartup(ServletContext servletContext) throws ServletException {
        WebApplicationContext context = getContext();
        servletContext.addListener(new ContextLoaderListener(context));


        DispatcherServlet dp =  new DispatcherServlet(context);
        dp.setThrowExceptionIfNoHandlerFound(true);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", dp);
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping(MAPPING_URL);
    }
}

#7


1  

The solution proposed in comments above really works:

上面评论中提出的解决方案确实有效:

@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration)
{
  registration.setInitParameter("throwExceptionIfNoHandlerFound", "true");
}

#1


18  

In Spring Framework, there are number of ways of handing exceptions (and particularly 404 error). Here is a documentation link.

在Spring Framework中,有许多处理异常的方法(尤其是404错误)。这是一个文档链接。

  • First, you can still use error-page tag in web.xml, and customize error page. Here is an example.
  • 首先,您仍然可以在web.xml中使用error-page标记,并自定义错误页面。这是一个例子。
  • Second, you can use one @ExceptionHandler for all controllers, like this:

    其次,您可以为所有控制器使用一个@ExceptionHandler,如下所示:

    @ControllerAdvice
    public class ControllerAdvisor {
    
         @ExceptionHandler(NoHandlerFoundException.class)
         public String handle(Exception ex) {
    
            return "404";//this is view name
        }
    }
    

    For this to work, set throwExceptionIfNoHandlerFound property to true for DispatcherServlet in web.xml:

    为此,请将webEx中的DispatcherServlet的throwExceptionIfNoHandlerFound属性设置为true:

    <init-param>
        <param-name>throwExceptionIfNoHandlerFound</param-name>
        <param-value>true</param-value>
    </init-param>
    

    You can also pass some objects to error view, see javadoc for this.

    您也可以将一些对象传递给错误视图,请参阅javadoc。

#2


10  

The most clean solution since spring 4.2 RC3 is using the new createDispatcherServlet hook within the class extending AbstractDispatcherServletInitializer (or indirectly through extending AbstractAnnotationConfigDispatcherServletInitializer) like this:

自Spring 4.2 RC3以来最干净的解决方案是在扩展AbstractDispatcherServletInitializer(或间接通过扩展AbstractAnnotationConfigDispatcherServletInitializer)的类中使用新的createDispatcherServlet钩子,如下所示:

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    /* ... */

    @Override
    protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
        final DispatcherServlet dispatcherServlet = super.createDispatcherServlet(servletAppContext);
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
        return dispatcherServlet;
    }
}

Then you can use a global @ControllerAdvice (a class that is annotated with @ControllerAdvice) as described in the reference docs. Within the advice you can handle the NoHandlerFoundException with an @ExceptionHandler as described here.

然后,您可以使用全局@ControllerAdvice(使用@ControllerAdvice注释的类),如参考文档中所述。在建议中,您可以使用@ExceptionHandler处理NoHandlerFoundException,如此处所述。

This could look something like this:

这看起来像这样:

@ControllerAdvice
public class NoHandlerFoundControllerAdvice {

    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<String> handleNoHandlerFoundException(NoHandlerFoundException ex) {
        // prepare responseEntity
        return responseEntity;
    }

}

#3


4  

Use code-based Servlet container initialization as described in the doc and override registerDispatcherServlet method to set throwExceptionIfNoHandlerFound property to true:

使用doc和覆盖registerDispatcherServlet方法中描述的基于代码的Servlet容器初始化将throwExceptionIfNoHandlerFound属性设置为true:

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

    @Override
    protected void registerDispatcherServlet(ServletContext servletContext) {
        String servletName = getServletName();
        Assert.hasLength(servletName, "getServletName() may not return empty or null");

        WebApplicationContext servletAppContext = createServletApplicationContext();
        Assert.notNull(servletAppContext,
            "createServletApplicationContext() did not return an application " +
                    "context for servlet [" + servletName + "]");

        DispatcherServlet dispatcherServlet = new DispatcherServlet(servletAppContext);

        // throw NoHandlerFoundException to Controller
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);

        ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
        Assert.notNull(registration,
            "Failed to register servlet with name '" + servletName + "'." +
                    "Check if there is another servlet registered under the same name.");

        registration.setLoadOnStartup(1);
        registration.addMapping(getServletMappings());
        registration.setAsyncSupported(isAsyncSupported());

        Filter[] filters = getServletFilters();
        if (!ObjectUtils.isEmpty(filters)) {
            for (Filter filter : filters) {
                registerServletFilter(servletContext, filter);
            }
        }

        customizeRegistration(registration);
    }
}    

Then create an exception handler:

然后创建一个异常处理程序

@ControllerAdvice
public class ExceptionHandlerController {
    @ExceptionHandler(Exception.class)
    public String handleException(Exception e) {
        return "404";// view name for 404 error
    }   
}

Don't forget about using @EnableWebMvc annotation on your Spring configuration file:

不要忘记在Spring配置文件中使用@EnableWebMvc注释:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages= {"org.project.etc"})
public class WebConfig extends WebMvcConfigurerAdapter {
    ...
}

#4


3  

Simple answer for 100% free xml:

100%免费xml的简单答案:

  1. Set properties for DispatcherServlet

    设置DispatcherServlet的属性

    public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[] { RootConfig.class  };
        }
    
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class[] {AppConfig.class  };
        }
    
        @Override
        protected String[] getServletMappings() {
            return new String[] { "/" };
        }
    
        @Override
        protected void customizeRegistration(ServletRegistration.Dynamic registration) {
            boolean done = registration.setInitParameter("throwExceptionIfNoHandlerFound", "true"); // -> true
            if(!done) throw new RuntimeException();
        }
    
    }
    
  2. Create @ControllerAdvice:

    创建@ControllerAdvice:

    @ControllerAdvice
    public class AdviceController {
    
        @ExceptionHandler(NoHandlerFoundException.class)
        public String handle(Exception ex) {
            return "redirect:/404";
        }
    
        @RequestMapping(value = {"/404"}, method = RequestMethod.GET)
        public String NotFoudPage() {
            return "404";
    
        }
    }
    

#5


3  

In your web configuration class,

在您的Web配置类中,

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter 

Declare a bean as follows,

声明一个bean如下,

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {

  return new EmbeddedServletContainerCustomizer() {
    @Override
    public void customize(ConfigurableEmbeddedServletContainer container)       
    {
      ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/401.html");
      ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
      ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html");

      container.addErrorPages(error401Page,error404Page,error500Page);
    }
  };
}

Add the mentioned html files(401.html .etc) to /src/main/resources/static/ folder.

将提到的html文件(401.html .etc)添加到/ src / main / resources / static /文件夹。

Hope this helps

希望这可以帮助

#6


3  

For Java config there is a method setThrowExceptionIfNoHandlerFound(boolean throwExceptionIfNoHandlerFound) in DispatcherServlet. By settting it to true I guess you are doing same thing

对于Java配置,DispatcherServlet中有一个方法setThrowExceptionIfNoHandlerFound(boolean throwExceptionIfNoHandlerFound)。通过将其设置为真,我猜你做的是同样的事情

<init-param>
    <param-name>throwExceptionIfNoHandlerFound</param-name>
    <param-value>true</param-value>
</init-param>

then you can can this NoHandlerFoundException.class in controller advice as stated in above answer

那么你可以在控制器建议中使用这个NoHandlerFoundException.class,如上面的答案中所述

it will be like something

它会像某样东西

public class WebXml implements WebApplicationInitializer{

    public void onStartup(ServletContext servletContext) throws ServletException {
        WebApplicationContext context = getContext();
        servletContext.addListener(new ContextLoaderListener(context));


        DispatcherServlet dp =  new DispatcherServlet(context);
        dp.setThrowExceptionIfNoHandlerFound(true);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", dp);
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping(MAPPING_URL);
    }
}

#7


1  

The solution proposed in comments above really works:

上面评论中提出的解决方案确实有效:

@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration)
{
  registration.setInitParameter("throwExceptionIfNoHandlerFound", "true");
}