[#0x002F] Spring-MVC example anatomy

  例子来自spring-framework-2.5.6.SEC01\docs\MVC-step-by-step\pdf\spring-mvc-step-by-step.pdf

  先上图,再慢慢解释。

1. DispatchServlet接过浏览器的/hello.htm请求

  在springapp/war/WEB-INF/web.xml中,定义了homepage:

<welcome-file-list>
	<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

所以浏览器端输入http://localhost:8080/springapp即相当于http://localhost:8080/springapp/index.jsp。

 

  而springapp/war/index.jsp是直接sendRedirect:

<%-- Redirected because we can't set the welcome page to a virtual URL. --%>
<c:redirect url="/hello.htm"/>

所以又转为http://localhost:8080/springapp/hello.htm

 

   在springapp/war/WEB-INF/web.xml中有:

<servlet>
	<servlet-name>springapp</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>springapp</servlet-name>
	<url-pattern>*.htm</url-pattern>
</servlet-mapping>

所以这个http://localhost:8080/springapp/hello.htm请求由DispatcherServlet来处理。

 

2.  DispatchServlet确定mapping of <Request, Controller>

  DispatchServlet默认使用的是BeanNameUrlHandlerMapping,即通过controller的bean name来与request对应。

  Controller在WebApplicationContext文件中定义,而WebApplicationContext文件的命名规则是<servlet-name>-servlet.xml,所以本案例的WebApplicationContext文件即是springapp-servlet.xml

  bean name必须是slash开头,然后只能写request中最后一个slash后面的部分。

<!-- spingapp/war/WEB-INF/springapp-servlet.xml -->

<bean name="/hello.htm" class="springapp.web.InventoryController">
	<property ......></property>
</bean>

 

  另外还有SimpleUrlHandlerMapping、ControllerClassNameHandlerMapping和CommonsPathMapHandlerMapping三种mapping形式,具体参见Spring in Action 2nd Edition 13.2

 

3. Controller返回ModelAndView给DispatchServlet

  Controller的类型有很多,最简单的形式就是自己实现一个Controller接口(spring自带了很多Controller及其子接口的实现),只需实现一个handleRequest(HttpServletRequest, HttpServletResponse)方法,返回一个ModelAndView即可。

  ModelAndView(ViewName, ModelName, ModelObject),其中的ModelName和ModelObject相当于给ViewName setAttribute(ModelName, ModelObject);ViewName可以写一个长路径,如“WEB-INF/jsp/hello.jsp”,更常见的方法是返回一个短字符串交给ViewResolver去解析。

 

4. DispatchServlet通过ViewResolver来解析ViewName

  DispatchServlet默认使用的ViewResolver是InternalResourceViewResolver(更多关于DispatchServlet的默认配置请参见spring-framework-2.5.6.SEC01\src\org\springframework\web\servlet\DispatcherServlet.properties),但与BeanNameUrlHandlerMapping不同的是,虽然InternalResourceViewResolver是默认的,但需要进一步对InternalResourceViewResolver进行配置。

<!-- spingapp/war/WEB-INF/springapp-servlet.xml -->

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

prefix + “hello” + suffix == "/WEB-INF/jsp/hello.jsp"(这里的“解析”更像是“拼接”)

 

  注意这里的bean id,虽然在spring-framework-2.5.6.SEC01\src\org\springframework\web\servlet\DispatcherServlet.java里有:

public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver";

但这里的bean id可以随便写。

  However, MessageSource类的bean id必须是"messageSource",不能随便写。我们在spring-framework-2.5.6.SEC01\src\org\springframework\context\support\AbstractApplicationContext.java里面可以看到有:

public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";

 

  另外,bean name和bean id的区别:

  Either one would work. It depends on your needs:
  If your bean identifier contains special character(s) for example (/viewSummary.html), it (the slash) won't be allowed as the bean id, because it's not a valid XML ID. In such cases you could skip defining the bean id and supply the bean name instead.
  The name attribute also helps in defining aliases for your bean, since it allows specifying multiple identifiers for a given bean.

 

5. JSP dispatched to browser by DispatchServlet

  hello.jsp被dispatch给浏览器显示,注意是dispatch,所以浏览器的地址栏仍然是hello.htm。

  JSP可以使用ModelAndView中的Model,形式如"${ModelName.ModelObject}",类似于getAttribute。

<%-- springapp/war/WEB-INF/jsp/hello.jsp --%>

<body>
	<h1><fmt:message key="heading"/></h1>
	<p><fmt:message key="greeting"/> <c:out value="${model.now}"></c:out></p>
	<h3>Product</h3>
	<c:forEach items="${model.products}" var="prod">
		<c:out value="${prod.description}"/> 
		<i><c:out value="${prod.price}"/></i><br><br>
	</c:forEach>
	<br>
	<a href="<c:url value="priceincrease.htm"/>">Increase Price</a>
	<br>
</body>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值