为什么SpringMVC用404响应并报告“在dispatcherservlet中找不到uri为[…]的http请求的Map”?

x33g5p2x  于 2021-06-30  发布在  Java
关注(0)|答案(8)|浏览(311)

我正在编写一个部署在tomcat上的springmvc应用程序。请参阅以下最小、完整且可验证的示例

public class Application extends AbstractAnnotationConfigDispatcherServletInitializer {
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { };
    }
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { SpringServletConfig.class };
    }
    protected String[] getServletMappings() {
        return new String[] { "/*" };
    }
}

哪里 SpringServletConfig

@Configuration
@ComponentScan("com.example.controllers")
@EnableWebMvc
public class SpringServletConfig {
    @Bean
    public InternalResourceViewResolver resolver() {
        InternalResourceViewResolver vr = new InternalResourceViewResolver();
        vr.setPrefix("/WEB-INF/jsps/");
        vr.setSuffix(".jsp");
        return vr;
    }
}

最后,我有一个 @Controller 在包裹里 com.example.controllers ```
@Controller
public class ExampleController {
@RequestMapping(path = "/home", method = RequestMethod.GET)
public String example() {
return "index";
}
}

我的应用程序的上下文名称是 `Example` . 当我向发送请求时

http://localhost:8080/Example/home

应用程序响应http状态404并记录以下内容

WARN o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/Example/WEB-INF/jsps/index.jsp] in DispatcherServlet with name 'dispatcher'

我有一个jsp资源在 `/WEB-INF/jsps/index.jsp` 我希望springmvc使用我的控制器来处理请求并转发到jsp,那么为什么它用404来响应呢?
这是一个关于这个警告信息的问题的规范帖子。
eivnm1vs

eivnm1vs1#

在我的例子中,我正在尝试将辅助java配置文件导入主java配置文件。在生成辅助配置文件时,我更改了主配置类的名称,但未能更新web.xml中的名称。因此,每次重新启动tomcat服务器时,我都没有看到eclipse ide控制台中记录的Map处理程序,当我尝试导航到主页时,我看到以下错误:
2019年11月1日11:00:01 pm org.springframework.web.servlet.pagenotfound nohandlerfound警告:在名为“dispatcher”的dispatcherservlet中找不到uri为[/webapp/home/index]的http请求的Map
修复方法是更新web.xml文件,使旧名称“webconfig”改为“mainconfig”,只需重命名它以反映主java配置文件的最新名称(其中“mainconfig”是任意的,此处使用的“web”和“main”不是语法要求)。mainconfig很重要,因为它是对“webcontroller”进行组件扫描的文件,我的spring mvc控制器类处理我的web请求。

@ComponentScan(basePackageClasses={WebController.class})

web.xml具有以下特性:

<init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        com.lionheart.fourthed.config.WebConfig
    </param-value>
</init-param>

网站.xm

daolsyd0

daolsyd02#

您的标准springmvc应用程序将通过 DispatcherServlet 您已经向servlet容器注册了。
这个 DispatcherServlet 看看它的 ApplicationContext 如果有的话 ApplicationContext 已注册 ContextLoaderListener 对于特殊bean,它需要设置其请求服务逻辑。文档中描述了这些bean。
可以说是最重要的豆子类型 HandlerMapping Map
传入到处理程序的请求以及基于某些条件的前置和后置处理程序(处理程序拦截器)列表,这些条件的详细信息因时间而异 HandlerMapping 实施。最流行的实现支持带注解的控制器,但也存在其他实现。
的javadoc HandlerMapping 进一步描述实现必须如何运行。
这个 DispatcherServlet 查找此类型的所有bean并按一定顺序注册它们(可以自定义)。在处理请求时 DispatcherServlet 循环通过这些 HandlerMapping 对象并用 getHandler 找到一个可以处理传入请求的,表示为标准的 HttpServletRequest . 从4.3.x开始,如果找不到任何警告,它会记录您看到的警告
找不到uri为的http请求的Map [/some/path]DispatcherServlet 有名字somename
要么扔一个 NoHandlerFoundException 或者立即提交带有404notfound状态码的响应。

为什么dispatcherservlet没有找到一个handlermapping来处理我的请求?

最常见的 HandlerMapping 实施是 RequestMappingHandlerMapping ,它处理注册 @Controller 作为处理程序的bean(实际上是它们的 @RequestMapping 带注解的方法)。您可以自己声明这种类型的bean(使用 @Bean 或者 <bean> 或者您可以使用内置选项。这些是:
为您的 @Configuration 与…同班 @EnableWebMvc .
宣布 <mvc:annotation-driven /> xml配置中的成员。
正如上面的链接所描述的,这两个都将注册一个 RequestMappingHandlerMapping 豆子(还有一堆其他的东西)。然而,一个 HandlerMapping 没有处理程序就没什么用。 RequestMappingHandlerMapping 期待一些 @Controller 所以你也需要通过 @Bean java配置中的方法或 <bean> xml配置中的声明或通过组件扫描 @Controller 其中一个中的注解类。确保这些豆子存在。
如果您收到了警告消息和404,并且已经正确配置了上述所有内容,那么您将请求发送到错误的uri,一个未被检测到的uri处理的uri @RequestMapping 带注解的处理程序方法。
这个 spring-webmvc 图书馆提供其他内置 HandlerMapping 实现。例如, BeanNameUrlHandlerMapping Map
从URL到名称以斜杠(“/”)开头的bean
你也可以自己写。显然,您必须确保您发送的请求与至少一个已注册的请求匹配 HandlerMapping 对象的处理程序。
如果您不隐式或显式注册 HandlerMapping 豆子(或 detectAllHandlerMappingstrue ),的 DispatcherServlet 注册一些默认值。这些定义见 DispatcherServlet.properties 在同一个包裹里 DispatcherServlet 班级。他们是 BeanNameUrlHandlerMapping 以及 DefaultAnnotationHandlerMapping (类似于 RequestMappingHandlerMapping 但不赞成)。

调试

springmvc将记录通过 RequestMappingHandlerMapping . 例如,一个 @Controller 喜欢

@Controller
public class ExampleController {
    @RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom")
    public String example() {
        return "example-view-name";
    }
}

将在信息级别记录以下内容

Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()

这描述了注册的Map。当您看到未找到处理程序的警告时,请将消息中的uri与此处列出的Map进行比较。中指定的所有限制 @RequestMapping 必须匹配springmvc才能选择处理程序。
其他 HandlerMapping 实现记录它们自己的语句,这些语句应该提示它们的Map和相应的处理程序。
类似地,在调试级别启用spring日志记录以查看spring注册了哪些bean。它应该报告找到了哪些带注解的类,扫描了哪些包,以及初始化了哪些bean。如果你期望的那些没有出现,那么回顾一下你的想法 ApplicationContext 配置。

其他常见错误

DispatcherServlet 只是一个典型的javaee Servlet . 你把它注册到你的
<web.xml> <servlet-class> 以及 <servlet-mapping> 申报,或直接通过 ServletContext#addServlet 在一个 WebApplicationInitializer ,或者使用spring boot使用的任何机制。因此,您必须依赖servlet规范中指定的urlMap逻辑,请参阅第12章。另请参见
如何使用web.xml中的servlet urlMap?
有鉴于此,一个常见的错误是注册 DispatcherServlet urlMap为 /* ,从 @RequestMapping 处理程序方法,并期望呈现一个jsp。例如,考虑如下处理程序方法

@RequestMapping(path = "/example", method = RequestMethod.GET)
public String example() {
    return "example-view-name";
}

带着一个 InternalResourceViewResolver ```
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}

