1. context:annotation-config
它的作用是隱式地向Spring容器注冊AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor這4個BeanPostProcessor。其作用是如果你想在程序中使用注解,就必須先注冊該注解對應的類,如下圖所示:
依賴的類 | 注解 |
CommonAnnotationBeanPostProcessor | @Resource 、@PostConstruct、@PreDestroy |
PersistenceAnnotationBeanPostProcessor | @PersistenceContext |
AutowiredAnnotationBeanPostProcessor | @Autowired |
RequiredAnnotationBeanPostProcessor | @Required |
另外還支持:@WebServiceRef,@EJB,@PersistenceUnit。
注意:
這個標簽不會激活處理Spring的@Transactional或EJB3的@TransactionAttribute注解。 考慮使用<tx:annotation-driven>標簽。
2. context:component-scan
掃描classpath時,被注釋的組件將自動注冊為Spring bean。 默認情況下,Spring提供的@Component,@Repository,@Service和@Controller原型會被檢測到。
這個標簽的存在意味可以不在xml中配置<context:annotation-config>標簽了。因為該標簽會支持@Required,@Autowired,@PostConstruct,@PreDestroy,@Resource,@PersistenceContext和@PersistenceUnit這些注釋,這通常是自動檢測組件的理想選擇(沒有外部配置)。 當然你可以選擇設置annotation-config屬性為false來棄用這個默認行為,該屬性默認為true。例如當你想使用自定義的BeanPostProcessor來處理這些注釋的時候你可以這么做。
另外需要注意:當Spring配置需要文件分層的時候,該標簽應該保證每一個配置文件都配置一次。這時就有點兒講究了,SpringMVC的dispatcher-servlet.xml配置文件可以只掃描帶有@Controller注解的類,而在Spring的applicationContext.xml文件中則可以掃描其他所有帶有注解的類(也可以過濾掉帶@Controller注解的類)。
除了必須指定的屬性base-package之外,<context:component-scan/>還可以指定如下屬性:
- resource-pattern:表示可以被自動檢測的Class的形式,默認為“**/*.class”,即所有的class文件。這個只是用來告訴Spring需要對哪些文件進行掃描,而並不是把它們自動定義為對應的bean。這個需要與后續需要介紹的filter區分開。
- use-default-filters:表示使用使用默認的filter,。<context:component-scan/>將把哪些Class自動注冊到bean容器是由對應的filter來控制的。該屬性的值默認為true,即默認會使用默認的filter。而默認的filter會將標注了@Component、@Controller、@Service和@Repository的類,包括這四個注解所標注的注解所標注的類,都會將它們自動注冊到bean容器中。
- annotation-config:是否啟用對注解的支持,即隱式的啟用<context:annotation-config/>,默認為true。
- name-generator:默認的beanName生成器,即在沒有顯式的指定beanName時,自動注冊的bean將如何使用默認的beanName。默認將使用Class的簡稱,即不包含包名的類名稱,並將首字母小寫作為當前bean的名稱。用戶可以通過實現org.springframework.beans.factory.support.BeanNameGenerator接口並指定其為當前的name-generator來改變對應的策略。
- scope-resolver:指定用於解析bean定義的scope的ScopeMetadataResolver,默認將通過AnnotationScopeMetadataResolver進行解析,而該解析器將根據類上標注的@Scope注解來解析對應的scope。默認沒有指定@Scope的都是單例。
- scoped-proxy:表示是否需要為自動檢測到的需要加入bean容器中的bean生成對應的代理。默認是不生成。可選值有“no”、“interfaces”和“targetClass”,分別對應不生成、根據接口生成和根據目標class生成。這對需要使用代理的scope是非常有必須要的,如request、session等。更詳細的內容請參考先前專門介紹scope的那篇文章。
3. mvc:annotation-driven
<mvc:annotation-driven/>會自動注冊LocaleResolver,ThemeResolver,HandlerMapping,HandlerAdapter,HandlerExceptionResolver,RequestToViewNameTranslator,ViewResolver,FlashMapManager這8個組件的實現類,這8個組件便是SpringMVC的核心組件。程序在運行時會先去容器中掃描看是否你自定義了某一組件的實現,如果沒有的話就使用properties文件中默認定義的實現類。
<mvc:annotation-driven/>標簽對應的解析類是AnnotationDrivenBeanDefinitionParser。從其中可以看出,該標簽為我們做了這些配置:
- 支持使用了像@RquestMapping、@ExceptionHandler等等的注解的controller方法去處理請求。
- 支持使用@RequestBody、@ResponseBody注解。
- 並提供了:數據綁定支持,@NumberFormat注解的支持對數據類型進行格式化,@DateTimeFormat支持
- 支持使用@Valid對javaBean進行JSR-303驗證。
- 讀寫XML的支持(JAXB),讀寫JSON的支持(Jackson)。
對於HttpMessageConverter,它到底是干什么的呢?它是用來將特定的對象轉換成字符串並最終作為HttpResponse返回的工具。實際上SpringMVC中面向開發人員的業務邏輯處理主要集中在各種Controller的方法中,基本模式是接受代表着HttpRequest的各種輸入參數,在方法體中進行業務邏輯處理,最后得到輸出結果,並以返回值的形式交給SpringMvc,Springmvc根據返回值的不同調用不同的處理邏輯並最終以HttpResponse的形式返回給客戶端。Controller中的返回值可以有很多種,比如字符串,ModelAndView,普通對象,等等,甚至void類型都是可以的。所以SpringMvc會根據返回值的類型做很多的if else,不同的類型調用不同的處理邏輯。那么當函數接受@ResponseBody聲明時,Spring就會嘗試用配置好的各種HttpMessageConverter來將返回值進行序列化。不同HttpMessageConverter能夠處理的對象以及處理方式都是不一樣的,Spring會遍歷各Converter,如果該Converter能夠處理該對象則交由其處理。因此,很多基於Spring的REST風格的應用常常會返回一個model對象,那么你就應該配置好正確的HttpMessageConverter,以便Spring能夠正確的將這些對象序列化回客戶端。
4. mvc:default-servlet-handler
其實當一個請求來到的時候,它的執行流程是先經過tomcat的servlet的url-pattern的匹配。進入到了SpringMVC,然后對於SpringMVC框架來說,為了處理對應的請求時,首先會去找對應的HandlerMapping看是否有對應的類來處理該請求,如果有的話再根據HandlerAdapter去找是什么類,以及對應的處理方法。找不到的時候會報404。但當配置了<mvc:default-servlet-handler>標簽的時候,它會注冊SimpleUrlHandlerMapping來處理請求映射,對應的Handler是DefaultServletHttpRequestHandler,這種情況一般是其他HandlerMapping無法匹配處理,最后才無奈交給DefaultServletHttpRequestHandler來處理。而該Handler具體的做法其實就是轉發給了web容器自身的defaultServlet來處理。這個servlet名稱可以在mvc:default-servlet-handler標簽中進行配置,如果沒有配置,采用默認的配置,tomcat默認的servlet名稱為default。即tomcat、Jetty等,在容器啟動的時候,自身就默認注冊了一個name叫default的servlet,DefaultServletHttpRequestHandler就是轉發給這些servlet。defaultServlet會去尋找有沒有該文件,找到了解析並返回文件內容,比如我們常請求的jsp頁面,就是通過JspServlet來進行翻譯的。找不到則404。但是你可以通過自定義servlet來替換defaultServlet。給用戶返回自定義的一些信息。
5. mvc:resources
<mvc:default-servlet-handler />將靜態資源的處理經由Spring MVC框架交回Web應用服務器處理。而<mvc:resources />更進一步,由Spring MVC框架自己處理靜態資源,並添加一些有用的附加值功能。<mvc:resources />允許靜態資源放在任何地方,如WEB-INF目錄下、類路徑下等,你甚至可以將JavaScript等靜態文件打到JAR包中。通過location屬性指定靜態資源的位置,由於location屬性是Resources類型,因此可以使用諸如classpath:等的資源前綴指定資源位置。傳統Web容器的靜態資源只能放在Web容器的根路徑下,<mvc:resources />完全打破了這個限制。
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory --> <resources mapping="/resources/**" location="/resources/" />