SpringMVC 入門

来源:http://www.cnblogs.com/wave-gbt/archive/2016/09/08/5852420.html
-Advertisement-
Play Games

主要參考了 [IMOOC-SpringMVC 起步](http://www.imooc.com/video/7237) 視頻教程和 [SpringMVC從入門到精通 系列 - HansonQ](http://www.imooc.com/article/3804) ,還有自己的一些總結。MVC 簡介、... ...


MVC 簡介

1、MVC 是一種架構模式
程式分層,分工合作,既相互獨立,又協同工作,分為三層:模型層、視圖層和控制層

2、MVC 是一種思考方式
View:視圖層,為用戶提供UI,重點關註數據的呈現,為用戶提供界面
Model:模型層,業務數據的信息表示,關註支撐業務的信息構成,通常是多個業務實體的組合
Controller:控制層,調用業務邏輯產生合適的數據(Model),傳遞數據給視圖用於呈現

MVC 設計模式在 B/S 下的應用:
MVC設計模式在B/S下的應用

①:瀏覽器發送請求到控制器(這裡要知道控制器的作用)
②:控制器不能處理請求必須交給模型層來處理接著去訪問資料庫
③:模型層將處理好的結果返回給控制層
④:控制層將邏輯視圖響應給瀏覽器(瀏覽器顯示的是渲染過的視圖)

MVC 本質:MVC 的核心思想是業務數據抽取同業務數據呈現相分離;分離有利於程式簡化,方便編程

前端控制器模式

前端控制器模式(Front Controller Pattern)是用來提供一個集中的請求處理機制,所有的請求都將由一個單一的處理程式處理。該處理程式可以做認證/授權/記錄日誌,或者跟蹤請求,然後把請求傳給相應的處理程式。

  • 前端控制器(Front Controller)- 處理應用程式所有類型請求的單個處理程式,應用程式可以是基於 web 的應用程式,也可以是基於桌面的應用程式。
  • 調度器(Dispatcher) - 前端控制器可能使用一個調度器對象來調度請求到相應的具體處理程式。
  • 視圖(View) - 視圖是為請求而創建的對象。

前端控制器的主要作用:

  • 指前端控制器將我們的請求分發給我們的控制器去生成業務數據
  • 將生成的業務數據分發給恰當的視圖模版來生成最終的視圖界面

Front Controller(MVC)

SpringMVC 基本概念

SpringMVC 基本概念

對組件說明:
1、DispatherServlet:前端控制器 用戶請求到達前端控制器,相當於 MVC 中的 C,而 DispatherServlet 是整個流程的核心,它來調用其他組件來處理用戶的請求,前端控制器的存在降低了其他組件之間的耦合度。
2、HandlerMapping:處理器映射器 它的作用就好比去看電影要拿著電影票根據電影票上面的座位號找到座位其中座位就是 Handler,電影票以及上面的座位號就是 URL HandlerMapping 負責根據用戶請求找到 Handler 即處理器,SpringMVC 提供了不同的映射器實現不同的映射方式,例如:配置文件方式,實現介面方式,註解方式等。
3、Handler:處理器 Handler 是後端控制器,在前端控制器的控制下後端控制器對具體的用戶請求進行處理,Handler 涉及到具體的用戶業務請求,所以一般情況下需要程式員根據業務需求開發。
4、HandlerAdapter:處理器適配器 通過 HandlerAdapter 對處理器進行執行,這是適配器模式的應用,通過適配器可以對更多類型的處理器進行執行。播放的電影是 3D 的你看不清楚,因此電影院跟你說你要想看清電影就必須戴 3D 眼鏡。也就是說 Handler 滿足一定的要求才可以被執行。
5、ViewResolver:視圖解析器 ViewResolver 負責將處理結果生成 View 視圖,ViewResolver 首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對象,最後對View進行渲染將處理結果通過頁面展示給用戶。

SpringMVC 基本概念

工作原理解釋說明:
1、用戶發送請求到 SpringMVC 框架提供的 DispatcherServlet 這個前端控制器(瞭解 struts2 的朋友也都知道其實 struts2也有一個前端控制器 web.xml 中的 filter 標簽就是)。
2、前端控制器會去找處理器映射器(HandlerMapping),處理器映射器根據請求 url 找到具體的處理器,生成處理器對象及處理器攔截器(如果有則生成)一併返回給 DispatcherServlet 。
3、根據處理器映射器返回的處理器,DispatcherServlet 會找“合適”的處理器適配器(HandlerAdapter)
4、處理器適配器 HandlerAdpater 會去執行處理器(Handler 開發的時候會被叫成 Controller 也叫後端控制器在 struts2 中action 也是一個後端控制器)執行之前會有轉換器、數據綁定、校驗器等等完成上面這些才會去正在執行 Handler
5、後端控制器 Handler 執行完成之後返回一個 ModelAndView 對象 。
6、處理器適配器 HandlerAdpater 會將這個 ModelAndView 返回前端控制器 DispatcherServlet。前端控制器會將ModelAndView 對象交給視圖解析器 ViewResolver。
7、視圖解析器 ViewResolver 解析 ModelAndView 對象之後返回邏輯視圖。
8、前端控制器 DispatcherServlet 對邏輯視圖進行渲染(數據填充)之後返回真正的物理 View 並響應給瀏覽器。

SpringMVC 基本概念

SpringMVC 配置

1、前端控制器需要在 web.xml 中配置

<!-- 配置前端控制器 -->
<servlet>
    <servlet-name>web-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--載入前端控制器配置文件 上下文配置位置-->
    <init-param>
        <!-- 備註:
            contextConfigLocation:指定 SpringMVC 配置的載入位置,如果不指定則預設載入
            WEB-INF/[DispatcherServlet 的 Servlet 名字]-servlet.xml
         -->
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/spring-*.xml</param-value>
    </init-param>
    <!-- 表示隨WEB伺服器啟動 -->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>web-dispatcher</servlet-name>
    <!-- 備註:可以攔截三種請求
        第一種:攔截固定尾碼的url,比如設置為 *.do、*.action, 例如:/user/add.action 此方法最簡單,不會導致靜態資源(jpg,js,css)被攔截
        第二種:攔截所有,設置為/,例如:/user/add  /user/add.action此方法可以實現REST風格的url,
        很多互聯網類型的應用使用這種方式.但是此方法會導致靜態文件(jpg,js,css)被攔截後不能正常顯示.需要特殊處理
        第三種:攔截所有,設置為/*,此設置方法錯誤,因為請求到Action,當action轉到jsp時再次被攔截,提示不能根據jsp路徑mapping成功
    -->
    <!-- 預設匹配所有的請求 -->
    <url-pattern>/</url-pattern>
</servlet-mapping>

2、在 spring/spring-web.xml 配置視圖解析器

<!-- 配置視圖解析器 -->
<!-- InternalResourceViewResolver:支持JSP視圖解析 -->
<!-- viewClass:JstlView 表示JSP模板頁面需要使用JSTL標簽庫,所以classpath中必須包含jstl的相關jar包; -->
<!-- prefix 和 suffix:查找視圖頁面的首碼和尾碼,最終視圖的址為: -->
<!-- 首碼+邏輯視圖名+尾碼,邏輯視圖名需要在controller中返回ModelAndView指定,比如邏輯視圖名為hello,-->
<!-- 則最終返回的jsp視圖地址 "WEB-INF/jsp/hello.jsp" -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- 決定視圖類型,如果添加了jstl支持(即有jstl.jar),那麼預設就是解析為jstl視圖 -->
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    <!-- 視圖首碼 -->
    <property name="prefix" value="/WEB-INF/jsp/" />
    <!-- 視圖尾碼 -->
    <property name="suffix" value=".jsp" />
</bean>

3、在 spring/spring-web.xml 配置 註解模式

<!-- 自動載入RequestMappingHandlerMapping和RequestMappingHandlerAdapter, -->
<!-- 可用在xml配置文件中使用<mvc:annotation-driven>替代註解處理器和適配器的配置。 -->
<mvc:annotation-driven/>

4、在 spring/spring-web.xml 配置 掃描web 相關的 bean

<!-- 組件掃描器:可以掃描 @Controller、@Service、@Repository 等等 -->
<context:component-scan base-package="com.controller" />

SpringMVC 中的註解

@Controller

@Controller 註解,用於標識這個類是一個後端控制器(類似struts中的action),主要作用就是接受頁面的參數,轉發頁面。
@Controller 源碼:

@Target({ElementType.TYPE}) // 表明只能定義在類上面
@Retention(RetentionPolicy.RUNTIME) //保留策略是RUNTIME,在JVM載入類時,會把註解載入到JVM記憶體中(它是唯一可以用反射來讀取註解的策略)
@Documented //@Documented用於描述其它類型的annotation應該被作為被標註的程式成員的公共API,因此可以被例如javadoc此類的工具文檔化。Documented是一個標記註解,沒有成員。
@Component //spring框架規定當一個類不好歸類(service、dao、controller)的時候可以使用這個註解,由此可見即便好歸類內部還是使用的@Component註解
public @interface Controller {
    /**
     * The value may indicate a suggestion for a logical component name,
     * to be turned into a Spring bean in case of an autodetected component.
     * @return the suggested component name, if any
     */
    String value() default "";
}

