1. 程式人生 > >CMS小專案04---SpringMVC檢視_資料及檢視對映方式

CMS小專案04---SpringMVC檢視_資料及檢視對映方式

臨時插入一個小插曲,說說SpringMVC的一些小應用。
對於框架型別的東西,不敢談的太深,容易把自己陷進去,這裡就只總結一些應用及表面的東西。

往實際點說,我認為SpringMVC最好用的地方就是檢視解析和註解。至於更深層的,自認為還不能在部落格上歸納。

這兩個特點幾乎讓我們擺脫了繁重的配置以及底層功能的實現讓我們可以更加關注業務邏輯。

1.MVC架構

說起檢視,那麼必須的瞭解到MVC架構。
這裡寫圖片描述

這裡寫圖片描述

這是網上隨處可見的圖,根據這個圖簡單的梳理一下,自認為沒有網上的大神理解透徹,所以不深入。

用我的視角,MVC有三個部分

名稱 對應 功能
控制器 controller或者action 接收使用者請求,委託給模型進行處理(狀態改變),處理完畢後把返回的模型資料返回給檢視,由檢視負責展示。
模型 model和service 資料模型,提供要展示的資料及執行業務邏輯
檢視 JSP或者其他的展示 負責進行模型的展示,一般就是我們見到的使用者介面,客戶想看到的東西。

所以,controller會告訴框架,我們要展示的檢視是什麼,而同時,會將模型的資料傳遞給檢視,控制器就是一個排程員。

而我們主要集中在SpringMVC對檢視的處理。

最常見的應該是這一段程式碼:

    <!-- 定義跳轉的檔案的前後綴 ,檢視模式配置-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 這裡的配置我的理解是自動給後面action的方法return的字串加上字首和字尾,變成一個 可用的url地址 --> <property name="prefix" value="/WEB-INF/static/cms/" /> <property name="suffix" value=".jsp" />
</bean>

一開始對於SpringMVC的理解就只有這一段程式碼,而在專案中,我一開始也只記住了這一段程式碼。
簡單點說,就是講controller設定的檢視名稱,對映到正確的檢視上面。

這一篇只針對檢視,那麼只需要理清楚兩個地方。

  • 資料對映
  • 檢視指定

2.資料對映與檢視指定

資料對映說明白點,就是模型裡面的資料,我們怎麼給檢視。檢視指定就是說對映到哪個檢視。都很簡單,沒必要分開講。
通常我們常用四個物件來完成這個過程:

  • ModelAndView
  • Model
  • ModelMap
  • Map

    註解方式:

  • @SessionAttribute(這個就不舉例了,感覺用的也不多)
  • @ModelAttribute

這些我在一位博主的博文裡面看到了不錯的梳理
連結

我只是貼上一些實際的用法:

package com.cms.controller;

import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.mysql.fabric.Response;


/**
*@author:gang
*@version:
**/
@Controller
@RequestMapping("/test")
public class MVCTest {

    private Map<String, String> map;
    private List<String> list;
    private String [] array ={"1","2","3"};
    private String name = new String("110");

    @RequestMapping("/modelandview")
    public ModelAndView modelAndViewTest(HttpServletRequest request){
        ModelAndView modelAndView = new ModelAndView();
        //設定對比引數
        //記住,要初始化,不然會包NullpointException
        map = new HashMap<String, String>();
        HashMap<String, String> map2 = new HashMap<String, String>();
        map2.put("mapkey1", "001");
        map2.put("mapkey3", "002");
        map.put("mapkey", "mapvalue1_001");
        map.put("mapkey1", "mapvalue1_002");
        list = new LinkedList<String>();
        list.add("list1_1");
        list.add("list1_2");
        array[0]="1_1";
        name="modelandview";

        //新增資料
        modelAndView.addObject(map);
        modelAndView.addObject(map2);
        modelAndView.addObject("map", map); 
        modelAndView.addObject("list", list);   
        modelAndView.addObject("array", array);
        modelAndView.addObject("name", name);
        HttpSession session = request.getSession();
        session.setAttribute("name2", name2);
        System.out.println(modelAndView.isEmpty());
        modelAndView.setViewName("mvctest");
        System.out.println(modelAndView.getViewName());

        //返回檢視
        return modelAndView;
    }
//  
    @RequestMapping("/modelmap")
    public String modelMap(ModelMap modelMap){
        //設定對比引數
        map.put("mapkey", "mapvalue2_001");
        map.put("mapkey1", "mapvalue2_002");
        list.add("list2_1");
        list.add("list2_2");
        array[0]="2_1";
        name="modelMAP";
        //新增資料模型
        modelMap.put("map", map);
        modelMap.put("name", name);
        modelMap.addAttribute("list", list);
        modelMap.put("array", array);
        //對映檢視名
        return "mvctest";
    } 
//  
    @RequestMapping("/model")
    public String modelTest(Model model){
        //設定對比引數
        map.put("mapkey", "mapvalue3_001");
        map.put("mapkey1", "mapvalue3_002");
        list.add("list3_1");
        list.add("list3_2");
        array[0]="3_1";
        name="model";
        //新增資料模型
        model.addAttribute("name", name);
        model.addAttribute("list", list);
        model.addAttribute("array",array);
        model.addAttribute(map);
        //對映檢視名
        return "mvctest";
    }

