<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    mvc 架構(gòu)

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

    [1]

    1. 前言

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

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

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


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

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

    2. 參考資料

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

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

    請(qǐng)求處理流傳如圖所示:



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

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

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

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

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

    3.1. 控制器 Controller




      控制器類配置在

    servlet-xxx.xml 文件中,封裝后的 Controller 特點(diǎn)如下:

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

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

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

    3.2. 邏輯層 Logic




      邏輯層類在

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

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

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

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

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

    范例代碼如下:

    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 標(biāo)簽的大部分功能了,標(biāo)簽的具體使用方法請(qǐng)參考相關(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ā)準(zhǔn)備

    4.1. 開發(fā)工具

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

    ?? JDK5.0 Update 11

    ?? Web 服務(wù)器 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

    時(shí)序調(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

    站點(diǎn)根目錄

    /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

    臨時(shí)文件保存目錄

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

    4.4.1 設(shè)置字符集

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


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


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


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

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

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

    5. web.xml 配置

    5.1. 基本配置

       web.xml 采用 servlet2.4 規(guī)范,默認(rèn)配置了會(huì)話過期時(shí)間和網(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">

    ?

    ??? <!-- 會(huì)話的時(shí)間 -->

    ? ??<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 應(yīng)用根目錄存儲(chǔ)到環(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)聽,啟動(dòng)時(shí)加載 applicationContext.xml 文件,初始化 applicationContext 實(shí)例 -->

    <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)容如下例,其中根日志級(jí)別為 warn ,而在包 cn.idtag 中的類的日志級(jí)別為 info

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

    log4j.rootCategory=warn, stdout, logfile

    ?

    # 在包 cn.idtag 中的類的日志級(jí)別

    log4j.logger.cn.idtag=info

    ?

    # 日志輸出參數(shù)

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

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

    #%p: 日志信息級(jí)別

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

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

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

    ?

    # 控制臺(tái)輸出

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

     如果應(yīng)用服務(wù)器是 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 請(qǐng)求中參數(shù)值帶有中文的,必須使用 URLEncode 編碼。

    5.5. 配置 servlet

     在 web.xml 文件中配置 servlet 請(qǐng)求路徑和實(shí)現(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 文件的默認(rèn)保存路徑,配置異常捕獲處理 Bean ,當(dāng)系統(tǒng)發(fā)生異常時(shí),自動(dòng)重新定向到 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>

    ?

    ??? <!-- 啟動(dòng)加載異常處理的類,用于監(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ù)庫連接池實(shí)現(xiàn),其實(shí)就是 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ù)庫事務(wù)

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

    <!-- 事務(wù)管理器 -->

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

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

    </bean>

    ?

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

    <aop:config>

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

    </aop:config>

    ?

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

    <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 )決定了方法的返回類型必須依次匹配一個(gè)連接點(diǎn),返回類型模式 * 代表了匹配任意的返回類型;

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

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

    ?

    下面給出一些常見切入點(diǎn)表達(dá)式的例子。

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

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

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

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

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

    ?

    表達(dá)式 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 個(gè)參數(shù)或者多個(gè)參數(shù)的,任意類型, (x,..) 第一個(gè)參數(shù)的類型必須是 X (x,,,s,..) 匹配至少 4 個(gè)參數(shù),第一個(gè)參數(shù)必須是 x 類型,第二個(gè)和第三個(gè)參數(shù)可以任意,第四個(gè)必須是 s 類型。

    6.4. 控制器配置

    控制器的配置文件為 servlet-xxx.xml xxx URI 請(qǐng)求的擴(kuò)展名,此文件可以在 web.xml 中配置,如果不配置, spring 默認(rèn)查找的是 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>

    ?

    ??? <!-- 無攔截請(qǐng)求 -->

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

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

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

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

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

    ??????? </property>

    ??? </bean>

    ?

    ??? <!-- 有攔截請(qǐng)求 -->

    ??? <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>

    ?

    ??? <!-- 請(qǐng)求與方法映射控制器 -->

    ??? <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ā)工作要做什么

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


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


    2.??
    配置 applicaionContext-xxx.xml 文件,加入響應(yīng) URI 請(qǐng)求的邏輯類 Bean 定義;


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


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



      點(diǎn)此下載演示代碼


      接下來會(huì)有一些應(yīng)用范例程序介紹給大家。


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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: AV在线亚洲男人的天堂| 国产特黄特色的大片观看免费视频| 国产桃色在线成免费视频 | 夭天干天天做天天免费看| 亚洲av无码电影网| 手机在线看永久av片免费| 亚洲avav天堂av在线网爱情| 国产a视频精品免费观看| 亚洲午夜一区二区电影院| 在线永久免费的视频草莓| 亚洲一区二区三区深夜天堂| 日本亚洲免费无线码| 波多野结衣亚洲一级| 免费羞羞视频网站| 久久精品国产亚洲av瑜伽| 又黄又爽一线毛片免费观看| 一区二区在线视频免费观看| 国产中文在线亚洲精品官网| 国产无遮挡色视频免费观看性色| 亚洲精品午夜国产VA久久成人| 免费国产99久久久香蕉| 亚洲视频在线观看| 99爱在线精品免费观看| 亚洲另类无码专区丝袜| 四虎影视免费永久在线观看| 有码人妻在线免费看片| 国产亚洲精品岁国产微拍精品| 久久免费视频精品| 亚洲国产精品综合久久2007| 成年在线网站免费观看无广告| 久久亚洲色WWW成人欧美| 亚洲国产综合精品一区在线播放| 本免费AV无码专区一区| 亚洲日韩图片专区第1页| 最近免费中文字幕大全视频| 精品亚洲视频在线| 亚洲午夜久久久久妓女影院| 亚洲成人免费在线| 亚洲精品国产国语| 亚洲成av人片天堂网老年人| 中文字幕日本人妻久久久免费|