@RequestMapping

這個註解的作用目標就跟@Controller不一樣了,這個註解可以定義在類上面也可以定義在方法上面。

/**
* 1.@RequestMapping:除了修飾方法,還可以修飾類
* 2.類定義處:提供初步的請求信息映射.相對於WEB應用的根目錄(窄化請求)
* 3.方法處:提供進一步的細分映射信息。相對於類定義處的URL。
*      若類定義處為標註@RequestMapping,則方法出的URL相對於WEB應用的根目錄
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String[] value() default {};
    RequestMethod[] method() default {}; //限制請求方式
    String[] params() default {}; //要求請求的URL包含指定的參數
}

代碼實例

@Controller
@RequestMapping("/demo")
public class IndexController {
    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public String index(Model model, HttpServletRequest request) {
        // 在游覽器訪問 http://localhost:8080/demo/test 將進入這裡
        model.addAttribute("originURL", "");
        model.addAttribute("controllerName", "index");
        return "index";
    }
}

@RequestMapping 還支持 Ant 方格的請求

?:匹配文件中的一個字元
*:匹配文件中任意字元
**:**匹配多層路徑

/user/*/createUser : 匹配 -/user/aa/createUser 或者 -/user/aa/createUser
/user/**/createUser : 匹配 -/user/aa/createUser 或者 -/user/createUser 或者 -/user/aa/cc/createUser
/user/createUser?? : 匹配 -/user/aa/createUseraa

