为什么/home.jsp的bean名称不能用于BeanNameUrlHandlerMapping?

时间:2012-08-25 09:13:00

标签: spring spring-mvc

在以下程序中,如果我将“/home.htm”替换为dispatcher-servlet.xml和index.jsp中的“/home.jsp”,则服务器无法找到home.jsp。以“.jsp”结尾的字符串是否作为bean名称无效?

调度-servlet.xml中

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <bean name="/home.htm" class="com.sample.HomePageController" />

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

</beans>

的index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Dynamic Tiles</title>
  </head>
  <body>
    <form action="/home.htm" method="post">
        Please enter your name:&nbsp;
        <input type="text" name="visitorName" />
        <input type="submit" value="Go"/>
    </form>
  </body>
</html>

HomePageController.java

package com.sample;

import org.apache.log4j.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

public class HomePageController  extends AbstractController {

    private static Logger logger = Logger.getLogger(HomePageController.class);

    HomePageController () {
        logger.info("Constructing HomePageController object");
    };

    public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.info("Handling request for home.jsp");

        return new ModelAndView("home", "visitorName", request.getParameter("visitorName"));
    }

}

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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"
           version="2.5">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

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

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>

</web-app>

2 个答案:

答案 0 :(得分:1)

您的应用程序有几个部分需要修改才能按预期工作。第一部分是web.xml中的Dispatcher Servlet映射。在Spring中,调度程序用于将来自客户端的特定请求路由到应用程序内的Spring控制器。通过调度程序路由的请求由servlet的web.xml文件中指定的url-pattern确定:org.springframework.web.servlet.DispatcherServlet。

在您的情况下,我们希望将url-pattern设置为与访问jsp文件不冲突的内容。由于您在Spring配置中指定了一个viewResolver,它在通用名称前加上/ WEB-INF / jsp /并用.jsp后缀它们,我们必须使用除.jsp之外的url-pattern。

如果使用.jsp url-pattern,则调度程序servlet首先处理请求并将其路由到任何映射控制器。如果控制器尝试使用视图名称导航到另一个页面(例如home),则视图名称带有前缀/后缀,从而生成url:/WEB-INF/jsp/home.jsp。这个构造的URL匹配为调度程序指定的.jsp url-pattern,并尝试路由/WEB-INF/jsp/home.jsp,很可能失败,因为没有找到映射。

要解决此问题,我们按如下方式设置您的web.xml:

<强> 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">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

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

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>

如您所见,我们将调度程序映射到url-pattern * .do。这允许调度程序用于路由请求而不干扰公共文件前缀。 将url-pattern更改为* .do要求我们更改表单上的操作。我将您的表单修改为以下内容:

<强>的index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
<title>Dynamic Tiles</title>
</head>
<body>
    <form action="home.do" method="post">
        Please enter your name:&nbsp; <input type="text" name="visitorName" />
        <input type="submit" value="Go" />
    </form>
</body>
</html>

我还假设您的所有.jsp文件都位于WEB-INF目录中。这要求我们使用控制器来访问每个.jsp文件。必须在Spring配置文件中为调度程序创建到控制器的映射,并且必须创建适当的index.jsp控制器。请注意,我使用.do后缀作为映射。

<强>调度-servlet.xml中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="handlerMapping"
        class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
    <bean name="/home.do" class="com.sample.HomePageController" />
    <bean name="/index.do" class="com.sample.IndexPageController" />

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
</beans>

<强> IndexPageController.java

package com.sample;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

public class IndexPageController extends AbstractController {

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest arg0,
            HttpServletResponse arg1) throws Exception {
        return new ModelAndView("index");
    }
}

为了彻底,我创建了一个home.jsp文件来测试应用程序,因为没有提供。这是我的home.jsp文件:

<强>回到Home.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
    <title>Home</title>
</head>
<body>
<h1>
    Hello, ${visitorName}  
</h1>

<P>  The time on the server is ${serverTime}. </P>
</body>
</html>

答案 1 :(得分:0)

您认为dispatcher只会处理.htm - 结束网址,但您希望它处理.jsp - 结束网址。要让后者工作,只需将url-patternweb.xml元素的内容更改为,例如:

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.jsp</url-pattern>
</servlet-mapping>