spring的一個小例子(二)


        接上篇:http://www.cnblogs.com/xuejupo/p/5236448.html

        首先應該明白,一個web項目,web.xml是入口。

        然后下面來分析上篇博客中出現的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>webAppRootKey</param-name>
<param-value>maven.cainiao.root</param-value>
</context-param>

<!-- Spring的log4j監聽器 -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

<!-- 字符集 過濾器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Spring view分發器 -->
<servlet>
<servlet-name>dispatcher_cainiao</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher_cainiao.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher_cainiao</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

         首先是context-param參數,說context-param之前,應該有個概念:

         web.xml的加載過程是context-param -> listener  -> fileter  -> servlet。

         context-param屬性在xml文件里是最先被加載的,但是只有他是然並卵的,他必須配合別的java類一起使用。context-param差不多就相當於一個web項目的內置map,key和value都是String,context-param的加載只是為這個map賦值,相當於配置參      數,讓之后的監聽或者過濾器等能夠使用context-param中配置好的參數。

           舉個例子,我的web服務器是jboss,在context-param中配置參數

<context-param>    
<param-name>webAppRootKey</param-name>
<param-value>maven.cainiao.root</param-value>
</context-param>

后,jboss在加載這個項目的時候這個項目的別名就是maven.cainiao.root。這時候,如果在jboss中有別的項目也叫這個名字,那么jboss就會報錯。

      再比如說,如果要設定日志監聽,就要在context-param中配置log4jConfigLocation參數,log監聽器Log4jConfigListener會在加載的時候自動監聽log4jConfigLocation參數對應的值下的文件;再比如,ContextLoaderListener監聽器負責將contextConfigLocation參數路徑下的xml文件加載。

      當然,也可以自己做監聽或者過濾器,然后在web.xml中通過context-param配置過濾的參數(通過ServletConfig.getInitParameter(key))。

      然后就是org.springframework.web.util.Log4jConfigListener,這是一個spring的log4j監聽器。實際上我們不實用這個監聽也是可以的,但是使用它有幾個好處:

      首先如果不用他,那么log的配置文件log4j.properties必須寫在classpath下,而用它的話,你就可以很方便得管理log4j.properties的位置了。

      其次,這個監聽中有個方法會每隔60秒掃描log4j配置文件,這樣修改log4j配置文件就可以不用重啟服務了。

      再然后,字符過濾器CharacterEncodingFilter,可以看到filter-mapping中的url-pattern是/*,他負責將/*(也就是全部路徑)下的所有請求,強制轉換為UTF-8編碼的形式,這樣如果在編寫頁面的時候也用utf-8

編碼,就可以防止亂碼的產生了。

      最后就是跟我們打交道最多的servlet了。首先看servlet-mapping,這里有個url-pattern,這里匹配url里輸入的,比如說上面的web.xml中這里是/,那么,所有的http://localhost:8080/test/*的url都會被這個名字叫做dispatcher_cainiao的servlet解析。servlet-mapping下的servlet-name對應servlet下的servlet-name,根據name找到具體的servlet(servlet-mapping是servlet的入口,感覺更像是接口,負責servlet的入口url和對應具體的servlet實現類);而這個servlet-class,就是具體的servlet實現類了。當然,我們可以寫自己的實現類,這樣url就會請求到我們自己的servlet里(現在已經很少有這種寫法了),還可以交給spring托管,比如實現類寫org.springframework.web.servlet.DispatcherServlet,這是spring框架中的一個流程控制器,負責分發url。init-param表示將初始化他的配置參數,如上面的配置中,這個分發器使用的配置文件路徑為:/WEB-INF/dispatcher_cainiao.xml,load-on-startup表示他在web容易啟動的時候會自加載(這個很重要,不加這個你的url就找不到可以分發的servlet了)。

      再來看分發器使用的xml配置文件:

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

<mvc:annotation-driven />
<!-- <mvc:default-servlet-handler/> -->
<context:component-scan base-package="controller" />

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/" />
<property name="suffix" value=".jsp" />
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
</bean>
</beans>

          首先,mvc:annotation-driven是一種簡寫模式,表示自動加載DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter 兩個bean,是spring MVC為@Controllers分發請求所必須的。context:component-scan是spring中的自動掃描機制,負責掃描包以下所有類中包含的所有spring注解。

然后,就是注冊一個bean了:InternalResourceViewResolver,視圖解析類,就是將servlet中的返回解析到prefix對應參數文件夾下的suffix對應的后綴文件。

       他需要配合控制類使用:

package controller;


import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.cainiaojava.beans.User;


/**
* DispatcherController:
*
@author xuejupo jpxue@travelsky.com
*
* create in 2016-3-1 下午3:35:13
*
*/
@Controller
@RequestMapping(
"demo")
public class DispatcherController {
@RequestMapping(method
=RequestMethod.GET)
public String printWelcome(ModelMap model) {
User user
= new User();
user.setInfo(
"哈哈,我是唯一的用戶!");
user.setUserName(
"我是老大!");
user.setPasswd(
"不告訴你!");
model.addAttribute(
"str0121", "我去,成功了呀!!!");
model.addAttribute(
"info","當前用戶信息為:");
model.addAttribute(
"user", user);
System.out.println(
"index.jsp");
return "index";
}
}

