SpringMvc demo示例及源碼詳細分析

三層架構介紹

  我們的開發架構一般都是基於兩種形式,一種C/S架構,也就是客戶端/服務器,另一種是B/S架構,也就是瀏覽器/服務器。在JavaEE開發中,幾乎全部都是基於B/S架構的開發。那麼在B/S架構中,系統標準的三層架構包括:表現層、業務層、持久層。三層架構在我們的實際開發中使用的非常多。

三層職責

表現層

  也就是我們長說的web層。它負責接收客戶端請求,向客戶端響應結果,通常客戶端使用http協議請求web層,web需要接收http請求,完成http響應。

  表現層包括展示層和控制層:控制層負責接收請求,展示層負責結果的展示。

  表現層依賴業務層,接收到客戶端請求一般會調用業務層進行業務處理,並將處理結果響應給客戶端。

  表現層的設計一般都是使用mvc模型。(mvc是表現層的設計模型,和其他層沒有關係)

業務層

  也就是我們常說的 service層。它負責業務邏輯處理,和我們開發項目的需求息息相關。web層依賴業務層,但是業務層不依賴web層。

  業務層在業務處理時可能會依賴持久層,如果要對數據持久化需要保證事務一致性。(也就是我們說的,事務應該放到業務層來控制)

持久層

  也就是我們常說的dao層。負責數據持久化,包括數據層即數據庫和數據訪問層,數據庫是對數據進行持久化的載體,數據訪問層是業務層和持久層交互的接口,業務層需要通過數據訪問層將數據持久化到數據庫中。

  通俗的講,持久層就是和數據交互,對數據庫表進行增刪改查的。

mvc設計模式介紹

  mvc全名是Model View Controller,模型(Model)-視圖(View)-控制器(Controller)的縮寫,是一種用於設計創建web應用程序表現層的模式。mvc中每個部分各司其職:

Model(模型)

  模型包含業務模型和數據模型,數據模型用於封裝數據,業務模型用於處理業務。

View(視圖)

  通常指的就是我們的jsp或者html。作用一般就是展示數據的。

  通過視圖是依據模型數據創建的。

Controller(控制器)

  是應用程序中處理用戶交互的部分。作用一般就是處理程序邏輯的。

SpringMVC介紹

Spring MVC是什麼?

  SpringMVC是一種基於Java的實現MVC設計模型的請求驅動類型的輕量級Web框架,屬於SpringFrameWork的後續產品,已經融合在Spring Web Flow裏面。Spring框架提供了構建Web應用程序的全功能MVC模塊。使用Spring可插入的MVC架構,從而在使用Spring進行Web開發時,可以選擇使用Spring的Spring MVC框架或集成其他MVC開發框架,如Struts1(現在一般不用),Struts2等。

  SpringMVC已經成為目前最主流的MVC框架之一,並隨着Spring3.0的發布,全面超越Struts2,成為最優秀的MVC框架。

  它通過一套註解,讓一個簡單的Java類稱為處理請求的控制器,而無需實現任何接口。同時它還支持RESTful編程風格的請求。

總結

  Spring MVC和Struts2一樣,都是為了解決表現層問題的web框架,他們都是基於MCC設計模式的。而這些表現層框架的主要職責就是處理前端HTTP請求

 Spring MVC由來?

 Spring MVC全名叫Spring Web MVC,它是Spring家族Web模塊的一個重要成員。這一點,我們可以從Spring的整體結構中看的出來:

 

 

 為什麼學習SpringMVC?

   也許你會問,為什麼要學習Spring MVC呢?struts2不才是主流嘛?看SSH的概念有多火?

  其實很多初學者混淆了一個概念,SSH實際上指的是Struts1.x+Spring+Hibernate。這個概念已經有十幾年的歷史了。在Struts1.x時代,它是當之無愧的霸主,但是在新的MVC框架湧現的時代,形式已經不是這樣了,Struts2.x藉助了Struts1.x的好名聲,讓國內開發人員認為Struts2.x是霸主繼任者(其實兩者在技術上無任何關係),導致國內程序員大多數學習基於Struts2.x的框架,又一個貌似很多的概念出來了S2SH(Struts2+Spring+Hibernate)整合開發。

 SpringMVC如何處理請求?

   SpringMVC是基於MVC設計模型的,MVC模式指的就是Model(業務模型)、View(視圖)、Controller(控制器)。SpringMVC處理請求就是通過MVC這三個角色來實現的。

