mvc 架構(gòu)

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            74 Posts :: 60 Stories :: 5 Comments :: 0 Trackbacks
          posted on 2007-09-12 13:57 e全 閱讀(3094) 評論(0)  編輯  收藏

          [1]

          1. 前言

          此文檔講述的內(nèi)容適合于對 Spring MVC 和數(shù)據(jù)持久層 ORM 概念有一定基礎(chǔ)的開發(fā)者,著重于講述基于 Spring 框架基礎(chǔ)之上進行 Java 開發(fā)的其中一種技術(shù)解決方案,而不是講述相關(guān)技術(shù)的原理,想要了解技術(shù)原理內(nèi)容請參考相關(guān)文檔資料。
          ?
            現(xiàn)在,網(wǎng)絡(luò)上流傳的Spring+Struts+Hibernate用得非常火,幾乎成為很多對技術(shù)癡迷的人的技術(shù)架構(gòu)標準,可是在我看來,也許是因為項目都不算大,人力也不夠多,這個技術(shù)架構(gòu)太復雜了。從Spring本身來講,從MVC到數(shù)據(jù)操作,都可以不需要其他附加組件即可實現(xiàn),并且結(jié)構(gòu)清晰,使用簡單,功能還更加強大,本文講述的重點就是單獨使用Spring來建立一個簡易的開發(fā)框架。
          ?
            首先說,為什么選擇Spring呢?大概在2003年的時候,Struts已經(jīng)開始流行了,但是在學習Struts的時候感覺這個技術(shù)框架比原始的JSP+JavaBean的方式復雜了很多,后來2004年做新項目時在論壇上看到推薦Spring,下載一試,上手非常的容易,結(jié)構(gòu)也很清晰,支持的功能也非常多,所以決定用它了(其實那時候?qū)τ谝蕾囎⑷牒?/span>AOP代理還不甚了解,也很少用到接口)。

            在
          2001-2003年的時候都是自己封裝了JavaBean做為公共模塊來訪問數(shù)據(jù)庫的,后來ORM興起了,先是看了Hibernate的,3.0版還沒用出,還不支持存儲過程,因為那時候也做Delphi相關(guān)開發(fā),用慣了SQL語句,始終覺得HQL這樣的東東增加了開發(fā)的復雜度和不可控制性,原生的復雜SQL語句無法使用,不喜歡。后來看到了iBATIS,經(jīng)過試用,正是我所需要的,SQL語句配置簡單,基本不會破壞SQL語句的結(jié)構(gòu),這樣將SQL語句Copy到外部數(shù)據(jù)庫工具中進行調(diào)試也非常的方便,加上SQL語句可以使用很多的特定數(shù)據(jù)庫的函數(shù),執(zhí)行效率和簡潔性也非常好,修改了SQL又不需要重新編譯程序。

            
          有網(wǎng)友說Hibernate支持多個數(shù)據(jù)庫移值啊,我認為這個就不僅僅是SQL語句的問題了,還有很多其他方面的因素,大多數(shù)項目都可以不用考慮。又有網(wǎng)友說Hibernate對于數(shù)據(jù)庫結(jié)構(gòu)修改的影響比較小,這種情況影響的也不僅僅是幾句代碼的問題,涉及到界面表現(xiàn)、業(yè)務流程等很多重要方面,相對說來修改代碼倒是小Case了。


            說完了上面的
          ORM 組件,再說說 JDBC Spring JdbcTemplate 將我們常用的 JDBC 流程封裝起來,使用非常簡單,一般執(zhí)行的 SQL 就是一句話,構(gòu)造 SQL 隨著業(yè)務的復雜而復雜,并且也支持 PrepareStatement 的執(zhí)行模式避免 SQL 注入漏洞發(fā)生,同樣具備完整的數(shù)據(jù)操作功能如查詢、更新、存儲過程、異常捕捉等等,經(jīng)過幾年的使用比較,我認為輕型的項目使用 JdbcTemplate 是非常不錯的選擇。

            由于能力所限,其中細節(jié)如有欠缺之處,請多多批評指正。

          2. 參考資料

          2 ? Spring 官方網(wǎng)站: http://www.springframework.org/

          2 ? Spring 2.0 中文參考手冊: http://spring.jactiongroup.net/

          2 ? Apache Jakarta 官方網(wǎng)站: http://jakarta.apache.org/

          2 ? JSTL 官方網(wǎng)站: http://java.sun.com/products/jsp/jstl/

          2 ? Intellij IDEA 官方網(wǎng)站: http://www.jetbrains.com/

          3. 架構(gòu)概覽

          MVC 層在 Spring AbstractController 類基礎(chǔ)上進行了繼承和重構(gòu),使整個框架僅使用單一的公共控制器,數(shù)據(jù)操作采用 Spring JdbcTemplate ,在邏輯層中直接集成了 Spring Jdbc 能力,可直接操作數(shù)據(jù),表現(xiàn)層 Jstl ,除此之外,未定義任何的表單對象、數(shù)據(jù)庫表映射對象和其他 ORM 的配置文件,在保留對關(guān)鍵功能的集成度的基礎(chǔ)上技術(shù)入門度極低,重點關(guān)注業(yè)務功能和優(yōu)化 SQL 語句

          請求處理流傳如圖所示:



          1)????? 用戶訪問 http://www.fyyk.com/a.do

          2)????? Web 應用服務器(如 tomcat )解析擴展名為 *.do 的請求,通過 Spring 分發(fā)器 org.springframework.web.servlet.DispatcherServlet 讀取 servlet-do.xml 中的配置,將請求轉(zhuǎn)發(fā)給公共控制器類 LogicController.java

          3)????? 公共控制器類 LogicController.java 根據(jù) servlet-do.xml 文件中的配置信息調(diào)用 DoLogicImpl.java 類中相對應名稱的方法;

          4)????? DoLogicImpl.java 類中的方法在處理完成業(yè)務邏輯后,將數(shù)據(jù)內(nèi)容 ModelAndView 返回給公共控制器類 LogicController.java

          5)????? 公共控制器類 LogicController.java 處理 ModelAndView 信息,執(zhí)行 b.jsp 將結(jié)果數(shù)據(jù)顯示出來;

          3.1. 控制器 Controller




            控制器類配置在

          servlet-xxx.xml 文件中,封裝后的 Controller 特點如下:

          1)??? 繼承 AbstractController 類,便于調(diào)用應用環(huán)境的 Web 特性;

          2)?? 只用控制器做請求的轉(zhuǎn)發(fā),業(yè)務實現(xiàn)全部在邏輯層;

          3)????? 采用反映射機制( reflect ),運行期調(diào)用邏輯類中的方法,而請求 URI 、邏輯類和方法名之間的對應關(guān)系只需要在 servlet-xxx.xml 中配置,這樣,控制器實現(xiàn)就只有唯一的一個類文件;

          3.2. 邏輯層 Logic




            邏輯層類在

          applicationContext-xxx.xml 文件配置 Bean 定義中,主要實現(xiàn)兩項功能:一是處理業(yè)務邏輯,二是操作數(shù)據(jù)庫;

          邏輯層類首先需要定義一個接口類,統(tǒng)一以 xxxLogic.java 命名,實現(xiàn)類命名為 xxxLogicImpl.java ,并繼承 JdbcDaoSupport 類,這樣邏輯類便具有了數(shù)據(jù)庫訪問能力。

          邏輯類的方法如果被公共控制器類 LogicController.java 的反映射機制直接調(diào)用,則其接口類需要繼承空的公共接口類 BasicLogic ,定義方法時參數(shù)和返回值是固定的,如果是被其他邏輯類調(diào)用則不需要。

          public ModelAndView initLogin(HttpServletRequest request, HttpServletResponse response, ServletContext servletContext);

          控制器層直接將請求的 request response servletContext 全部傳遞過來交由邏輯層自由控制,對于 request 中的表單數(shù)據(jù),未采用 SimpleFormController 的模式定義表單對象,建議手工獲取,從代碼量本身來將并不復雜,反而更加靈活。在業(yè)務處理完成后,必須構(gòu)造一個 ModelAndView 對象,作為方法返回值回傳給控制器。

          范例代碼如下:

          public class AdminLogicImpl extends JdbcDaoSupport implements AdminLogic

          {

          ?

          public ModelAndView insertUser(HttpServletRequest request, HttpServletResponse response,

          ??? ServletContext servletContext) throws DataAccessException

          ??? {

          ? ???? ??String userId = request.getParameter("userId");

          ? ???? ??String userName = request.getParameter("userName");

          ? ???? ??int age = Integer.parseInt(request.getParameter("age"));

          ? ???? ??double weight = Double.parseDouble(request.getParameter("weight"));

          ?

          ? ???? ??String sqlStr = "insert into testuser (userId,username,age,weight,updatetime) values (?,?,?,?,?)";

          ?? ???? ?Object[] object = new Object[]{userId, userName, age, weight, new Date()};

          ?? ???? ?getJdbcTemplate().update(sqlStr, object);

          ?

          ? ???? ?Map<String, Object> model = new HashMap<String, Object>();

          ?? ???? ?model.put("msg", " 插入用戶成功! ");

          ??? ????model.put("url", "pageForm.user");

          ?? ???? ?String view = "admin/message.jsp";

          ?? ???? ?return new ModelAndView(view, model);

          ??? }

          }

          3.3. 表現(xiàn)層 Jstl

          表現(xiàn)層采用 Jstl taglib 1.2 ,在 *.jsp 頁面中加入 taglib 引用即可使用 Jstl 標簽的大部分功能了,標簽的具體使用方法請參考相關(guān)文檔。

          <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

          <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

          <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>


          4. 開發(fā)準備

          4.1. 開發(fā)工具

          ?? Java 編輯器 Intellij IDEA 6.0.5 Eclipse WTP 3.2

          ?? JDK5.0 Update 11

          ?? Web 服務器 Tomcat 5.5.20

          ?? 數(shù)據(jù)庫 Oracle10g

          4.2. 支撐庫文件

          spring.jar

          spring 2.0.3

          jstl.jar

          standard.jar

          Jstl 1.2

          commons-io-1.3.1.jar

          commons-fileupload-1.2.jar

          文件上傳組件

          commons-logging-1.1.jar

          log4j-1.2.14.jar

          日志組件

          mail.jar

          activation.jar

          郵件組件

          quartz-1.5.2.jar

          時序調(diào)度組件

          aspectjweaver.jar

          AOP 組件

          commons-lang-2.3.jar

          Apache 公共包

          commons-codec-1.3.jar

          commons-collections-3.2.jar

          commons-httpclient-3.0.1.jar

          Httpclient 組件

          4.3. 系統(tǒng)目錄結(jié)構(gòu)

          s004.gif

          ?

          ?

          /

          工程根目錄

          /lib

          工程所用的庫文件目錄

          /src

          源代碼目錄

          /webapp

          站點根目錄

          /webapp/css

          樣式表目錄

          /webapp/images

          圖片目錄

          /webapp/js

          Js 腳本目錄

          /webapp/WEB-INF

          web.xml 等配置文件所在目錄

          /webapp/WEB-INF/classes

          Class 所在目錄

          /webapp/WEB-INF/jsp

          Jsp 文件存放目錄

          /webapp/WEB-INF/lib

          jar 包目錄

          /webapp/WEB-INF/logs

          程序日志目錄

          /webapp/WEB-INF/temp

          臨時文件保存目錄

          4.4. 配置開發(fā)環(huán)境

          4.4.1 設(shè)置字符集

          程序文件全部為 UTF-8 字符集,使用開發(fā)工具建立工程時需要修改工程的默認字符集。


            在
          IDEA 中通過 Ctrl+Alt+S 快捷鍵打開設(shè)置窗口,選擇 IDE Settings 下面的 General 打開通用設(shè)置窗口,修改 File Encoding 下面的 Default encoding UTF-8 ,同時修改 Properties Files 下面的 Default encoding UTF-8


           在
          Eclipse 中點擊菜單 Window-Preferences 打開參數(shù)設(shè)置窗口,選擇左側(cè)樹形節(jié)點 General-Workspace ,修改 Text File Encoding UTF-8


            如果需要使用已經(jīng)存在的源文件,使用
          IDEA 建立同名新文件,然后 copy 原始文件內(nèi)容到新文件中,注意不要直接使用源文件,可能會產(chǎn)生亂碼問題。

          4.4.2 配置數(shù)據(jù)庫驅(qū)動

            由于數(shù)據(jù)庫連接池組件包使用的是 Tomcat 自帶,所以數(shù)據(jù)庫驅(qū)動程序包需要放在 Tomcat 可以訪問的位置, Oracle 驅(qū)動 ojdbc14.jar 文件必須 Copy tomcat/common/lib 這樣的目錄下,而不能放在開發(fā)工具工程 lib 目錄下。

          5. web.xml 配置

          5.1. 基本配置

             web.xml 采用 servlet2.4 規(guī)范,默認配置了會話過期時間和網(wǎng)站首頁文件。

          <?xml version="1.0" encoding="UTF-8"?>

          <web-app id="WebApp_ID" version="2.4"

          ?????? xmlns="http://java.sun.com/xml/ns/j2ee"

          ?????? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

          ?????? xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

          ?

          ??? <!-- 會話的時間 -->

          ? ??<session-config>

          ????????????? <session-timeout>30</session-timeout>

          ?????? </session-config>

          ?

          ?????? <!-- 歡迎頁面 -->

          ?????? <welcome-file-list>

          ????????????? <welcome-file>index.jsp</welcome-file>

          ?????? </welcome-file-list>

          ??????

          </web-app>

          5.2. 加載 spring 監(jiān)聽

             在 web.xml 文件中加入如下配置:

          <!-- 設(shè)置環(huán)境變量,將 web 應用根目錄存儲到環(huán)境變量中 -->

          <context-param>

          ??? <param-name>webAppRootKey</param-name>

          ??? <param-value>webapp.root</param-value>

          </context-param>?

          ?

          <!-- 設(shè)置環(huán)境變量指定 applicationContext.xml 配置文件 -->

          <context-param>

          ??? <param-name>contextConfigLocation</param-name>

          ??? <param-value>

          ??????? /WEB-INF/applicationContext.xml

          ??????? /WEB-INF/applicationContext-admin.xml

          ??????? /WEB-INF/applicationContext-quartz.xml

          ??? </param-value>

          </context-param>???

          ?

          <!-- 設(shè)置 context 的監(jiān)聽,啟動時加載 applicationContext.xml 文件,初始化 applicationContext 實例 -->

          <listener>

          ??? <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

          </listener>

          5.3. Log4j 日志

             首先,在 web.xml 文件中加入如下配置:

          <!-- 設(shè)置環(huán)境變量指定 log4j 的配置文件 -->

          <context-param>

          ??? <param-name>log4jConfigLocation</param-name>

          ??? <param-value>/WEB-INF/log4j.properties</param-value>

          </context-param>

          ?

          <!-- 設(shè)置 log4j 的監(jiān)聽,使日志組件能夠使用,調(diào)用 log4jConfigLocation 中設(shè)置的環(huán)境變量 -->

          <listener>

          ??? <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>

          </listener>

           log4j.properties 文件放在 /WEB-INF/ 目錄下, 文件內(nèi)容如下例,其中根日志級別為 warn ,而在包 cn.idtag 中的類的日志級別為 info

          # 定義根日志的級別和輸出路徑 fatal, error, warn, info, debug

          log4j.rootCategory=warn, stdout, logfile

          ?

          # 在包 cn.idtag 中的類的日志級別

          log4j.logger.cn.idtag=info

          ?

          # 日志輸出參數(shù)

          #%c: 日志信息所在類名

          #%d: 日志信息產(chǎn)生時間

          #%p: 日志信息級別

          #%m: 產(chǎn)生的日志具體信息

          #%n: 輸出日志信息換行

          log4j.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %c%n%m%n%n

          ?

          # 控制臺輸出

          log4j.appender.stdout=org.apache.log4j.ConsoleAppender

          log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

          log4j.appender.stdout.layout.ConversionPattern=${log4j.ConversionPattern}

          ?

          # 日志文件輸出

          log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender

          log4j.appender.logfile.File=${webapp.root}/WEB-INF/logs/log.txt

          log4j.appender.logfile.Append = true

          log4j.appender.logfile.layout=org.apache.log4j.PatternLayout

          log4j.appender.logfile.layout.ConversionPattern=${log4j.ConversionPattern}

          5.4. 解決中文亂碼

           在 web.xml 文件中加入如下配置,可以解決表單提交的編碼,不需要在每個 *.jsp *.htm 等頁面上編寫代碼“ <%@ page contentType="text/html; charset=gbk" language="java"%> ”了,并且為瀏覽器端設(shè)置的“ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> ”代碼也不需要寫了,瀏覽器會自動識別,注意建立文件時一定要使用 UTF-8 字符集。

          <!-- 設(shè)置字符串過濾器,解決表單 Post 提交中的亂碼問題 -->

          <filter>

          ??? <filter-name>characterEncoding</filter-name>

          ??? <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

          ??? <init-param>

          ?? ?????<param-name>encoding</param-name>

          ??????? <param-value>utf-8</param-value>

          ??? </init-param>

          ??? <init-param>

          ??????? <param-name>forceEncoding</param-name>

          ??????? <param-value>true</param-value>

          ??? </init-param>

          </filter>

          <filter-mapping>

          ??? <filter-name>characterEncoding</filter-name>

          ??? <url-pattern>/*</url-pattern>

          </filter-mapping>

          ?

          <!-- 設(shè)置 jsp,htm,html 頁面的字符集,是否使用標簽,是否使用 jsp 腳本等,頭尾載入頁面等 -->

          <jsp-config>

          ??? <jsp-property-group>

          ??????? <description> 指定 JSP 文件的配置屬性 </description>

          ??????? <display-name>jspConfiguration</display-name>

          ??????? <url-pattern>*.jsp</url-pattern>

          ??????? <el-ignored>false</el-ignored>

          ??????? <page-encoding>utf-8</page-encoding>

          ??????? <scripting-invalid>false</scripting-invalid>

          ??????? <include-prelude></include-prelude>

          ??????? <include-coda></include-coda>

          ??? </jsp-property-group>

          ?

          ??? <jsp-property-group>

          ??????? <description> 指定 htm 文件的配置屬性 </description>

          ??????? <display-name>jspConfiguration</display-name>

          ??????? <url-pattern>*.htm</url-pattern>

          ??????? <el-ignored>false</el-ignored>

          ??????? <page-encoding>utf-8</page-encoding>

          ??????? <scripting-invalid>false</scripting-invalid>

          ??????? <include-prelude></include-prelude>

          ??????? <include-coda></include-coda>

          ??? </jsp-property-group>

          ?

          ??? <jsp-property-group>

          ??????? <description> 指定 html 文件的配置屬性 </description>

          ??????? <display-name>jspConfiguration</display-name>

          ??????? <url-pattern>*.html</url-pattern>

          ??????? <el-ignored>false</el-ignored>

          ??????? <page-encoding>utf-8</page-encoding>

          ??????? <scripting-invalid>false</scripting-invalid>

          ??????? <include-prelude></include-prelude>

          ??????? <include-coda></include-coda>

          ??? </jsp-property-group>

          ?

          </jsp-config>

           如果應用服務器是 Tomcat ,編輯 Tomcat 根目錄下的“ /conf/server.xml ”文件,找到 Connector 配置部分,在配置結(jié)尾加入“ URIEncoding="utf-8" ”:

          <Connector port="8080" maxThreads="150" …… disableUploadTimeout="true"/>

          改為:

          <Connector port="8080" maxThreads="150" …… disableUploadTimeout="true" URIEncoding="UTF-8"/>

           可解決系統(tǒng)內(nèi)部 GET 方法傳遞中文字符參數(shù)的亂碼問題,但是在外部 URL 請求中參數(shù)值帶有中文的,必須使用 URLEncode 編碼。

          5.5. 配置 servlet

           在 web.xml 文件中配置 servlet 請求路徑和實現(xiàn)類:

          <servlet>

          ??? <servlet-name>sendSms</servlet-name>

          ??? <servlet-class>cn.idtag.test.servlet.SendSmsServlet</servlet-class>

          </servlet>

          <servlet-mapping>

          ??? <servlet-name>sendSms</servlet-name>

          ??? <url-pattern>/servlet/sendsms</url-pattern>

          </servlet-mapping>

           而 SendSmsServlet.java 文件需要繼承 HttpServlet 類,如果 response 要輸出內(nèi)容并包含非英文字符,要設(shè)置輸出的字符集為 UTF-8

          package cn.idtag.test.servlet;

          ?

          import javax.servlet.http.HttpServletRequest;

          import javax.servlet.http.HttpServletResponse;

          import javax.servlet.http.HttpServlet;

          import javax.servlet.ServletException;

          import java.io.IOException;

          ?

          public class SendSmsServlet extends HttpServlet

          {

          ??? public void doGet(HttpServletRequest request, HttpServletResponse response)

          ??????????? throws ServletException, IOException

          {

          ??????? response.setContentType("text/html;charset=utf-8");

          ??????? PrintWriter out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), "utf-8"));

          ??????? try

          ??????? {

          ??????? //do something…

          ??????? } finally

          ??????? {

          ??????????? out.close();

          ??????? }

          ??? }

          ?

          ??? public void doPost(HttpServletRequest request, HttpServletResponse response)

          ??????????? throws ServletException, IOException

          ?? ?{

          ??????? doGet(request, response);

          ??? }

          }


          6. Spring 配置

          6.1. 視圖配置

          配置 Spring 環(huán)境公共設(shè)置的 applicationContext.xml 文件放在 /WEB-INF/ 目錄下, 首先定義視圖類型為 Jstl ,并約定 JSP 文件的默認保存路徑,配置異常捕獲處理 Bean ,當系統(tǒng)發(fā)生異常時,自動重新定向到 error.jsp 文件顯示異常內(nèi)容。

          <?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:tx="http://www.springframework.org/schema/tx"

          ?????? xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

          ?????????? http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd

          ?????????? http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

          ?

          ??? <!-- 返回的視圖資源的前綴和后綴,基于 Jstl 模板 -->

          ??? <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">

          ??????? <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>

          ?????? ?<property name="prefix" value="/WEB-INF/jsp/"/>

          ??? </bean>

          ?

          ??? <!-- 啟動加載異常處理的類,用于監(jiān)聽各模塊中觸發(fā)的異常 -->

          ??? <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

          ??????? <property name="defaultErrorView" value="error.jsp"/>

          ??? </bean>

          </beans>

          6.2. 數(shù)據(jù)庫連接

          applicationContext.xml 文件中加入下面配置,首先加載數(shù)據(jù)庫配置文件 jdbc.properties ,然后配置數(shù)據(jù)源,此處使用的是 TOMCAT 自帶的數(shù)據(jù)庫連接池實現(xiàn),其實就是 Apache DBCP 連接池的重新封裝。

          <!-- 加載 properties 配置文件 -->

          <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

          ??? <property name="locations">

          ??????? <list>

          ??????????? <value>/WEB-INF/jdbc.properties</value>

          ??????? </list>

          ??? </property>

          </bean>

          ?

          <!-- 數(shù)據(jù)源 -->

          <bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" destroy-method="close">

          ??? <property name="driverClassName" value="${jdbc.driverClassName}"/>

          ??? <property name="url" value="${jdbc.url}"/>

          ??? <property name="username" value="${jdbc.username}"/>

          ??? <property name="password" value="${jdbc.password}"/>

          </bean>

            jdbc.properties 文件在 /WEB-INF/ 目錄下:

          jdbc.driverClassName=oracle.jdbc.OracleDriver

          jdbc.url=jdbc:oracle:thin:@localhost:1521:oradb

          jdbc.username=demo

          jdbc.password=123456

          6.3. 數(shù)據(jù)庫事務

          applicationContext.xml 文件中加入下面配置,數(shù)據(jù)庫事務管理,采用的是 AOP 代理,對所有文件名稱以 Logic 結(jié)尾的接口類進行事務代理。在接口類中,方法名稱以 insert update 等開頭的采用事務管理,設(shè)置 Propagation REQUIRED 表示支持當前事務,如果當前沒有事務,就新建一個事務;而其他的方法以 * 表示,設(shè)置 Propagation SUPPORTS 表示支持當前事務,如果當前沒有事務就以非事務方式執(zhí)行, read-Only true 表示對應事務被最優(yōu)化為只讀事務。

          <!-- 事務管理器 -->

          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

          ??? <property name="dataSource" ref="dataSource"/>

          </bean>

          ?

          <!--aop 代理,對所有以 Logic 為后綴文件名的接口類進行代理 -->

          <aop:config>

          ??? <aop:advisor pointcut="execution(* *..*Logic.*(..))" advice-ref="txAdvice"/>

          </aop:config>

          ?

          <!-- 數(shù)據(jù)庫事務代理,對類中的指定前綴的方法進行事務控制 -->

          <tx:advice id="txAdvice">

          ??? <tx:attributes>

          ??????? <tx:method name="insert*" propagation="REQUIRED"/>

          ??????? <tx:method name="update*" propagation="REQUIRED"/>

          ??????? <tx:method name="delete*" propagation="REQUIRED"/>

          ??????? <tx:method name="upload*" propagation="REQUIRED"/>

          ??????? <tx:method name="*" propagation="SUPPORTS" read-only="true"/>

          ??? </tx:attributes>

          </tx:advice>


          pointcut 的語法說明如下:

          execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)

          ?? 除了返回類型模式、名字模式和參數(shù)模式以外,所有的部分都是可選的;

          ?? 返回類型模式( ret-type-pattern )決定了方法的返回類型必須依次匹配一個連接點,返回類型模式 * 代表了匹配任意的返回類型;

          ?? 名字模式( name-pattern )匹配的是方法名,可以使用 * 通配符作為所有或者部分命名模式;

          ?? 參數(shù)模式( param-pattern )稍微有點復雜, () 匹配了一個不接受任何參數(shù)的方法,而 (..) 匹配了一個接受任意數(shù)量參數(shù)的方法(零或者更多),模式 (*) 匹配了一個接受一個任何類型的參數(shù)的方法,模式 (*,String) 匹配了一個接受兩個參數(shù)的方法,第一個可以是任意類型,第二個則必須是 String 類型。

          ?

          下面給出一些常見切入點表達式的例子。

          ?? 任意公共方法的執(zhí)行: execution(public * *(..))

          ?? 任何一個以“ set ”開始的方法的執(zhí)行: execution(* set*(..))

          ?? AccountService 接口的任意方法的執(zhí)行: execution(* com.xyz.service.AccountService.*(..))

          ?? 定義在 service 包里的任意方法的執(zhí)行: execution(* com.xyz.service.*.*(..))

          ?? 定義在 service 包或者子包里的任意方法的執(zhí)行: execution(* com.xyz.service..*.*(..))

          ?

          表達式 execution(* *..BookManager.save(..)) 的解讀:

          ?? 第一顆 * 代表 ret-type-pattern 返回值可任意;

          ?? *..BookManager 代表任意 Pacakge 里的 BookManager 類,如果寫成 com.xyz.service.* 則代表 com.xyz.service 下的任意類, com.xyz.service..* com.xyz.service 則代表 com.xyz.service 及其子 package 下的任意類;

          ?? save 代表 save 方法,也可以寫 save* 代表 saveBook() 等方法;

          ?? (..) 匹配 0 個參數(shù)或者多個參數(shù)的,任意類型, (x,..) 第一個參數(shù)的類型必須是 X (x,,,s,..) 匹配至少 4 個參數(shù),第一個參數(shù)必須是 x 類型,第二個和第三個參數(shù)可以任意,第四個必須是 s 類型。

          6.4. 控制器配置

          控制器的配置文件為 servlet-xxx.xml xxx URI 請求的擴展名,此文件可以在 web.xml 中配置,如果不配置, spring 默認查找的是 xxx-servlet.xml 文件,前后調(diào)轉(zhuǎn)一下可方便很多的同類文件排序查看:

          <?xml version="1.0" encoding="UTF-8"?>

          <beans xmlns="http://www.springframework.org/schema/beans"

          ?????? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

          ?????? xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

          ?

          ??? <import resource="applicationContext.xml"/>

          ?

          ??? <bean id="defaultHandlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

          ?

          ??? <bean name="/mainpage.do" class="org.springframework.web.servlet.mvc.ParameterizableViewController">

          ??????? <property name="viewName" value="mainpage.jsp"/>

          ??? </bean>

          ?

          ??? <!-- 無攔截請求 -->

          ??? <bean id="noInterceptors" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

          ??????? <property name="mappings">

          ??????????? <props>

          ??????????????? <prop key="login.do">doController</prop>

          ??????????? </props>

          ??????? </property>

          ??? </bean>

          ?

          ??? <!-- 有攔截請求 -->

          ??? <bean id="hasInterceptors" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

          ??????? <property name="interceptors">

          ??????????? <list>

          ??????????????? <ref bean="authInterceptor"/>

          ??????????? </list>

          ??????? </property>

          ??????? <property name="mappings">

          ??????????? <props>

          ??????????????? <prop key="enter.do">doController</prop>

          ??????????????? <prop key="logout.do">doController</prop>

          ??????????? </props>

          ??????? </property>

          ??? </bean>

          ?

          ??? <!-- 請求與方法映射控制器 -->

          ??? <bean id="doController" class="com.fyyk.core.LogicController">

          ??????? <property name="logicClass" ref="doLogic"/>

          ??????? <property name="uriMethodMapping">

          ??????????? <props>

          ??????????????? <prop key="login">login</prop>

          ??????????????? <prop key="enter">enter</prop>

          ??????????????? <prop key="logout">logout</prop>

          ??????????? </props>

          ??????? </property>

          ??? </bean>

          ?

          </beans>

          6.5. 邏輯類配置

          邏輯類的配置文件為 applicationContext-xxx.xml ,此文件可以在 web.xml 中配置,如 applicationContext-admin.xml 文件,也可以配置合并在 applicationContext.xml 中:

          ??? <bean id="authInterceptor" class="com.fyyk.interceptor.AuthInterceptor">

          ??????? <property name="noLoginRedirect" value="/WEB-INF/jsp/noLogin.jsp"/>

          ??? </bean>

          ?

          ??? <bean id="doLogic" class="com.fyyk.logic.DoLogicImpl">

          ??????? <property name="dataSource" ref="dataSource"/>

          ??? </bean>

          7. 開發(fā)工作要做什么

          一般說來,完成一個操作流程的全部開發(fā)需要完成以下工作:


          1.??
          配置 servlet-xxx.xml 文件,加入 URI 請求的控制器 Bean 、邏輯類及方法;


          2.??
          配置 applicaionContext-xxx.xml 文件,加入響應 URI 請求的邏輯類 Bean 定義;


          3.??
          建立邏輯類文件接口類文件,加入響應 URI 請求的方法,并實現(xiàn)該類和方法,在方法體中完成具體的業(yè)務代碼,如果需要操作數(shù)據(jù)庫,則實現(xiàn)類需要繼承 JdbcDaoSupport 類;


          4.??
          建立 .jsp 文件,輸出請求結(jié)果;



            點此下載演示代碼


            接下來會有一些應用范例程序介紹給大家。


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           
          主站蜘蛛池模板: 凤台县| 喜德县| 新民市| 黔江区| 灵寿县| 黑龙江省| 玉门市| 黄龙县| 介休市| 临沭县| 榆树市| 栾城县| 锦屏县| 浏阳市| 城市| 清镇市| 延吉市| 柞水县| 青神县| 泰和县| 晋中市| 射阳县| 百色市| 会宁县| 宝应县| 溧水县| 壤塘县| 湟中县| 玛纳斯县| 沙河市| 巩留县| 永嘉县| 当涂县| 泰兴市| 获嘉县| 泸溪县| 永修县| 西峡县| 辽宁省| 大名县| 隆昌县|