    @RequestMapping("/map")
    public String mapTest(Map<String, Object> map){
        map.put("mapkey", "mapvalue3_001");
        map.put("mapkey1", "mapvalue3_002");
        list.add("list3_1");
        list.add("list3_2");
        name="map";
        //新增資料模型
        map.put("name", name);
        map.put("map", map);
        map.put("list", list);
        map.put("array", Arrays.asList("map4_1", "map4_2", "map4_3"));
        //對映檢視名
        return "mvctest";
    }
    //註解的使用
    @ModelAttribute(value="modelAttribute")
    public String modelAttribute(){
        return "modelAttribute success";
    }

    @ModelAttribute
    public void modelAttribute(ModelMap model){
        model.addAttribute("modelAttribute02", "modelAttribute02");
    }

}

以及對應的結果顯示
這裡寫圖片描述

這裡寫圖片描述
這裡寫圖片描述

以及註解的
這裡寫圖片描述

3.實現方式探討

這一篇我們主要是為了去探討更深層的一點,起因是這一段程式碼:

//沒有名字,他是怎麼對映的呢
modelAndView.addObject(map);

所以,我們用Debug一步步跟蹤原始碼來看看
注意,debug時tomcat的開啟會明顯變慢,需要將Tomcat的初始化時間調節一下,不然會報錯
這裡寫圖片描述
這裡寫圖片描述

下面正式開始:

//看到這一個方法,是不是很神奇,居然是將資料儲存在modelmap中,
//也側面解釋了modelAndView.addAllObjects(modelMap)方法的執行方式
public ModelAndView addObject(Object attributeValue) {
        getModelMap().addAttribute(attributeValue);
        return this;
}

//包括另外一個addObject
public ModelAndView addObject(String attributeName, Object attributeValue) {
        getModelMap().addAttribute(attributeName, attributeValue);
        return this;
        }

繼續:
那麼接著看,後面是怎麼執行的呢
也是分成有name和無name兩個方面

//無name
public ModelMap addAttribute(Object attributeValue) {
        Assert.notNull(attributeValue, "Model object must not be null");
        //為空的集合就返回這個ModelMap
        if (attributeValue instanceof Collection && ((Collection<?>) attributeValue).isEmpty()) {
                return this;
        }
        return addAttribute(Conventions.getVariableName(attributeValue), attributeValue);
}
//有name
public ModelMap addAttribute(String attributeName, Object attributeValue) {
        Assert.notNull(attributeName, "Model attribute name must not be null");
        put(attributeName, attributeValue);
        return this;
}

可以發現,
首先用Assert工具類進行判斷,這個工具類我們會在附件中貼上來,Asserts是Spring的斷言工具類,通常用於資料合法性檢查,可以將複雜的if判斷語句進行簡化,例如下面的例子

Assert.notNull(attributeValue, "Model object must not be null");
Assert.notNull(attributeName, "Model attribute name must not be null");

我們繼續,先進行了Assert判斷,在判斷是否為集合,並且判斷是否為空,然後進行了put操作,實際上還是將物件放到了map物件之中
對於有名字的就不多說了,這裡就只分析不帶名字的是怎麼將名字對映到物件上的
可以看到,有一個這樣的語句Conventions.getVariableName(attributeValue),

