spring2.0 sample 之 countries

首先当然是从配置文件入手。先看看 web.xml.

java 代码
xml 代码
  1. <listener>  
  2.     <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>  
  3. listener>  

这句的作用是初始化 applicationContext, 默认使用的配置文件就是 applicationContext.xml

java 代码
xml 代码
  1. <servlet>  
  2.     <servlet-name>countriesservlet-name>  
  3.     <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>  
  4.     <load-on-startup>2load-on-startup>  
  5. servlet>  
  6.   
  7. <servlet-mapping>  
  8.     <servlet-name>countriesservlet-name>  
  9.     <url-pattern>*.htmurl-pattern>  
  10. servlet-mapping>  
  11.   
  12. <servlet-mapping>  
  13.     <servlet-name>countriesservlet-name>  
  14.     <url-pattern>*.pdfurl-pattern>  
  15. servlet-mapping>  
  16.   
  17. <servlet-mapping>  
  18.     <servlet-name>countriesservlet-name>  
  19.     <url-pattern>*.xlsurl-pattern>  
  20. servlet-mapping>  

这些代码就是配置servlet,非常熟悉不过了。通过这样的配置,所有的请求都由org.springframework.web.servlet.DispatcherServlet 来处理。

 接下来看看 applicationContext.xml.

xml 代码
  1. <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">      
  2.     <property name="basename" value="messages"/>  
  3. bean>  
  4.   
  5.   
  6. <bean id="countryService" class="org.springframework.samples.countries.DefaultCountryService"/>  

 messageSource 是spring国际化的方式。 在这个例子里,spring   会在classpath 里寻找 messages_en.properties, messages_zh_cn.properties 等国际化的文件。一般这些文件都放到 /WEB-INF/classes 里,当然你放到别的也可以,
只要是在 classpath 里。

countryService 是一个 bean 了,可以看到它具体对应的class.

在 web.xml 里,我们配置了 servlet 的处理方式,那么处理那些请求的配置文件在哪呢?
在这个例子里,默认是 “countries-servlet.xml”。规则是什么呢?
如果定义servlet 的时候是如下这样:

xml 代码
  1. <servlet-name>countries<servlet-name>   

那么默认的就是 “countries-servlet.xml”。也就是 servlet名字+"-servlet.xml" .

 

那么精化部分就应该都在 countries-servlet.xml 里了,看看这个配置文件吧。

xml 代码
  1. <bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">  
  2.     <property name="basename" value="views-countries"/>  
  3.     <property name="defaultParentView" value="modelView"/>  
  4. bean>  

这里用了spring 中的一种视图方式,关于视图的详细信息,请参考
http://www.redsaga.com/spring_ref/2.0/html/mvc.html#mvc-viewresolver

不过这里也简单说一下这个 ResourceBundleViewResolver.
它有2个属性。
basename : 指定了去读取哪个配置文件。在这个例子中,spring 会去读取 views-countries.properties, 如果有国际化的
                       的信息,还会去读取 views-countries_en.properties,  views-countries_zh_CN.properties 等文件。


defaultParentView : 指定了视图的父类。这里的父类并不是java的class. 而是配置文件的继承。

多说无用,非常抽象,还是看看 views-countries.properties 文件来得实在。

 

  1. modelView.(class)=org.springframework.web.servlet.view.JstlView   
  2. modelView.requestContextAttribute=rc   
  3. modelView.url=/WEB-INF/views/jsp/countries/model.jsp   
  4.   
  5. #--------------------------------------------------------   
  6.   
  7. homeView.attributesCSV=htitle=[home.htitle],nav=[nav.jsp],content=[home.jsp]   
  8.   
  9. copyView.attributesCSV=htitle=[copy.htitle],nav=[nav.jsp],content=[copy.jsp]   
  10.        
  11. configView.attributesCSV=htitle=[config.htitle],nav=[nav.jsp],content=[config.jsp]   
  12.   
  13. countries_mainView.attributesCSV=htitle=[countries.main.htitle],\   
  14.     nav=[main/nav.jsp],\   
  15.     content=[main/home.jsp]   
  16.   
  17. countries_detailView.attributesCSV=htitle=[countries.detail.htitle],\   
  18.     nav=[main/detailnav.jsp],\   
  19.     content=[main/detail.jsp]   
  20.   
  21. countries_excelView.(class)=org.springframework.samples.countries.web.CountriesExcelView   
  22.   
  23. countries_pdfView.(class)=org.springframework.samples.countries.web.CountriesPdfView   
  24.   
  25. #--------------------------------------------------------   
  26.   
  27. errorHttp404View.attributesCSV=htitle=[error.http404.htitle],nav=[nav.jsp],content=[../errors/http404.jsp]   

 

 首先我们看到对 modelView 的定义,也就是 defaultParentView  的 value.