注:不要把MVC設計模式工程的三層架構混淆,三層結構指的是表現層、業務層、數據持久層。而MVC只針對表現層進行設計

  下面讓我們看看處理流程吧

 

 

 第一個MVC程序

達到效果

  1. 學會如果配置前端控制器
  2. 如何開發處理器

任務需求

  訪問/queryItem,返回商品列表頁面,商品數據暫時使用靜態數據(不從數據庫查詢並返回)。

 實現

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.cyb</groupId>
    <artifactId>springmvc-demo01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <dependencies>
        <!-- spring ioc組件需要的依賴包 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>

        <!-- 基於AspectJ的aop依賴 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>

        <!-- spring MVC依賴包 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>

        <!-- jstl -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        
        <!-- servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- 配置Maven的JDK編譯級別 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>8080</port>
                </configuration>
            </plugin>
            <!-- tomcat依賴包 -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
            </plugin>
        </plugins>
    </build>
</project>

注:

1、依賴添加完之後,項目上右鍵->maven->Update Maven Project

2、項目上右鍵->Java EE Tools->Generate Deployment Descriptor Stub

 web.xml

路徑:src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    <!-- 學習前置條件 -->
    <!-- 問題1:web.xml中servelet、filter、listener、context-param加載順序 -->
    <!-- 問題2:load-on-startup標籤的作用,影響了Servlet對象創建的時機 -->
    <!-- 問題3:url-pattern:標籤的配置方式有四種:/dispatcherServlet、/servlet/*、*.do、/ 以上四種配置-->
    <!-- 問題4:url-pattern標籤的配置為什麼配置/就不攔截jsp請求,而配置/*,就會攔截jsp請求 -->
    <!-- 問題4原因:標籤配置為/*報錯,因為它攔截了jsp請求,但是又不能處理jsp請求。 -->
    <!-- 問題5:配置了springmvc去讀取spring配置文件之後,就產生了spring父子容器的問題 -->
    
    <!-- 配置前端控制器 -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 設置spring配置文件路徑 -->
        <!-- 如果不設置初始化參數,那麼DispatcherServlet會讀取默認路徑下的配置文件 -->
        <!-- 默認配置文件路徑:/WEB-INF/springmvc-servlet.xml -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!-- 指定初始化時機,設置為2,表示Tomcat啟動時,它會跟隨着啟動,DispatcherServlet會跟隨着初始化 -->
        <!-- 如果沒有指定初始化時機,DispatcherServlet就會在第一次被請求的時候,才會初始化,而且只會被初始化一次(單例模式) -->
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!-- url-pattern的設置 -->
        <!-- 不要配置為/*,否則報錯 -->
        <!-- 通俗解釋:會攔截整個項目中的資源訪問,包含JSP和靜態資源的訪問,對於JS的訪問,springmvc提供了默認Handler處理器 -->
        <!-- 但是對於JSP來講,springmvc沒有提供默認的處理器,我們也沒有手動編寫對應的處理器,此時按照springmvc的處理流程分析得知,它down了 -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

springmvc.xml

路徑:src/main/resources/springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- 處理器類的掃描 -->
    <context:component-scan
        base-package="com.cyb.springmvc.controller"></context:component-scan>
    <!-- 註解映射器 @Controller和@RequestMapping組合這種方式的註解映射的解析 -->
    <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean> -->
    <!-- 註解適配器 -->
    <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean> -->
    <!-- 配置註釋的適配器和映射器,同時還注入其他很多的bean -->
    <!-- <mvc:annotation-driven></mvc:annotation-driven> -->
    <!-- 显示配置視圖解析器 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>

ItemController.java

路徑:/src/main/java/com/cyb/springmvc/controller/ItemController.java

package com.cyb.springmvc.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.cyb.springmvc.po.item;

/**
 * 處理器的開發方式有多種,比如實現HttpRequestHandler接口、Controller接口的方式、還有註解的方式 企業中使用的一般都是註解的方式
 * 註解的注意事項
 *  1、類上加上@Controller註解(必須是Controller,可以通過源碼找到答案)
 *  2、類上或者方法上面要加上@RequestMapping(必須)
 * 
 * @author apple
 *
 */