@PathVariable

@PathVariable 這個註解支持現在當下較為流行的 Restful 風格的 URL。 先說說這個註解的作用,支持將 url 中的占位符參數綁定到目標方法的參數上, 該功能也是 SpringMVC 實現 Restful 風格 url 的重要措施。

代碼實例

// http://localhost:8080/demo/sss
@RequestMapping(value = "/{slug:.+}", method = RequestMethod.GET)
    public String index2(@PathVariable("slug") String slug, Model model) {
    LOG.info("DemoController index2 slug  " + slug);
    // common
    model.addAttribute("originURL", "demo/");
    model.addAttribute("controllerName", "demo");
    model.addAttribute("controllerMethod", "index2");
    model.addAttribute("slug", slug);
    return "demo";
}

//slug = sss

我們熟悉的請求應該是 POST 和 GET 請求,這兩個請求也是最常用的而實際上 HTTP1.1 請求還有 PUT、DELETE 等8種來表名請求的動作。

在 SpringMVC 中要實現 PUT 和 DELETE 請求需要在 web.xml 額外配置一個過濾器,這個過濾器的作用就是把 POST 請求變為 PUT 和 DELETE 請求。
關於 Restful 的內容計劃單獨寫。

@RequestParam

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    String value() default "";//值即為請求參數的參數名
    boolean required() default true;//該參數是否是必須。預設值為true
    String defaultValue() default ValueConstants.DEFAULT_NONE;//請求參數的預設值
}
// http://localhost:8080/demo/para?slug=google
@RequestMapping(value = "/para", method = RequestMethod.GET)
public String index3(@RequestParam(value = "slug", defaultValue = "") String slug, Model model) {
    model.addAttribute("originURL", "demo/");
    model.addAttribute("controllerName", "demo");
    model.addAttribute("controllerMethod", "index3");
    model.addAttribute("slug", slug);
    return "demo";
}
slug = google

另外還有一點要提示一下,參數沒有加這個註解也能映射成功,這是應為 SpringMVC 框架支持請求參數和目標方法參數一致的時候可以省略這個註解。

@ResponseBody

/**
 * Annotation that indicates a method return value should be bound to the web
 * response body. Supported for annotated handler methods in Servlet environments.
 * 
 * 這個註解指明一個方法的返回值應該綁定在 web response body 中,在 Servlet 環境中支持註解處理方法
 * 
 * <p>As of version 4.0 this annotation can also be added on the type level in
 * which case it is inherited and does not need to be added on the method level.
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {
}

代碼

// http://localhost:8080/demo/json
@RequestMapping(value = "/json", method = RequestMethod.POST)
public @ResponseBody Domain index7(HttpServletRequest request, Model model) {

    LOG.info("DemoController demo index7");
    model.addAttribute("originURL", "demo/");
    model.addAttribute("controllerName", "demo");
    model.addAttribute("controllerMethod", "index7");

    Domain domain = new Domain();
    domain.setDomain("gggoogle.com");
    domain.setId(100);
    return domain;
}

/* response body
{
    "id": 100,
    "domain": "gggoogle.com"
}
*/

SpringMVC 數據綁定