处理这个View的类是 org.springframework.web.servlet.view.JstlView
处理这个View的页面是 /WEB-INF/views/jsp/countries/model.jsp

 请记住,这个 modelView 是下面所有其他的view的“父类”,也就是下面的view都是“继承”这些配置的。

 举个例子来说,homeView.attributesCSV=htitle=[home.htitle],nav=[nav.jsp],content=[home.jsp]
处理这个 homeView 的类就是 org.springframework.web.servlet.view.JstlView
处理这个 homeView 的页面就是 /WEB-INF/views/jsp/countries/model.jsp

那我们是不是很疑惑,为什么所有的view的处理页面都是 /WEB-INF/views/jsp/countries/model.jsp ??

没错,看看 model.jsp , 其实就是一个模板!

xml 代码
  1. >  
  2. <%@ include file="../common/includes.jsp" %>  
  3.   
  4. <html xmlns="http://www.w3.org/1999/xhtml">  
  5.   <head>  
  6.     <title><fmt:message key="${htitle}"/>title>  
  7.     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />  
  8.     <c:set var="css"><spring:theme code="css"/>c:set>  
  9.     <c:if test="${not empty css}"><link rel="stylesheet" href="
  10.   head>  
  11.   <body>  
  12.     <div id="pageContent">  
  13.     <div id="inContent">  
  14.     <div id="nav"><c:import url="${nav}"/>div>  
  15.     <div id="top"><c:import url="top.jsp"/>div>  
  16.     <div id="content"><h1><fmt:message key="app.short"/>h1><c:import url="${content}"/>div>  
  17.     <div id="footer"><c:import url="${nav}"/>div>  
  18.     div>  
  19.     div>  
  20.   body>  
  21. html>  

具体的 htitle, content, 都是子类(如 homeView)里传递过去的。

(这部分比较头晕的是 父类,子类,继承,千万不要弄成java里的概念)

如何处理视图已经弄清楚了,那么继续往下看 countries-servlet.xml.

xml 代码
  1. <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/>  
  2.   
  3. <bean id="themeResolver" class="org.springframework.web.servlet.theme.CookieThemeResolver">  
  4.     <property name="defaultThemeName" value="spring"/>  
  5. bean>  

这里定义了两个 Resolver bean, 关于这两个 Resolver 的详细信息,可以参考:
http://www.redsaga.com/spring_ref/2.0/html/mvc.html#mvc-localeresolver
http://www.redsaga.com/spring_ref/2.0/html/mvc.html#mvc-themeresolver

这里就不多解释了,相信上面的资料足够让您看懂。

在继续往下看:

xml 代码
  1. <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
  2.     <property name="interceptors">  
  3.         <list>  
  4.             <ref bean="localeChangeInterceptor"/>  
  5.             <ref bean="themeChangeInterceptor"/>  
  6.         list>  
  7.     property>  
  8.     <property name="mappings">  
  9.         <props>  
  10.             <prop key="/home.htm">countriesControllerprop>  
  11.             <prop key="/config.htm">countriesControllerprop>  
  12.             <prop key="/copy.htm">countriesControllerprop>  
  13.             <prop key="/main/home.htm">countriesControllerprop>  
  14.             <prop key="/main/detail.htm">countriesControllerprop>  
  15.             <prop key="/main/countries.xls">countriesControllerprop>  
  16.             <prop key="/main/countries.pdf">countriesControllerprop>  
  17.             <prop key="/notfound.htm">errorsControllerprop>  
  18.         props>  
  19.     property>  
  20. bean>  

 这里定义了 url 的处理,例如 /home.htm 这个 url 会由 countriesController 这个类来处理。

不过这里还有 “interceptors”这个配置,这个叫做拦截器,详细信息可以参考
http://www.redsaga.com/spring_ref/2.0/html/mvc.html#mvc-handlermapping-interceptor

相信上面的信息足够让人明白拦截器是什么东东。
我们先看看这两个拦截器是如何定义的:

xml 代码
  1. <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>  
  2.   
  3. <bean id="themeChangeInterceptor" class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>  

都是用的 spring 默认的拦截器。

好了,拦截器就到此为止。继续看看上面的 url 处理的定义。
我们可以看到,好多 url 都用的同一个 controller 来处理,那么这个 controller 该如何处理这些请求?
下意识的想法可能是在 controller 里有这样的代码:

java 代码
  1. if ( url 来自 home,htm) {   
  2.   
  3. else if (url 来自 copy.htm ) {   
  4.   
  5. else {   
  6.   
  7. }  

那就看看 spring 是如何做的吧.

java 代码
xml 代码
  1. <bean id="errorsController" class="org.springframework.samples.countries.web.ErrorsController">  
  2. <property name="methodNameResolver">  
  3. <bean    
  4. class="org.springframework.web.servlet.mvc.multiaction.Propertie   
  5. sMethodNameResolver">  
  6.             <property name="mappings">  
  7.                 <props>  
  8.                 <prop key="/notfound.htm">handleHttp404</prop>  
  9.                 </props>  
  10.             </property>  
  11.         </bean>  
  12.     </property>  
  13. </bean>  
  14.   
  15. <!-- Application specific multi-action controller -->  
  16. <bean id="countriesController"    
  17. class="org.springframework.samples.countries.web.CountriesController">  
  18.         <property name="methodNameResolver">  
  19.             <bean    
  20. class="org.springframework.web.servlet.mvc.multiaction.P   
  21. ropertiesMethodNameResolver">  
  22.                 <property name="mappings">  
  23.                     <props>  
  24.                     <prop key="/home.htm">handleHome</prop>  
  25.                     <prop key="/config.htm">handleConfig</prop>  
  26.                     <prop key="/copy.htm">handleCopy</prop>  
  27.                     <prop key="/main/home.htm">handleMain</prop>  
  28.                     <prop key="/main/detail.htm">handleDetail</prop>  
  29.                     <prop    
  30. key="/main/countries.xls">handleExcel   
  31. </prop>  
  32.                     <prop    
  33. key="/main/countries.pdf">handlePdf   
  34. </prop>  
  35.                     </props>  
  36.                 </property>  
  37.             </bean>  
  38.         </property>  
  39.         <property name="countryService" ref="countryService"/>  
  40. </bean>  

虽然这里定义了2个controller,但是都是一样的用法。

我们注意到这样的定义:

java 代码
  1. "methodNameResolver">   
  2.             class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">   
  3. 。。。。 省略  

不用说,这肯定是 spring 的一种用法了!

不过我们还是先看看 org.springframework.samples.countries.web.CountriesController 是怎么定义的吧:

 

java 代码
  1. public class CountriesController extends MultiActionController  

“MultiActionController”?从名字可以知道,应该是一个特殊的controller,专门处理多个action的!
可以参考这里 http://www.redsaga.com/spring_ref/2.0/html/mvc.html#mvc-controller-multiaction

相信上面的信息会给您满意的答案!

明白了 MultiActionController,我们也就知道了,这样的配置,意思是 对于 /home.htm 这样的url, 会调用 handleHome 这个方法。

  1. <prop key="/home.htm">handleHome<prop>  

 

可见,如果一个 controller 处理多个 action,可以把被调用的方法的名字直接写到配置文件里。

到目前为止,我们还没看过这个例子里的java代码,但我想,我们对整个的结构,应该有一个大概的了解了。

那么现在就去看看 CountriesController.java .

 先挑一个方法看看:

java 代码
  1. public ModelAndView handleHome(HttpServletRequest request, HttpServletResponse response) throws ServletException {   
  2.     return new ModelAndView(homeView);   
  3. }  

简单不过的方法,这个 homeView 通过查代码知道是 “homeView”这个字符串。

那么整个流程我们现在应该十分清晰了:
系统得到一个 home.htm 的请求,spring 调用 CountriesController 的 handleHome 来处理,返回 "homeView" 构造
ModelAndView 对象。根据前面的 ResourceBundleViewResolver 的定义,系统会显示
/WEB-INF/views/jsp/countries/model.jsp 这个页面,不过这个页面其实只是个 模板,里面的信息是通过
homeView.attributesCSV=htitle=[home.htitle],nav=[nav.jsp],content=[home.jsp]  来确定的。

另外不要忘了那些国际化的部分,在这个例子里,如果有国际化信息,那么相应的配置的文件也会加上一些 "_en",
"_zh_CN" 的后缀。

CountriesController 里还有一个类的定义:

private CountryService countryService;

这个类可不是 countryService = new CountryService () 方式获得的,

xml 代码
  1. <property name="countryService" ref="countryService"/>  

这样的方式注入的。

CountryService 类的内容就不多说,因为和spring本身的特点没什么太大的关系。

 

这个例子不复杂,但是涉及的内容却不少,Resolver, Interceptor, MultiActionController, 国际化。

从这个小小的例子也可以看出,spring 实在是太灵活,
如果说 structs 类的framework 是降龙十八掌,那 spring 就得说是有九九八十一招的武功,招数实在太多,
临敌的时候选择哪个招式,还真的仔细考虑 :)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值