@Controller
public class ItemController {
    //@RequestMapping此時填寫的是url
    //ModelAndView:Model標識的是數據類型,View就是最終要展示給用戶的視圖
    @RequestMapping("queryItem")
    public ModelAndView queryItem() {
        //用靜態數據模型
        List<item> itemList=new ArrayList<item>();
        
        item item_1=new item();
        item_1.setName("蘋果手機");
        item_1.setPrice(5000);
        item_1.setDetail("iphoneX蘋果手機!");
        itemList.add(item_1);
        
        item item_2=new item();
        item_2.setName("華為手機");
        item_2.setPrice(6000);
        item_2.setDetail("華為5G網速就是快!");
        itemList.add(item_2);
        ModelAndView mvAndView=new ModelAndView();
        //設置數據模型,相當於request的setAttribute方法,實質上,底層確實也是轉成了request()
        //先將k/v數據放入map中,最終根據視圖對象不同,再進行後續處理
        mvAndView.addObject("itemList",itemList);
        //設置view視圖
        mvAndView.setViewName("/WEB-INF/jsp/item/item-list.jsp");
        return mvAndView;
    }
}

item.java

路徑:src/main/java/com/cyb/springmvc/po/item.java

package com.cyb.springmvc.po;

public class item {
    private String name;
    private double price;
    private String detail;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }
}

item-list.jsp

 路徑:src/webapp/WEB-INF/jsp/item/item-list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查詢商品列表</title>
</head>
<body>
    <form action="${pageContext.request.contextPath }/itemList.do"
        method="post">
        查詢條件:
        <table width="100%" border=1>
            <tr>
                <td><input type="submit" value="查詢" /></td>
            </tr>
        </table>
        商品列表:
        <table width="100%" border=1>
            <tr>
                <td>商品名稱</td>
                <td>商品價格</td>
                <td>商品描述</td>
                <td>操作</td>
            </tr>
            <c:forEach items="${itemList }" var="item">
                <tr>
                    <td>${item.name }</td>
                    <td>${item.price }</td>
                    <td>${item.detail }</td>
                    <td><a
                        href="${pageContext.request.contextPath }/itemEdit.do?id=${item.name}">修改</a></td>
                </tr>
            </c:forEach>

        </table>
    </form>
</body>

</html>

 項目結構圖

 運行

 完整項目

 SpringMVC 框架源碼分析

 框架結構

 程序入口

一、初始化Servlet

二、處理器映射,渲染頁面

 注:標記的方法體,跟蹤進去讀源碼就好啦!~~

默認配置文件

 

 

 

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
    org.springframework.web.servlet.function.support.RouterFunctionMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
    org.springframework.web.servlet.function.support.HandlerFunctionAdapter


org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
    org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
    org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

 

架構流程

  1. 用戶發送請求至前端控制器DispatcherServlet
  2. DispatcherServlet收到請求調用HandlerMapping處理器映射器
  3. 處理器映射器根據請求url找到具體的處理器,生成處理器對象及處理器攔截器(如果有則生成)一併返回給DispatcherServlet
  4. DispatcherServlet通過HandlerAdapter處理器適配器調用處理器
  5. HandlerAdapter執行處理器(handler,也叫後端控制器)
  6. Controller執行完成返回ModelAndView
  7. HandlerAdapter將handler執行結果ModelAndView返回給DispatcherServlet
  8. DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器
  9. ViewReslover解析后返回具體View對象
  10. DispatcherServlet對View進行渲染視圖(即將模型數據填充至視圖種)
  11. DispatcherServlet響應用戶

 組件說明

 DispatcherServlet:前端控制器

   用戶請求到達前端控制器,它就相當於mvc模式中的C,DispatcherServlet是整個流程控制的中心,由它調用其他組件處理用戶的請求,DispatcherServlet的存在降低了組件之間的耦合性。