簡單說一下場景:
對於一個註冊頁面有很多信息譬如:用戶名、密碼、確認密碼、郵箱、手機、興趣等等。這時候就會想能不能將這些個參數包裝在一個對象中(POJO),用這個POJO來做目標方法的形參上面。可以說的是 SpringMVC 是支持將 POJO 作為目標參數的。當然也是要遵循一些規則的,就是表單的 name 屬性值要和 POJO 的屬性值要一致。當然了,這樣又會有一個新的疑問支不支持級聯屬性答案是支持的。

public class Address {
    private String city;
    ...
}
public class Persion {
    private String name;
    private Address address;
    ...
}
<form action="/demo/pojo">
    NAME:<input type="text" name="name" />
    CITY:<input type="text" name="address.city" />
</form>
@RequestMapping(value = "/pojo", method = RequestMethod.POST)
public String index4(Persion persion, Model model) {
    model.addAttribute("originURL", "demo/");
    model.addAttribute("controllerName", "demo");
    model.addAttribute("controllerMethod", "index4");
    model.addAttribute("persion", persion);
    return "demo";
}

SpringMVC 使用 Servlet API

可以使用 Servlet 原生的API作為目標方法的參數。具體支持以下類型:HttpServletRequest、HttpServletResponse、HttpSession、java.security.Principal、Locale、InputStream、OutputStream、Reader、Writer

// http://localhost:8080/demo/req?slug=facebook
@RequestMapping(value = "/req", method = RequestMethod.GET)
public String index5(HttpServletRequest request, Model model) {
    String slug = request.getParameter("slug");
    model.addAttribute("originURL", "demo/");
    model.addAttribute("controllerName", "demo");
    model.addAttribute("controllerMethod", "index5");
    model.addAttribute("slug", slug);
    return "demo";
}

Reference:


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 應用程式安裝在用戶電腦上,異常處理一直是反覆出現的問題。用戶報障中的描述不足以重現該問題。你不得不猜測,或者只是做猴子測試,以找出其異常出現的根源。 最嚴重的問題是當認為你已經找出了原因並糾正它,但後來您收到新的報障,還是同樣的問題,證明自己只是讓原來的代碼變得更加複雜。 為此您不斷的改進異常日誌 ...
  • 直播平臺整體架構 視頻直播鏈路 視頻流轉換成不同清晰度 不同的端,不同的網路環境,需要不同碼率,以保流暢 播放器的基本實現 SDK在播放器上做層管理 視頻相關技術細節 消息發送流程 不同消息通道的優劣對比 心跳及房間結構 用戶按需分桶 固定分桶與按需分桶對比 關鍵詞及垃圾文本過濾 大促風險控制 平臺... ...
  • 這道題的題目是: 你所在的學校有電腦科學專業和軟體工程專業麽?相關專業的教學計劃和畢業出路有什麼不同?閱讀有關軟體工程和電腦科學的區別的文章,談談你的看法。 我來自天津大學電腦科學技術學院,電腦科學技術專業。選修的這門課是現代軟體工程,由於之前本科我跟隨導師做過一些軟體工程的學術研究,因此很 ...
  • 抽象類&抽象方法 (只能被繼承)(關鍵字 abstract)(繼承關鍵字extends) 抽象類&抽象方法 (只能被繼承)(關鍵字 abstract)(繼承關鍵字extends) 具有抽象方法的類為抽象類, 抽象方法即為沒有內容的空方法,要求子類進行完善內容, 抽象類不能實例化,只能繼承, 通過ex ...
  • 回到目錄 進位 我是一個程式猿,我喜歡簡單的數字,十進位如何,數字太多,有10種數字組成,但由於它廣為人知,所有使用最為廣泛,人們的慣性思維培養了十進位,並說它是最容易被計算的數字,事實上,在電腦里,最簡單的進位是當然是二進位,原因最為直接,因為它只有兩種數字,0和1。 二進位里的最簡單的運算 不 ...
  • SSH 為 struts+spring+hibernate的一個集成框架,是目前較流行的一種Web應用程式開源框架。 首先我們先瞭解SSH的框架所需的包和基本概念: 一、下麵我們先來瞭解一下struts2,下載地址:http://struts.apache.org/ Struts2作為系統的整體基礎 ...
  • 1.singleShot的用法 代碼: QTextEdit *testEdit = new QTextEdit("hello world"); testEdit->setMaximumHeight(20); QTimer::singleShot( 5*1000, testEdit, SLOT(cle ...
  • 單例模式 定義:確保一個類只有一個實例,而且自行實例化並向整個系統提供這個實例。 類型:創建類模式 類圖: 單例模式應該是23種設計模式中最簡單的一種模式了。它有以下幾個要素: 私有的構造方法 指向自己實例的私有靜態引用 以自己實例為返回值的靜態的公有的方法 單例模式根據實例化對象時機的不同分為兩種 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...