@Controller表示這是一個控制器,@RequestMapping("demo")表示他接收后綴為demo的url(比如http://localhost:8080/test/demo),@RequestMapping(method=RequestMethod.GET)表示請求方式是get的話進這個方法,ModelMap是spring內置的ui控制類,可以將值傳到前端。 return "index",和前邊說的suffix參數的值,合組成index.jsp,所以這個servlet會將請求返回到頁面index.jsp中。

    總結一下:

     首先加載web.xml,web.xml中首先加載context-param,他們沒什么實際意義,只是一個上下文。然后加載監聽,上面的web.xml配置了log監聽器,所以加載Log4jConfigListener文件(配置log監聽器,應該要在context-param中配置log4jConfigLocation參數,我是犯懶,還沒配日志。。),然后,加載字符過濾器CharacterEncodingFilter,再然后自上而下加載servlet(本文只有一個servlet,不存在先后順序問題),加載DispatcherServlet分發器,這時候就要加載分發器的配置文件dispatcher_cainiao.xml了。在dispatcher_cainiao.xml中,因為 寫了mvc:annotation-driven,所以加載DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter兩個bean,然后掃描包controller,處理包controller下的所有文件包含的注解,然后配置視圖解析類InternalResourceViewResolver,再然后web項目啟動完畢。

       當我們請求http://localhost:8080/test/demo的時候,首先根據http://localhost:8080/test找到這個項目,然后根據/demo,在servlet-mapping中的url-pattern中查找對應的項,找到一個dispatcher_cainiao,然后根據注解@RequestMapping("demo")找到文件DispatcherController,然后進入相應的方法處理,最后返回的時候根據return值index和配置文件中的InternalResourceViewResolver視圖管理,找到jsp文件/views/index.jsp,最后就是渲染jsp文件了。

      ps:

       首先,web項目的唯一入口是web.xml(不知道是不是有其他入口,我是菜鳥,如果有其他入口希望大神留言指正),其他的xml文件都是在web.xml文件中注冊過的,或者是在servlet或者監聽器中被加載的,而監聽也是在web.xml中注冊的,所以所有的配置文件,都能從web.xml通過一定的路徑走到。學spring框架一定要知道他的大概流程是什么。所以初學spring,建議找一張白紙,好好畫一畫他的流程走向是什么,很有幫助的。

     歡迎轉載,但請標明出處:http://www.cnblogs.com/xuejupo/p/5252009.html,  也歡迎跟我討論。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com