HandlerMapping:處理器映射器

   HandlerMapping負責根據用戶請求找到Handler即處理器,springmvc提供了不同的映射器實現不同的映射方式,例如:配置文件方式,實現接口方式,註解方式等。

Handler:處理器

  Handler是繼DispatcherServlet前端控制器的後端控制器,在DispatcherServlet的控制下,Handler對具體的用戶請求進行處理。

  由於Handler涉及到具體的用戶業務請求,所以一般情況需要程序員根據業務需求開發Handler。

HandlerAdapter:處理器適配器

  通過HandlerAdapter對處理器進行執行,這是適配器模式的應用,通過擴展適配器可以對更多類型的處理器進行執行。

 View Resolver:視圖解析器

  View Resolver負責將處理結果生成View視圖,View Resolver首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對象,最後對View進行渲染將處理結果通過頁面展示給用戶。

View:視圖

  springmvc框架提供了很多View視圖類型的支持,包括:jstlView、freemarkerView、pdfView等。我們最常用的視圖就是jsp。

  一般情況下需要通過頁面標籤或頁面模板技術將模型數據通過頁面展示給用戶,需要由程序員根據業務需求開發具體的頁面。

說明

  再springmvc的各個組件中,處理器映射器、處理器適配器、視圖解析器稱為springmvc的三大組件。需要用戶開發的組件有:處理器、視圖

三大組件配置(註解方式)

註解映射器和適配器

通過bean標籤配置

RequestMappingHandlerMapping:註解式處理器映射器

  對類中標記@ResquestMapping的方式進行映射,根據ResquestMapping定義的url匹配ResquestMapping標記的方法,匹配成功返回HandlerMethod對象給前端控制器,HandlerMethod對象中封裝url對應的方法Method。

配置如下:

<!--註解映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--註解適配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

通過mvc標籤配置(推薦)

<mvc:annotation-drivern />

  mvc:annotation-drivern標籤的作用,詳見AnnotationDrivenBeanDefinitionParser類的parse方法。分析源碼可知:mvc:annotation-drivern往spring容器中註冊以下的一些BeanDefinition

  • ContentNegotiationManagerFactoryBean
  • RequestMappingHandlerMapping
  • ConfigurableWebBindingInitializer
  • RequestMappingHandlerAdapter
  • CompositeUriComponentsContributorFactoryBean
  • ConversionServiceExposingInterceptor
  • MappedInterceptor
  • ExceptionHandlerExceptionResolver
  • ResponseStatusExceptionResolver
  • DefaultHandlerExceptionResolver
  • BeanNameUrlHandlerMapping
  • HttpRequestHandlerAdapter
  • SimpleControllerHandlerAdapter
  • HandlerMappingIntrospector

視圖解析器

再springmvc.xml文件配置如下:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!-- 該視圖解析器,默認的視圖類就是JstlView,可以不寫 -->
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
  • InternalResourceViewResolver:默認支持JSP視圖解析
  •  viewClass:JstlView表示JSP模板頁面需要使用JSTL標籤庫,所以classpath中必須包含jstl的相關jar 包。此屬性可以不設置,默認為JstlView
  • prefix suffix:查找視圖頁面的前綴和後綴,最終視圖的址為:前綴+邏輯視圖名+後綴,邏輯視圖名需要在controller中返回的ModelAndView指定,比如邏輯視圖名為hello,則最終返回的jsp視圖地址 “WEB-INF/jsp/hello.jsp”

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

收購3c,收購IPHONE,收購蘋果電腦-詳細收購流程一覽表

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品在網路上成為最夯、最多人討論的話題?

※高價收購3C產品,價格不怕你比較

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!