1. 程式人生 > >使用Spring MVC搭建WEB應用框架-完整案例

使用Spring MVC搭建WEB應用框架-完整案例

============

1.簡介

首先Spring MVC是基於三個層面來開發的,那三個層面呢?

M(model) - 模型層,控制器完成邏輯處理後,通常會產生一些資訊,而這些資訊需要返回給使用者並在瀏覽器上顯示的,我們把這些資訊稱為模型;

V(view) - 檢視層,我們使用JSP作為檢視層,通過檢視能使這些模型資料渲染輸出,並通過這個輸出響應的對你傳遞給客戶端;

C(controller) - 控制層,從使用者提交請求開始,這些請求都會通過一個前端控制器Servlet,然後經過前端控制器Servlet的解析,再將使用者請求指定到某一個特定的控制器,即控制層。

三個層的關係:使用者提交請求,經前端控制器Servlet解析,再指定控制器,當控制器處理邏輯資訊後,返回模型資料,然後再經指定的檢視把模型資料渲染輸出,終於呈現給客戶端,即使用者。

2.引入spring mvc jar包

因為我之前的文章介紹過Maven的使用(專案是用Maven搭建的),我們這裡就使用Maven的依賴來關聯下載spring的jar包吧。

首先,搜尋需要的,如圖:


下面還有一大堆相關的列表,找到我們需要的或者你可以輸入命名搜尋會更快


點選進去,選擇版本


點選進去,把依賴複製出來到你的pom.xml中,即可


pom.xml配置:

<project>
...
<!-- 定義屬性,供${propertieName}訪問 -->
  <properties>
  	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  	<spring.version>4.1.3.RELEASE</spring.version>
  </properties>
  <!-- 依賴關聯 -->
  <dependencies>
  	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>${spring.version}</version>
	</dependency>
  </dependencies>
...
</project>

完之後,執行pom.xml update


看,相關聯的jar都會下載到本地倉庫,這就是使用Maven的好處!

3.配置一個前端控制器Servlet

Spring MVC中,所有的請求的必經之路為一個前端控制器Servlet,即DispatcherServlet,它是Spring MVC的核心。

DispatcherServlet必須在Web應用程式的web.xml檔案中進行配置,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app...>
...
<!-- spring mvc 前端控制器 -->
  	<servlet>
		<servlet-name>wwo</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
                            classpath:conf/wwo-servlet.xml
                        </param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>wwo</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
...
</web-app>

DispatcherServlet的目的既是為了根據一個XML檔案來載入其配置到Spring應用上下文中,xml檔案的命名方式是預設通過<servlet-name>來指定的XML的檔名,即我們常見的${<servlet-name>}-servlet.xml,如上述例子xml檔案命名為:wwo-servlet.xml(預設路徑位於應用程式的WEB-INF目錄下)。通常我們spring的配置檔案可以分成多個XML檔案,一個用於服務層,一個用於持久層還有一個用於資料來源配置。那怎麼辦呢?

spring 為我提供了一個ContextLoaderListener,它是一個Servlet監聽器,我們只需將ContextLoaderListener配置於web.xml檔案裡即可,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
...
<!-- spring監聽器 -->
  <listener>
  	<listener-class>
  		org.springframework.web.context.ContextLoaderListener
  	</listener-class>
  </listener>
...
</web-app>
但,一般這樣配置監聽器的話,它會預設去載入/WEB-INF/applicationContext.xml這個spring配置檔案。

如果我們要指定spring配置檔案的名字或載入多個spring xml配置檔案的話,我們需要這樣配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
...
<!-- spring監聽器 -->
  <listener>
  	<listener-class>
  		org.springframework.web.context.ContextLoaderListener
  	</listener-class>
  </listener>
  <!-- 指定監聽器載入指定的spring xml配置檔案 -->
  <context-param>
  	<param-name>contextConfigLocation</param-name>
  	<!-- 分別對應的是資料來源、服務層、持久層、安全 -->
  	<param-value>
  		classpath:conf/dataSource-context.xml
  		classpath:conf/service-context.xml
  		classpath:conf/persistence-context.xml
  		/WEB-INF/wwo-security.xml
  	</param-value>
  </context-param>
...
</web-app>


好了,這樣spring的xml配置檔案就分得很清楚了!

但是,這裡有個問題,就是所有的請求都經過這個監聽器,包括對靜態資源的請求,問題就在這。如果是靜態資源,怎麼辦呢?

顯示我們還要對所謂的靜態資源進行處理,spring為我們提供了<mvc:resources>元素可以處理這個問題,service-context.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:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

	<!-- 對靜態資源的處理 -->
	<mvc:resources 
		location="/JScript/**" 
		mapping="/JScript/" />
</beans>

這樣就對URL包含/JScript/的請求,即對應位於/JScript/下的所以資源來進行特別處理!

4.配置註解驅動的Spring MVC

好了,不多說!現在spring已經大部分能使用註釋來代替從前要在配置檔案裡所做的事,接下來我們大部分會使用註釋方式來完成。

a.定義控制器

DispatcherServlet需要諮詢一個或多個處理器來明確地將請求分發給那個控制器。Spring提供了許多處理器對映實現,那我們只需要DefaultAnnotationHandlerMapping來實現即可。

DefaultAnnotationHandlerMapping:將請求對映給使用@requestMapping註解的控制器和控制器方法。