return addAttribute(Conventions.getVariableName(attributeValue), attributeValue);

很明顯,這是一個起別名的類,看一下具體的原始碼

public static String getVariableName(Object value) {
//判斷資料合法性
    Assert.notNull(value, "Value must not be null");
    //說明一個Class
    Class<?> valueClass;
    boolean pluralize = false;
    //判斷是什麼型別
    if (value.getClass().isArray()) {
        valueClass = value.getClass().getComponentType();
        pluralize = true;
    }
    else if (value instanceof Collection) {
        Collection<?> collection = (Collection<?>) value;
        if (collection.isEmpty()) {
            throw new IllegalArgumentException("Cannot generate variable name for an empty Collection");
        }
        Object valueToCheck = peekAhead(collection);
        //反射,根據值確定這個Class
        valueClass = getClassForValue(valueToCheck);
        pluralize = true;
    }
    else {
        valueClass = getClassForValue(value);
    }
    //根據屬性獲取name
    String name = ClassUtils.getShortNameAsProperty(valueClass);
    return (pluralize ? pluralize(name) : name);
}


    //到了這一步,基本上我們的推測就出來了,這個屬性的名字和型別應該是一樣的,那麼,,,我們debug看看

這裡寫圖片描述

沒錯,是被對映為了型別名
那麼我們試試當有兩個map的時候呢

map2.put("mapkey1", "001");
map2.put("mapkey3", "002");
map.put("mapkey", "mapvalue1_001");
map.put("mapkey1", "mapvalue1_002");
modelAndView.addObject(map);
modelAndView.addObject(map2);

這裡寫圖片描述

並沒有前面的資料。
所以說,hashmap是一個物件,在裡面可以取出所有包含的值,多個map會被後者替換

4.總結

檢視的實際應用基本上就這些了,對於其內部的詳細流程,及資料最終會被放在哪,我下次再詳細的分析。

5.附件:Assert

抽象類,每個方法的具體實現大概都可以猜出來

package org.springframework.util;

import java.util.Collection;
import java.util.Map;

public abstract class Assert {
    public static void isTrue(boolean expression, String message) {
        if (!expression) {
            throw new IllegalArgumentException(message);
        }
    }
    public static void isTrue(boolean expression) {
        isTrue(expression, "[Assertion failed] - this expression must be true");
    }
    public static void isNull(Object object, String message) {
        if (object != null) {
            throw new IllegalArgumentException(message);
        }
    }
    public static void isNull(Object object) {
        isNull(object, "[Assertion failed] - the object argument must be null");
    }
    public static void notNull(Object object, String message) {
        if (object == null) {
            throw new IllegalArgumentException(message);
        }
    }
    public static void notNull(Object object) {
        notNull(object, "[Assertion failed] - this argument is required; it must not be null");
    }
    public static void hasLength(String text, String message) {
        if (!StringUtils.hasLength(text)) {
            throw new IllegalArgumentException(message);
        }
    }
    public static void hasLength(String text) {
        hasLength(text,
                "[Assertion failed] - this String argument must have length; it must not be null or empty");
    }
    public static void hasText(String text, String message) {
        if (!StringUtils.hasText(text)) {
            throw new IllegalArgumentException(message);
        }
    }

    public static void hasText(String text) {
        hasText(text,
                "[Assertion failed] - this String argument must have text; it must not be null, empty, or blank");
    }

