<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    推薦淘寶秋冬男裝熱賣網店

    追求無止境

    我的程序人生
    隨筆 - 31, 文章 - 2, 評論 - 20, 引用 - 0
    數據加載中……

    2009年11月25日

    有一天你會長大

    什么話該說,什么話不該說,該說的話該怎么說。誰能告訴我。

    posted @ 2010-01-19 13:21 追求無止境 閱讀(202) | 評論 (0)編輯 收藏

    2009年度盛事 - 總結2009

           2009年12月31日,站在2009年的尾巴上,不禁感到時間飛逝。2009年,匆匆而過。在過去的2009年,收獲何多,失去何多。2009年,對我來說,是一個重要的轉折點。漸漸的發現自己應該長大了,也發現自己確實長大了,更發現自己實際上還是需要繼續長大。

          每年的這個時候,各個新聞媒體都會評出什么十大之類的,我也落一會俗(當然自己本身就很俗),來看看今年發生在我身上的幾大事件:

    先大體羅列一下吧:

    1. 訂婚
    2. 進京
    3. 工作
    4. 畢業
    5. 讀研
    6. 買筆記本

         從時間跨度上來說, 1月到2月在家過年,2月和3月在青島某公司實習,4月和5月在北京某公司實習,6月在中國石油大學享受畢業之前的時光,7月到8月繼續在北京某公司實習,9月到12月在上學+實習。2009年最幸福的事情發生在1到2月,盡快也有不快;最平常的日子在2月和3月,到了4月和5月或許是我最糾結的日子吧;6月或許是最快樂的日子的吧;7月和8月讓我體會到了工作的滋味;而9月到12月,整天在公司與學校之間奔跑,知道了工作+上課兩者要做到兼顧的滋味,雖然并沒有做到兼顧。

         2009年大體經歷如此。2009年對我最大的關鍵字或許就是“改變”,這一年我訂婚了,在這一點上,改變了我的準非單身狀態;在這一年,我實習了,而且大量的時間都在于此,改變了我僅僅是學生的狀態;在這一年,我畢業了,我離開了生活學習四年的中國石油大學,離開了讓我畢生難忘的日子;在這一年,我來北京了,從對北京的一無所知,到開始的彷徨,然后漸漸熟悉和適應;在這一年,我的經濟漸漸獨立,盡管每個月只有不到1000的收入,但能滿足的我的基本需求;在這一年,我買了筆記本,雖然對其他人來說,這不是一件特別的事,對我來說,因采用了分期付款,而用接下來一年中近半個月的工資來還,但我不覺得后悔,在這個過程中,我的經濟觀念和理財觀念開始漸漸改變;在這一年,工作成了我的核心,工作教會我很多東西,在與人交流、在工作態度、在技術上,都有一定的提高。

         回憶2009年,收獲頗多,也失去不少。但日子總是向前的,有得必有失。希望在以后的2009年,自己能夠漸漸提高自己的能力。無論是在生活上,在工作上,還是在心理上。

     

        2009年10大大事:

           與老婆訂婚:

           2009年,

    posted @ 2009-12-31 12:55 追求無止境 閱讀(207) | 評論 (0)編輯 收藏

    Spring web MVC 框架學習筆記 之 ViewResolver技術

    上次的文章中介紹了ModelAndView對象中的view對象,可以使用字符串來讓Spring框架進行解析獲得適合的視圖。而解析View的就是ViewResolver技術。

    ViewResolver的定義如下:

    public interface ViewResolver {
    View resolveViewName(String viewName, Locale locale) throws Exception;
    }
     
    在[spring-dispatcher-name]-servlet.xml中,可以定義viewResolver:

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

    來讓DispacherServlet進行加載默認的viewResolver,如果沒有設置viewResolver,spring使用InternalResourceViewResolver進行解析。

    Spring實現ViewResolver的非抽象類且我們經常使用的viewResolver有以下四種:

    InternalResourceViewResolver 將邏輯視圖名字解析為一個路徑
    BeanNameViewResolver 將邏輯視圖名字解析為bean的Name屬性,從而根據name屬性,找定義View的bean
    ResourceBundleResolver 和BeanNameViewResolver一樣,只不過定義的view-bean都在一個properties文件中,用這個類進行加載這個properties文件
    XmlViewResolver 和ResourceBundleResolver一樣,只不過定義的view-bean在一個xml文件中,用這個類來加載xml文件

     

    使用多視圖解析器:

    我們不想只使用一種視圖解析器的話,可以在[spring-dispatcher-name]-servlet.xml定義多個viewResolver:

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

    <bean id=”beanNameViewResolver” class=”...BeanNameViewResolver”>
    <property name="order" value="1"></property>
    </bean>

    <bean id=”beanNameViewResolver” class=”...XmlViewResolver”>
    <property name="order" value="0"></property>
    </bean>

    DispatcherServlet會加載所有的viewResolver到一個list中,并按照優先級進行解析。注意order中的值越小,優先級越高。而id為viewResolver

    的viewResolver的優先級是最低的。

    posted @ 2009-11-27 12:11 追求無止境 閱讀(6879) | 評論 (1)編輯 收藏

    Spring MVC框架學習筆記 之 View技術

    以前,我們詳細介紹了Spring的Controller技術。Spring的面向接口編程,使Controller的實現多種多樣。View技術也一樣。今天的分析先從在Controller中的ModelAndView開始。

    public class ModelAndView {     
      private Object view; //View實例或者view的字符串    
    /** Model Map */  
      private ModelMap model; //model
     /* * Convenient constructor when there is no model data to expose.     * Can also be used in conjunction with <code>addObject</code>.    
     * @param view View object to render   
      * @see #addObject     */  
     public ModelAndView(View view) {        
        this.view = view;    
    }
    public ModelAndView(String viewName){ 
       this.view = viewName;
    }

     
    可以看到view實例可以指向一個View對象或者字符串。現在先看看View接口:
    public interface View { 
    
        /**
         * Return the content type of the view, if predetermined.
         * <p>Can be used to check the content type upfront,
         * before the actual rendering process.
         * @return the content type String (optionally including a character set),
         * or <code>null</code> if not predetermined.
         */
        String getContentType(); 
    
        /**
         * 繪制視圖
         * 繪制視圖的第一步是準備請求: 如果是JSP的視圖技術
         * 首先會把model設為request的屬性。
         * 第二步則是真正的繪制視圖
         * @param model Map with name Strings as keys and corresponding model
         * objects as values (Map can also be <code>null</code> in case of empty model)
         * @param request current HTTP request
         * @param response HTTP response we are building
         * @throws Exception if rendering failed
         */
        void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception; 
    
    }
    在這之后,我們再來看看View的實現繼承類圖,可以看到Spring支持多種類型視圖:

    org.springframework.web.servlet.view.AbstractView (implements org.springframework.beans.factory.BeanNameAware, org.springframework.web.servlet.View)

    • org.springframework.web.servlet.view.document.AbstractExcelView
    • org.springframework.web.servlet.view.document.AbstractJExcelView
    • org.springframework.web.servlet.view.document.AbstractPdfView
    • org.springframework.web.servlet.view.AbstractUrlBasedView (implements org.springframework.beans.factory.InitializingBean)
      • org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsView
        • org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsSingleFormatView
          • org.springframework.web.servlet.view.jasperreports.ConfigurableJasperReportsView
          • org.springframework.web.servlet.view.jasperreports.JasperReportsCsvView
          • org.springframework.web.servlet.view.jasperreports.JasperReportsHtmlView
          • org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
          • org.springframework.web.servlet.view.jasperreports.JasperReportsXlsView
        • org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView
      • org.springframework.web.servlet.view.document.AbstractPdfStamperView
      • org.springframework.web.servlet.view.AbstractTemplateView
        • org.springframework.web.servlet.view.freemarker.FreeMarkerView
        • org.springframework.web.servlet.view.velocity.VelocityView
          • org.springframework.web.servlet.view.velocity.VelocityToolboxView
            • org.springframework.web.servlet.view.velocity.VelocityLayoutView
      • org.springframework.web.servlet.view.InternalResourceView
        • org.springframework.web.servlet.view.JstlView
        • org.springframework.web.servlet.view.tiles.TilesView
          • org.springframework.web.servlet.view.tiles.TilesJstlView
      • org.springframework.web.servlet.view.RedirectView
      • org.springframework.web.servlet.view.tiles2.TilesView
      • org.springframework.web.servlet.view.xslt.XsltView
    • org.springframework.web.servlet.view.xslt.AbstractXsltView
     
    和Controller一樣,View的第一個實現也是AbstractView。所以先讓我們看看AbstractView對render函數的實現:

     

    public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
    if (logger.isTraceEnabled()) {
    logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
    " and static attributes " + this.staticAttributes);
    }

    // Consolidate static and dynamic model attributes.
    Map mergedModel = new HashMap(this.staticAttributes.size() + (model != null ? model.size() : 0));
    mergedModel.putAll(this.staticAttributes);
    if (model != null) {
    mergedModel.putAll(model);
    }

    // Expose RequestContext?
    if (this.requestContextAttribute != null) {
    mergedModel.put(this.requestContextAttribute, createRequestContext(request, mergedModel));
    }

    prepareResponse(request, response);
    renderMergedOutputModel(mergedModel, request, response);
    }

    第一步,將靜態屬性和model的屬性都添加到mergedModel里面。如果需要請求上下文,則將請求上下文添加到model中。

    靜態屬性是繼承AbstractView進行設置的屬性。而請求上下文如果設置的名字就會創建一個request上下文。在requestContext中定義了一些包括本地化和主題的處理工具。

    第二步,對響應進行預處理。最后調用子類需要實現的函數renderMergedOutputModel。

    對PDF和EXCEL格式我們暫且不管,且Spring支持多種視圖技術,這里我們主要關注JSTL技術,

    接著我們來看AbstractUrlBasedView 類。在AbstractUrlBasedView 只定義了一個url屬性。別的沒有什么特殊處理。

    接著繼承AbstractUrlBasedView 的是InternalResourceView。他對renderMergedOutputModel進行實現,實現如下:

    /**
    * Render the internal resource given the specified model.
    * This includes setting the model as request attributes.
    */
    protected void renderMergedOutputModel(
    Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {

    // 獲取要暴露的request,一般都是傳入的參數request
    HttpServletRequest requestToExpose = getRequestToExpose(request);

    // 將model的數據添加到request屬性中
            exposeModelAsRequestAttributes(model, requestToExpose);

    // 設置helper,如果存在的話
    exposeHelpers(requestToExpose);

    // 對繪制進行預處理,從而獲得到要分發的url
    String dispatcherPath = prepareForRendering(requestToExpose, response);

    // 獲取請求分發對象
    RequestDispatcher rd = requestToExpose.getRequestDispatcher(dispatcherPath);
    if (rd == null) {
    throw new ServletException(
    "Could not get RequestDispatcher for [" + getUrl() + "]: check that this file exists within your WAR");
    }

    // 決定使用RequestDispatcher的include方法還是forward方法
    if (useInclude(requestToExpose, response)) {
    response.setContentType(getContentType());
    if (logger.isDebugEnabled()) {
    logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
    }
    rd.include(requestToExpose, response);
    }

    else {
    // Note: The forwarded resource is supposed to determine the content type itself.
    exposeForwardRequestAttributes(requestToExpose);
    if (logger.isDebugEnabled()) {
    logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
    }
    rd.forward(requestToExpose, response);
    }
    }
    可以看到InternalResourceView對請求進行了轉發。轉發到url上。最后我們看看JSTLView的實現:

     
    public class JstlView extends InternalResourceView {
    
        private MessageSource messageSource;
    
        public JstlView() {
        }
    
        
        public JstlView(String url) {
            super(url);
        }
    
        public JstlView(String url, MessageSource messageSource) {
            this(url);
            this.messageSource = messageSource;
        }
    
        protected void initServletContext(ServletContext servletContext) {
            if (this.messageSource != null) {
                this.messageSource = JstlUtils.getJstlAwareMessageSource(servletContext, this.messageSource);
            }
            super.initServletContext(servletContext);
        }
    
        protected void exposeHelpers(HttpServletRequest request) throws Exception {
            if (this.messageSource != null) {
                JstlUtils.exposeLocalizationContext(request, this.messageSource);
            }
            else {
                JstlUtils.exposeLocalizationContext(new RequestContext(request, getServletContext()));
            }
        }
    
    }

     

    在InternalResourceView  中,基本上所有的處理都差不多了。在JSTLView對兩個方法進行了覆蓋。第一個initServletContext,主要初始化了MessageResource

    第二個exposeHelpers將messageSource放在了request里面。

    這樣view的解析就結束了。接下來容器對jsp進行解析,并進行tag等的處理。然后將生成的頁面返回給客戶端。

    posted @ 2009-11-26 13:25 追求無止境 閱讀(8207) | 評論 (2)編輯 收藏

    SpringMVC web框架學習 Controller 分析

    org.springframework.web.servlet.mvc.AbstractController (implements org.springframework.web.servlet.mvc.Controller)

    Spring MVC框架中的Controller對請求進行處理:所有的Controller都實現接口Controller:

    public interface Controller { 
    
        /**
         * Process the request and return a ModelAndView object which the DispatcherServlet
         * will render. A <code>null</code> return value is not an error: It indicates that
         * this object completed request processing itself, thus there is no ModelAndView
         * to render.
         * @param request current HTTP request
         * @param response current HTTP response
         * @return a ModelAndView to render, or <code>null</code> if handled directly
         * @throws Exception in case of errors
         */
        ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; 
    
    }
    上面的doc表明Controller返回的modelandview可以使空,表明請求都是該函數中處理完成了,不需要modeland來進行渲染。
     
    在繼續之前先介紹一個有用的工具類:WebUtils。用這個可以簡化session,request的處理。具體的內容可以參考文檔。
     
    Controller的第一個實現是:AbstractController。他是一個Abstract類,除了實現了Controller接口,它還繼承了WebContentGenerator。
     
    WebContentGenerator的作用是什么?參考文檔可以發現,該類主要對Cache和Session進行管理。
     
    cacheSeconds 指定內容緩存的時間,默認為1
    requireSession 是否需要會話,默認支持
    supportedMethods 支持的方法,默認是GET\post\Head
    useCacheControlHeader 指定是否使用http1.1的cache控制頭信息,默認使用
    useCacheControlNoStore 指定是否設置http1.1的cache控制頭信息為no-store。默認使用
    useExpiresHeader 指定是否使用http1.0的expire頭信息。默認使用
    用戶可以對這些參數進行測試,cache和expire信息涉及到了http協議信息,更多信息可以參考http協議文檔。這里不再說明。
     
    再看AbstractController的代碼:
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
    throws Exception {

    // Delegate to WebContentGenerator for checking and preparing.
    checkAndPrepare(request, response, this instanceof LastModified);

    // Execute handleRequestInternal in synchronized block if required.
    if (this.synchronizeOnSession) {
    HttpSession session = request.getSession(false);
    if (session != null) {
    Object mutex = WebUtils.getSessionMutex(session);
    synchronized (mutex) {
    return handleRequestInternal(request, response);
    }
    }
    }
    return handleRequestInternal(request, response);
    }
    checkandPrepare的目的就是使用用于進行的配置來對request進行預處理和準備。
    他會檢查支持的方法,和會話,然后應用cache設置。
    如果需要session同步,就進行同步處理。session同步應用于有session的情況下。如果沒有session,session同步是沒有用的。
    AbstractController會調用handleRequestInternal方法進行處理,繼承AbstractController的類需要實現該方法。
    下面我們再看看AbstractUrlViewController 的代碼實現和文檔,先看handleRequestInternal的實現:

     
    /**
    * Retrieves the URL path to use for lookup and delegates to
    * {@link #getViewNameForRequest}.
    */
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
    String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    String viewName = getViewNameForRequest(request);
    if (logger.isDebugEnabled()) {
    logger.debug("Returning view name '" + viewName + "' for lookup path [" + lookupPath + "]");
    }
    return new ModelAndView(viewName);
    }

    可以看到,它使用了getViewNameForRequest獲取需要的viewName。而getViewNameForRequest是一個抽象函數,需要子類實現。lookupPath就是我們請求的URL中的一部分。如我們使用UrlFilenameViewController來進行如下的配置:
    <bean name="/index.do" class="org.springframework.web.servlet.mvc.UrlFilenameViewController"></bean>、
    09-11-25 11:56:06 - DEBUG [http-8200-1] - Returning view name 'index' for lookup path [/index.do]
    該Controller對/index.do解析成index,然后再通過viewResolver對index進行擴展為/jsp/index.jsp。從而找到該頁面。
    可以看到這個類的主要是用于對url進行解析,然后轉到合適的頁面上,而在轉到這個頁面之前不需要進行特別的處理。
    明白了該類的作用自然也就知道了UrlFilenameViewController的作用。這里不再進行詳細分析。
     
     

    posted @ 2009-11-26 09:35 追求無止境 閱讀(4163) | 評論 (0)編輯 收藏

    Spring MVC 框架學習之AbstractFormController以及AbstractFormControll

    在看完BaseCommandController和AbstractCommandController之后,我們再看BaseCommandController的另一個實現AbstractFormController,以及AbstractFormController的具體實現SimpleFormController。

    先看看AbstractFormController對handleRequestInternal的實現:

    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
    throws Exception {
    // Form submission or new form to show?
    if (isFormSubmission(request)) {
    // Fetch form object from HTTP session, bind, validate, process submission.
    try {
    Object command = getCommand(request);
    ServletRequestDataBinder binder = bindAndValidate(request, command);
    BindException errors = new BindException(binder.getBindingResult());
    return processFormSubmission(request, response, command, errors);
    }
    catch (HttpSessionRequiredException ex) {
    // Cannot submit a session form if no form object is in the session.
    if (logger.isDebugEnabled()) {
    logger.debug("Invalid submit detected: " + ex.getMessage());
    }
    return handleInvalidSubmit(request, response);
    }
    }
    else {
    // New form to show: render form view.
    return showNewForm(request, response);
    }
    }
    這個方法,首先判斷是不是Form提交,判斷方法是:
    protected boolean isFormSubmission(HttpServletRequest request) {
    return "POST".equals(request.getMethod());
    }
    如果是form提交的話,系統首先創建一個Command,然后對數據進行綁定和驗證,之后調用processFormSubmission方法。showNewForm則調用showForm。
    在AbstractFormController中里面有兩個抽象方法:

    protected abstract ModelAndView processFormSubmission(
    HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)
    throws Exception;
    protected abstract ModelAndView showForm(
    HttpServletRequest request, HttpServletResponse response, BindException errors)
    throws Exception;



     

     

    好了,看完AbstractFormController之后,再看看SimpleFormController是如何實現:

    protected ModelAndView processFormSubmission(
    HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)
    throws Exception {

    if (errors.hasErrors()) {
    if (logger.isDebugEnabled()) {
    logger.debug("Data binding errors: " + errors.getErrorCount());
    }
    return showForm(request, response, errors);
    }
    else if (isFormChangeRequest(request, command)) {
    logger.debug("Detected form change request -> routing request to onFormChange");
    onFormChange(request, response, command, errors);
    return showForm(request, response, errors);
    }
    else {
    logger.debug("No errors -> processing submit");
    return onSubmit(request, response, command, errors);
    }
    }
    在上面的方法中,如果有錯誤,調用showForm,來顯示form。沒有錯誤的話,則調用onSubmit方法。
    protected final ModelAndView showForm(
    HttpServletRequest request, BindException errors, String viewName, Map controlModel)
    throws Exception {

    // In session form mode, re-expose form object as HTTP session attribute.
    // Re-binding is necessary for proper state handling in a cluster,
    // to notify other nodes of changes in the form object.
    if (isSessionForm()) {
    String formAttrName = getFormSessionAttributeName(request);
    if (logger.isDebugEnabled()) {
    logger.debug("Setting form session attribute [" + formAttrName + "] to: " + errors.getTarget());
    }
    request.getSession().setAttribute(formAttrName, errors.getTarget());
    }

    // Fetch errors model as starting point, containing form object under
    // "commandName", and corresponding Errors instance under internal key.
    Map model = errors.getModel();

    // Merge reference data into model, if any.
    Map referenceData = referenceData(request, errors.getTarget(), errors);
    if (referenceData != null) {
    model.putAll(referenceData);
    }

    // Merge control attributes into model, if any.
    if (controlModel != null) {
    model.putAll(controlModel);
    }

    // Trigger rendering of the specified view, using the final model.
    return new ModelAndView(viewName, model);
    }
    在showForm中,設置屬性,放在model中,然后在viewName進行設置。
    FormController就是上面的過程。具體的執行過程和詳細信息會在以后的博客中具體介紹。

    posted @ 2009-11-25 17:31 追求無止境 閱讀(2447) | 評論 (0)編輯 收藏

    Spring MVC 框架學習筆記之BaseCommandController和AbstractCommandController

     

    Spring的BaseCommandController繼承自AbstractController。在看BaseCommandController之前先看他的繼承類AbstractCommandController是如何實現

    AbstractController的handleInternalRequest方法的:

    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
    throws Exception {
    Object command = getCommand(request);
    ServletRequestDataBinder binder = bindAndValidate(request, command);
    BindException errors = new BindException(binder.getBindingResult());
    return handle(request, response, command, errors);
    }
    

    getCommand就是BaseCommandController中的方法。

    protected Object getCommand(HttpServletRequest request) throws Exception {
    return createCommand();
    }
    protected final Object createCommand() throws Exception {
    if (this.commandClass == null) {
    throw new IllegalStateException("Cannot create command without commandClass being set - " +
    "either set commandClass or (in a form controller) override formBackingObject");
    }
    if (logger.isDebugEnabled()) {
    logger.debug("Creating new command of class [" + this.commandClass.getName() + "]");
    }
    return BeanUtils.instantiateClass(this.commandClass);
    }
    

    createCommand創建了一個CommandClass的對象。

    然后再看bindAndValidate方法:

    protected final ServletRequestDataBinder bindAndValidate(HttpServletRequest request, Object command)
    throws Exception {
    ServletRequestDataBinder binder = createBinder(request, command);
    BindException errors = new BindException(binder.getBindingResult());
    if (!suppressBinding(request)) {
    binder.bind(request);
    onBind(request, command, errors);
    if (this.validators != null && isValidateOnBinding() && !suppressValidation(request, command, errors)) {
    for (int i = 0; i < this.validators.length; i++) {
    ValidationUtils.invokeValidator(this.validators[i], command, errors);
    }
    }
    onBindAndValidate(request, command, errors);
    }
    return binder;
    }
    

    這個方法首先創建了 DataBinder對象,然后,獲取創建綁定對象時發生的錯誤。報錯在errors。接下來綁定對象,調用onBind處理綁定事件;接下來應用Validator。然后調用onBindAndValidate來處理綁定和驗證事件。最后返回binder。

    處理完之后調用handle方法進行處理。

    綜上所述,AbstractCommandController具有兩個功能:

    1、將請求參數轉換為Command對象。在該Controller中,我們設置一個object對象。然后BaseCommandController將請求的參數進行轉換。如果請求參數有value值,就會調用object的的setValue對象來設置對象里的值。如果請求參數中有address.city.就會調用object中getAddress().setCity()方法來賦值。這個object可以是任意的object,唯一的要求就是這個object類沒有參數。

    2、對數據進行驗證。在轉換和驗證時發生錯誤時,需要在handle(request, response, command, errors)中進行處理。

    posted @ 2009-11-25 16:25 追求無止境 閱讀(5382) | 評論 (0)編輯 收藏

    Spring的MVC web框架學習筆記

    1、Spring web 框架的核心:DispatcherServlet

    DispatcherServlet 用于接收請求。是使用Spring框架的入口。在web.xml中,需要配置該servlet。在配置該Servlet的時候url-pattern你可以使用你自己想使用的形式,如*.aspx,*.do,*.htm,*.action,用以混淆客戶端對服務器架構的認識。

    另外,該Servlet在容器中還會加載一個APPlicationContext的xml文件。默認加載的是[servlet-name]-servlet.xml。例如,你在web.xml中配置的servlet如下:

    <web-app>
    <servlet>
    <servlet-name>example</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>example</servlet-name>
    <url-pattern>*.form</url-pattern>
    </servlet-mapping>
    </web-app>
    
    該Servlet就會在服務器啟動時,加載example-servlet.xml。當然,你也可以自己來指定加載文件。
    要看看DispatcherServlet真面目,打開源文件,發現定義了很多BeanName的常量,如本地化解析器beanname,主題解析器beanname,視圖解析器beanname,上傳文件解析的multipart解析器beanname。
    等:
    public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
    public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";
    public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
    public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";
    public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter";
    public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver";
    public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator";
    public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver";
    
    這個類怎么使用這些bean呢?以上面的exexample-servlet.xml為例,我們定義的名字為example的DispatcherServlet使用example-servlet.xml的配置。在example-servlet.xml里,我們可以配置名字上面的beanName的bean,來讓servlet加載這些bean。
    這下明白了,servlet.xml該怎么配置,該配置什么了。
    好了,看完了最重要的servlet的配置問題,我們再看下一個重要的接口:Controller。至于上面servlet要使用的什么什么解析器啦,我們稍后在分析。
     
    2、Controller
    我們的請求提交到DispacherServlet后,會轉給Controller。怎么找Controller?通過使用handlerMapping。如果沒有設置handlerMapping,spring使用默認的BeanNameUrlHandlerMapping來找Controller。
    BeanNameUrlHandlerMapping?顧名思義,就是通過bean的name屬性來映射controller。bean的name請求是一個url,如果請求的是logout.do,在example-servlet.xml中定義一個名字(name)為login.do的Controller.

    <bean name="/logout.do" class="com.jy.bookshop.web.spring.LogoutController">
        </bean>

    再插一句話,在handlerMapping中,我們可以使用請求攔截器來對請求進行攔截處理。該攔截器怎么使用這里暫且不表,有機會再討論。

    ok,現在我們創建一個LogoutController來讓他處理請求,讓他實現Controller吧:

    public class LogOutController implements Controller {
        public ModelAndView handleRequest(HttpServletRequest req,
                HttpServletResponse res) throws Exception {
              …
            return new ModelAndView(new RedirectView("login.do"));
        }
    }
    看看這個Controller接口的定義,發現這個接口只定義了一個handleRequest方法。在這個方法中,返回一個ModelAndView。
    先說ModelAndView。我們知道MVC,那么ModelAndView就是 MV了。Controller就是C。這樣MVC全了。呵呵。
    繼續說ModelAndView,要了解他的結構,那自然要看看他的源代碼了:
    /** View instance or view name String */
    private Object view; 
    
    /** Model Map */
    private ModelMap model;
    

       

        只關注我們關注的,里面包含了一個View對象和model對象。model對象是一個Map,這里不再說了。關鍵看看view,奇怪,怎么是一個Object,太抽象了。再繼續看源代碼的話,會更加明白:

     

    public ModelAndView(String viewName, String modelName, Object modelObject) {
            this.view = viewName;
            addObject(modelName, modelObject);
        }
    public void setViewName(String viewName) {
            this.view = viewName;
        }

    原來這個view可以指向一個View對象,也可以指向String對象啊。View一個接口,如果看doc的話,他的實現類有AbstractExcelView, AbstractJasperReportsSingleFormatView, AbstractJasperReportsView, AbstractJExcelView, AbstractPdfStamperView, AbstractPdfView,AbstractTemplateView, AbstractUrlBasedView, AbstractView, AbstractXsltView, ConfigurableJasperReportsView, FreeMarkerView, InternalResourceView,JasperReportsCsvView, JasperReportsHtmlView, JasperReportsMultiFormatView, JasperReportsPdfView, JasperReportsXlsView, JstlView, RedirectView,TilesJstlView, TilesView, TilesView, VelocityLayoutView, VelocityToolboxView, VelocityView, XsltView(誠實的說,這些View是拷doc的)。

    現在可以知道,我們的Controller返回一個View和Model,來讓Spring框架來創建一個回應。

    現在奇怪的還有一點,我吧view設置為字符串,Spring框架怎么處理?在ModelAndView中,如果view是一個字符串,則會將這個值交給DispatcherServlet的viewResovler來處理。記得上面提到的viewResovler了嗎?呵呵,派上用場了。

    view的問題解決了,然后再說model吧。在ModelAndView添加了一些對象,Spring是怎么處理的呢?總應該把這些對象給弄到request對象里,讓jsp頁面來使用吧。讓View使用?那么看看View接口吧:

    public interface View {
    
        String getContentType();
    
        void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception;
    
    }
    render函數需要帶一個model變量。再找找view的實現類,看看是怎么工作的。不過view有那么多,對于一些像什么pdf啦,excel了他們都不需要在request中添加這個model。
    最終呢,我們在jstlView的父類InternalResourceView中的renderMergedOutputModel函數發現他把model放在了request里面了。
     
    OK,現在我們明白了,controller返回的modelandview交給Servlet進行處理,來生成一個頁面。
    最簡單的Controller介紹完畢。現在看看Spring提供的一些controller的實現,Spring提供了很多controller的實現,繼承的結構如下:

     

    org.springframework.web.servlet.mvc.AbstractController (implements org.springframework.web.servlet.mvc.Controller)

    • org.springframework.web.servlet.mvc.AbstractUrlViewController
      • org.springframework.web.servlet.mvc.UrlFilenameViewController
    • org.springframework.web.servlet.mvc.BaseCommandController
      • org.springframework.web.servlet.mvc.AbstractCommandController
      • org.springframework.web.servlet.mvc.AbstractFormController
        • org.springframework.web.servlet.mvc.AbstractWizardFormController
        • org.springframework.web.servlet.mvc.SimpleFormController
          • org.springframework.web.servlet.mvc.CancellableFormController
    • org.springframework.web.servlet.mvc.ParameterizableViewController
    • org.springframework.web.servlet.mvc.ServletForwardingController (implements org.springframework.beans.factory.BeanNameAware)
    • org.springframework.web.servlet.mvc.ServletWrappingController (implements org.springframework.beans.factory.BeanNameAware, org.springframework.beans.factory.DisposableBean, org.springframework.beans.factory.InitializingBean)
      AbstractController是Controller的第一個實現。其他的Controller都是繼承這個Controller的。我們先看比較重要的Controller。
      先說UrlFilenameViewController。不如我們自己來部署一個吧。
      在example-servlet.xml中增加如下的配置:

      <bean name="/error.do"  class="org.springframework.web.servlet.mvc.UrlFilenameViewController">
          </bean>

      OK,當/error.do的請求上來后,urlFileNameViewController將他變成/error。然后返回個View,這個view的name就是/error,然后使用viewresolver來進行解析,可以解析成/jsp/error.jsp。
      另外還有比較重要的controller是baseCommandController,將請求參數轉換為一個對象,并對對象參數合法性進行驗證。另外,SimpleFormController可以對表單進行處理。
      關于各個controller的分析。未完待續。。

       

       

       

      posted @ 2009-11-25 11:09 追求無止境 閱讀(3714) | 評論 (2)編輯 收藏

      主站蜘蛛池模板: 永久免费AV无码国产网站| 67pao强力打造高清免费| 成年人在线免费看视频| 亚洲另类自拍丝袜第1页| 久久精品国产免费观看| 亚洲精品亚洲人成在线观看麻豆| 久久免费国产视频| 国产亚洲精AA在线观看SEE| 久久久WWW成人免费精品| 亚洲欧洲日产国码无码网站| 国产精品成人免费观看| 国产亚洲色婷婷久久99精品| 久久大香伊焦在人线免费| 色噜噜综合亚洲av中文无码| 99re视频精品全部免费| 亚洲手机中文字幕| 免费在线看v网址| 亚洲综合av一区二区三区| 国产jizzjizz免费视频| 久久国产精品免费一区二区三区| 亚洲精品国产精品乱码不卡√| 免费一级不卡毛片| 亚洲美女aⅴ久久久91| 大地资源二在线观看免费高清| 一本天堂ⅴ无码亚洲道久久| 国产精品va无码免费麻豆| 一级中文字幕乱码免费| 亚洲国产综合专区电影在线| 在线观看视频免费完整版| 阿v免费在线观看| 亚洲国产精品久久久天堂| 成年人网站免费视频| 亚洲国产成人无码AV在线| 亚洲高清国产拍精品青青草原 | 亚洲综合免费视频| 亚洲女人初试黑人巨高清| 成年男女免费视频网站| 亚洲色大成WWW亚洲女子| 在线日韩av永久免费观看| 特级毛片A级毛片100免费播放| 久久久久亚洲av毛片大|