首先要作用註解,你必需把註解的類及方法等載入到上下文應用中,即spring容器,才能使用!

我們需要在配置檔案中加上以下配置,即可實現註解功能:

<beans>
	...
	<!-- 掃描指定包下的註解 --></span>
	<context:component-scan base-package="com.blog">
		<!-- 配置元件過濾器 -->
		<!-- 指定掃描的包 -->
		<context:include-filter type="annotation" expression="com.blog.controller"/>
		<!-- 指定不需要掃描的包 -->
		<context:exclude-filter type="annotation" expression="com.blog.dao"/>
	</context:component-scan>
	...
</beans>

注:上面只是為了舉例說明

下面配置基本也夠用了,如果不是特別要求:

<beans>
...
<!-- 掃描指定包下的註解 -->
	<context:component-scan base-package="com.blog"/>
...
</beans>
說明:

預設情況下,<context:component-scan>查詢使用構造型註解所標註的類,這些特殊的註解如下:

@Component -- 通用的構造型註解,標識該類為Spring元件;

@Controller -- 標識將該類定義為Spring MVC controller;

@Repository -- 標識將該類定義為資料倉庫;

@Service -- 標識將該類定義為服務;

使用@component標註的任意自定義註解。

一般為好區分某類屬於控制、資料庫訪問和業務層,會分別使用對應的註解@Controller、@Repository和@Service,而儘量少用@Component,@Component是通用的!

接下來我們可以宣告一個登入到主頁面(或首頁)的控制器:

先把 spring mvc切換到3.x版本的jar吧,之前用的是4.x以上的。

這是因為4.x的註解可能與3.x有點差別,而本例子注重的是3.x版本的開發。

切換配置:

<project>
...
<!-- 定義屬性,供${propertieName}訪問 -->
  <properties>
  	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  	<spring.version>3.2.13.RELEASE</spring.version>
  </properties>
...
</project>

b.渲染檢視

--通過上述的控制器去呼叫對應的業務層後,然後要將處理的結果告知使用者時,我們需要對檢視進行渲染,從而顯示在客戶端上即可!

wwo-servlet.xml檔案中配置的程式碼如下:

<!-- 
		原理:邏輯檢視名通過新增字首字尾來確定要檢視路徑
		解析檢視,因jsp檢視使用了jstl標籤,
		所以需要通過設定viewClass屬於來將InternalResourceViewResolver替換為JstlView -->
	
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
		<property name="prefix" value="/"/>
		<property name="suffix" value=".jsp"/>
	</bean>
	
上面是我常用渲染檢視的配置方法,但我們接下講的是通過Apache Tiles佈局管理器來渲染!

Apache Tiles:對於一般的web應用程式,InternalResourceViewResolver檢視基本夠用了。但對於一些複雜的web應用,就應該使用Apache Tiles佈局管理器了,好處是它可以使一些通用的元素(或頁面)被頁面所共享,從而達到元素的重用。

wwo-servlet.xml檔案中配置的程式碼如下:

<!-- 
		Apache Tiles 代替 JstlView
		要是希望一些通用的元素被頁面共享,則可以使用Apache Tiles佈局管理器。
		通過Spring MVC配置解析Tiles的佈局檢視!
		建立檢視解析器:TilesViewResolver;
		載入Tiles的定義:TilesConfigurer;
		由TilesConfigurer載入tiles定義,並使用TilesViewResolver解析檢視。
		views.xml為tiles的定義檔案,它們都分散在/WEB-INF/views/目錄下;
		/WEB-INF/views/**/views.xml:**,查詢/WEB-INF/views/目錄下的所以views.xml檔案
	 -->
	 <bean class="org.springframework.web.servlet.view.tiles2.TilesViewResolver"/>
	 <bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
	 	<property name="definitions">
	 		<list>
	 			<value>/WEB-INF/main-tiles/main-tiles.xml</value>
	 		</list>
	 	</property>
	 </bean>

我們再來看看/WEB-INF/main-tiles/main-titles.xml檔案的配置:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC 
	"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
	"http://tiles.apache.org/dtds/tiles-config_2_1.dtd">

<tiles-definitions>
	<!-- 
		定義通用的佈局
	 -->
	<definition name="template" template="/blog/main/main_template.jsp">
		<put-attribute name="top" value="/blog/main/title.jsp"/>
	</definition>
	<!-- 
		定義main的tiles
	 -->
	<definition name="main" extends="template">
		<put-attribute name="content" value="/blog/main/main.jsp"/>
	</definition>
</tiles-definitions>

注:這裡definition標籤的屬性name是對應控制層,return返回的邏輯檢視名。

再下來,看在main_template.jsp中怎麼來配置使用,來達到重用的目的的。

也就是說,main_template.jsp可以由若干個.jsp頁面組成!

main_template.jsp檔案:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="t" uri="http://tiles.apache.org/tags-tiles" %>
<!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>Insert title here</title>
<style type="text/css">
	body{
		background-color: rgb(95, 2, 2);
	}
</style>
</head>
<body>
	<t:insertAttribute name="top"/>
	<t:insertAttribute name="content"/>
</body>
</html>
好了,我們可以看到要使用tags-tiles的標籤庫來達到目的!

效果:

main_template.jsp顯示的頁面:



title.jsp顯示的頁面:


main.jsp顯示的頁面:


好了,到此Spring MVC構架完成!