    public static void doesNotContain(String textToSearch, String substring, String message) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            throw new IllegalArgumentException(message);
        }
    }

    public static void doesNotContain(String textToSearch, String substring) {
        doesNotContain(textToSearch, substring,
                "[Assertion failed] - this String argument must not contain the substring [" + substring + "]");
    }

    public static void notEmpty(Object[] array, String message) {
        if (ObjectUtils.isEmpty(array)) {
            throw new IllegalArgumentException(message);
        }
    }

    public static void notEmpty(Object[] array) {
        notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element");
    }

    public static void noNullElements(Object[] array, String message) {
        if (array != null) {
            for (Object element : array) {
                if (element == null) {
                    throw new IllegalArgumentException(message);
                }
            }
        }
    }
    public static void noNullElements(Object[] array) {
        noNullElements(array, "[Assertion failed] - this array must not contain any null elements");
    }
    public static void notEmpty(Collection<?> collection, String message) {
        if (CollectionUtils.isEmpty(collection)) {
            throw new IllegalArgumentException(message);
        }
    }
    public static void notEmpty(Collection<?> collection) {
        notEmpty(collection,
                "[Assertion failed] - this collection must not be empty: it must contain at least 1 element");
    }
    public static void notEmpty(Map<?, ?> map, String message) {
        if (CollectionUtils.isEmpty(map)) {
            throw new IllegalArgumentException(message);
        }
    }
    public static void notEmpty(Map<?, ?> map) {
        notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry");
    }
    public static void isInstanceOf(Class<?> clazz, Object obj) {
        isInstanceOf(clazz, obj, "");
    }
    public static void isInstanceOf(Class<?> type, Object obj, String message) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            throw new IllegalArgumentException(
                    (StringUtils.hasLength(message) ? message + " " : "") +
                    "Object of class [" + (obj != null ? obj.getClass().getName() : "null") +
                    "] must be an instance of " + type);
        }
    }
    public static void isAssignable(Class<?> superType, Class<?> subType) {
        isAssignable(superType, subType, "");
    }
    public static void isAssignable(Class<?> superType, Class<?> subType, String message) {
        notNull(superType, "Type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            throw new IllegalArgumentException(message + subType + " is not assignable to " + superType);
        }
    }
    public static void state(boolean expression, String message) {
        if (!expression) {
            throw new IllegalStateException(message);
        }
    }
    public static void state(boolean expression) {
        state(expression, "[Assertion failed] - this state invariant must be true");
    }

}

相關推薦

CMS專案04---SpringMVC檢視_資料檢視對映方式

臨時插入一個小插曲,說說SpringMVC的一些小應用。 對於框架型別的東西,不敢談的太深,容易把自己陷進去,這裡就只總結一些應用及表面的東西。 往實際點說,我認為SpringMVC最好用的地方就是檢視解析和註解。至於更深層的,自認為還不能在部落格上歸納。

CMS專案

資料庫用的是mysql,IDE為idea。 專案目錄 NewsServlet檔案 package com.cmsTest.controller; import com.cmsTest.dao.NewsDao; import com.cms

python專案一:NBA比賽資料分析

該專案來源於實驗樓,我這裡只是記錄下自己做完專案的筆記和總結(實驗樓是py2的程式碼,我則是用的py3)。 專案目的:通過分析之前的比賽資料,得到每個隊伍的狀態的特徵表達,利用機器學習訓練迴歸模型,從而對新的比賽進行預測。 為了掌握並實現這個專案,需瞭解一下幾個問題:

springmvc接收json資料的4種方式

ajax我經常用到,傳的資料是json資料,json資料又有物件,陣列。所有總結下springmvc獲取前端傳來的json資料方式: 1、以RequestParam接收 前端傳來的是json資料不多時:[id:id],可以直接用@RequestParam來獲取值 @Autowired p

SpringMVC返回json資料的三種方式

1、第一種方式是spring2時代的產物,也就是每個json檢視controller配置一個Jsoniew。 如:<bean id="defaultJsonView" class="org.springframework.web.servlet.view.json

控制器向檢視傳遞資料的3種方式

僅供自己學習用: 在ASP.NET MVC中,控制器和檢視之間的資料傳遞包括兩個方向: 將控制器設定的資料傳遞到檢視中,在檢視中顯示資料;將檢視中的資料傳遞到控制器 中,在控制器中讀取、處理資料。 今天先給大家講講控制器向檢視傳遞資料:控制器向檢視傳遞資料ASP.NET

【Spring】SpringMVC返回json資料的三種方式

歡迎關注公眾號: ----------------------------------------------正文---------------------------------------------------- 方式一:使用JSON工具將物件序列化成j

SpringMVC 返回json資料的三種方式

1、第一種方式是spring2時代的產物,也就是每個json檢視controller配置一個Jsoniew。 如:<bean id="defaultJsonView" class="org.springframework.web.servlet.view.json

以58同城為例詳解如何用爬蟲採集二手房房源資料中介聯絡方式