您可能希望请求被转发到路径上的jsp资源 `/WEB-INF/jsps/example-view-name.jsp` . 这不会发生的。相反,假设上下文名称为 `Example` ,的 `DisaptcherServlet` 将报告
找不到uri为的http请求的Map `[/Example/WEB-INF/jsps/example-view-name.jsp]` 在 `DispatcherServlet` “调度员”
因为 `DispatcherServlet` 已Map到 `/*` 以及 `/*` 匹配所有内容(精确匹配除外,后者具有更高的优先级) `DispatcherServlet` 会被选来处理 `forward` 从 `JstlView` (由 `InternalResourceViewResolver` ). 在几乎所有的情况下 `DispatcherServlet` 将不配置为处理此类请求。
相反,在这种过于简单的情况下,您应该注册 `DispatcherServlet` 至 `/` ,将其标记为默认servlet。默认servlet是请求的最后一个匹配项。这将允许您的典型servlet容器选择一个内部servlet实现,Map到 `*.jsp` ,来处理jsp资源(例如,tomcat `JspServlet` ),然后尝试使用默认servlet。
这就是你在例子中看到的。
hgtggwj0

hgtggwj03#

尝试用配置文件中的以下更改来修改代码。使用java config代替 application.properties . 不要忘记在中启用配置 configureDefaultServletHandling 方法。 WebMvcConfigurerAdapter 类已弃用,因此我们使用 WebMvcConfigurer 接口。