2008年9月4日,英國《自然》雜誌刊登了一個名為“Big Data”的專輯,首次提出大資料概念,該專輯對如何研究PB級容量的大資料流,以及目前正在制訂的、用以最為充分地利用海量資料的最新策略進行了探討。2011、2012年達沃斯世界經濟論壇將大資料作為專題討論的主題之一,釋出了《大資料、大影響:國

詳解如何批量採集58同城二手房資料中介聯絡方式

2008年9月4日,英國《自然》雜誌刊登了一個名為“Big Data”的專輯,首次提出大資料概念,該專輯對如何研究PB級容量的大資料流,以及目前正在制訂的、用以最為充分地利用海量資料的最新策略進行了探討。2011、2012年達沃斯世界經濟論壇將大資料作為專題討論的主題之一,釋出了《大資料、大影響:國際發展新的

CentOS 7檢視系統版本檢視機器位數x86-64 & centOS7下實踐查詢版本/CPU/記憶體/硬碟容量等硬體資訊

http://www.linuxidc.com/Linux/2016-11/137550.htm http://blog.csdn.net/dream_broken/article/details/52883883 前言 記下CentOS

AIX檢視硬碟大小檢視檔案系統在磁碟上的分佈

今天大概瞭解了幾種檢視硬碟和記憶體大小的方法。在這裡記錄一下。 硬碟 1. lsattr -El hdisk* 2.lscfg -vpl hdisk*  3.如果 2看不到的話,可以通過 part number 在baidu 或者 google 中 查到。 4.booti

專案(Gensim庫)--維基百科中文資料處理

1.下載維基百科資料 https://dumps.wikimedia.org/zhwiki/latest/ 2.預處理檔案:將壓縮的檔案轉化成.txt檔案 新增指令碼檔案process.py,程式碼如下: import logging import os.path import sys

專案(文字資料分析)--新聞分類任務

1.資料 import pandas as pd import jieba #資料(一小部分的新聞資料) df_news = pd.read_table('val.txt',names=['category','theme','URL','content'],encoding='ut

【python課堂專欄】python課堂04 - 基本資料型別布林篇

python小課堂04 - 基本資料型別布林篇 什麼是布林型別? 布林型別:英文boolean。 舉個栗子,比如今天是愚人節!你發工資了,於是你興高采烈的去與同事探討一番,同事偷偷的告訴你,他漲工資了!然後你表示很開心,但是你意識到今天是愚人節了,於是你充滿疑問的心態去問他,

[大資料專案]-牛學堂2018年大資料24期-10階段3個專案

  2018最新最全大資料技術、專案視訊。整套視訊,非那種淘寶雜七雜八網上能免費找到拼湊的亂八七糟的幾年前的不成體系浪費咱們寶貴時間的垃圾,詳細內容如下,需要的聯絡QQ:3164282908(加Q註明部落格園)。 更有海量大資料技術視訊、大資料專案視訊,機器學習深度學習技術視訊、專案視訊。Pyt

springMVC專案例項

一、什麼是 Spring MVC Spring MVC 屬於 SpringFrameWork 的後續產品,已經融合在 Spring Web Flow 裡面,是一個強大靈活的 Web 框架。Spring MVC 提供了一個 DispatcherServlet 作為前端控制器來分配請求。通過策略介面

PHP+MySQL開發專案的集合筆記(四)控制div的排列和p標籤,從另外表讀取加工資料並規定小數點位數

需求:HTML頁面增加註釋,div盒子控制曲線大小,多個盒子相互巢狀。具體資料從另外表內獲取。 HTML頁面更改: <!-- Morris chart - Sales --> <!-- Change! -->

專案——訓練畫風資料

承接上篇處理好資料之後開始定義網路 tf.placeholder定義形參 datas_placeholder = tf.placeholder(tf.float32, [None,32,32,3]) labels_placeholder = tf.placeholder(tf.int

專案——自制畫風資料

承接上篇爬取了想要的資料集之後,先將圖片的尺寸統一。(我自己爬取了塗鴉,油畫,素描這3類圖片) 關於塗鴉資料集爬下來的圖片,其中混入了一些妹子和西海岸黑人黑幫文化的圖片。(為什麼我也不知道。。。)注意清除,資料集的好壞很關鍵! resize 先統一圖片格式32*32 # co