@Configuration
@EnableWebMvc
@ComponentScan
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

我使用gradle,你应该在 pom.xml :

dependencies {

    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.3.0.RELEASE'
    compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '9.0.35'
}
zujrkrfu

zujrkrfu4#

对我来说,我发现我的目标类是在一个文件夹模式中生成的,而不是源。这可能是在eclipse中,我添加包含控制器的文件夹,而不是将它们作为包添加。所以我在spring配置中定义了错误的路径。
我的目标类是在app下生成类,我指的是com.happy.app

<context:annotation-config />
<context:component-scan
    base-package="com.happy.app"></context:component-scan>

我为com.happy.app添加了包(而不是文件夹),并在eclipse中将文件从文件夹移到包中,解决了这个问题。

dzjeubhm

dzjeubhm5#

清理服务器。可能会删除服务器并再次添加项目并运行。
停止tomcat服务器
右键单击服务器并选择“清除”
再次右键单击服务器并选择“清理tomcat工作目录”

xlpyo6sf

xlpyo6sf6#

我遇到了另一个同样错误的原因。这也可能是由于没有为controller.java文件生成类文件。因此,web.xml中提到的DispatcherServlet无法将其Map到控制器类中的相应方法。

@Controller
Class Controller{
@RequestMapping(value="/abc.html")//abc is the requesting page
public void method()
{.....}
}

在eclipse中的project->select clean->build project.do下检查是否已经为工作区中builds下的controller文件生成了类文件。

hgc7kmma

hgc7kmma7#

我解决了我的问题,除了之前描述的:`

@Bean
public InternalResourceViewResolver resolver() {
    InternalResourceViewResolver vr = new InternalResourceViewResolver();
    vr.setPrefix("/WEB-INF/jsps/");
    vr.setSuffix(".jsp");
    return vr;
}
``` `added tomcat-embed-jasper:` ```
<dependency>
       <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
       <scope>provided</scope>
</dependency>

`from:jsp文件未在spring boot web应用程序中呈现

xqkwcwgp

xqkwcwgp8#

在我的例子中,我遵循了5.1.2版的拦截器spring文档(同时使用springbootv2.0.4.release)和 WebConfig 类有注解 @EnableWebMvc ,这似乎与我的应用程序中阻止正确解析静态资产的其他内容相冲突(即没有css或js文件返回到客户端)。
在尝试了很多不同的东西之后,我试着把 @EnableWebMvc 成功了!
编辑:这里的参考文档说,你应该删除 @EnableWebMvc 注解
显然,至少在我的例子中,我已经在配置我的spring应用程序(尽管不是通过使用 web.xml 或者任何其他静态文件,它肯定是编程的),所以这是一个冲突。

相关问题