欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Matrix - 與 Java 共舞 - 開(kāi)始使用Commons Chain(第二部分)
開(kāi)始使用Commons Chain (第二部分)

開(kāi)始使用Commons Chain (第一部分)


就像我們在第一部分中討論的那樣,Commons Chain提供了一個(gè)基于Java的框架和API來(lái)描述順序的處理過(guò)程?,F在這個(gè)在Javarta Commons項目下開(kāi)發(fā)的框架正在最新的Struts發(fā)布版(在這指的是1.3版本)中接受考驗。在這一部分,我將具體描述Struts如何使用Chain簡(jiǎn)化HTTP請求處理。

Commons Chain允許你定義多組順序的命令。每一組命令(也就是鏈)負責實(shí)現某種處理。鏈中每一個(gè)命令都是一個(gè)實(shí)現了Command接口的Java類(lèi)。這個(gè)接口只包含了一個(gè)execute方法,方法有一個(gè)類(lèi)型是Context的參數。execute方法返回true來(lái)聲明請求的處理已完成,這時(shí)鏈的執行就會(huì )結束。如果返回false,處理將交給下個(gè)命令繼續。

你可以使用Commons Chain的API或者XML文件定義鏈。使用XML文件可以提供最大的靈活性,因為這樣做你可以在部署期修改鏈的定義。下面是我在第一篇文章中使用的鏈定義文件:
<catalog>
  <chain name="sell-vehicle">
    <command   id="GetCustomerInfo"
        className="com.jadecove.chain.sample.GetCustomerInfo"/>
    <command   id="TestDriveVehicle"
        className="com.jadecove.chain.sample.TestDriveVehicle"/>
    <command   id="NegotiateSale"
        className="com.jadecove.chain.sample.NegotiateSale"/>
    <command   id="ArrangeFinancing"
        className="com.jadecove.chain.sample.ArrangeFinancing"/>
    <command   id="CloseSale"
        className="com.jadecove.chain.sample.CloseSale"/>
  </chain>
</catalog>


Struts使用Chain替換了原來(lái)傳統的在RequestProcessor類(lèi)中執行的HTTP請求處理。Struts的ActionServlet通過(guò)struts-config.xml決定使用哪個(gè)RequestProcessor。如果沒(méi)有顯式的指出,ActionServlet將使用org.apache.struts.action.RequestProcessor。他首先得到一個(gè)RequestProcessor的實(shí)例,調用實(shí)例的init方法,然后執行實(shí)例的process方法。

下面是RequestProcessor的init方法:
public void init(ActionServlet servlet,
                 ModuleConfig moduleConfig)
    throws ServletException {

    synchronized (actions) {
         actions.clear();
    }
        
    this.servlet = servlet;
    this.moduleConfig = moduleConfig;
}


沒(méi)有什么不可思議的地方——這個(gè)方法只是簡(jiǎn)單的清除了Action實(shí)例緩存,設置了幾個(gè)實(shí)例變量。RequestProcessor的核心在它的process方法。這個(gè)方法里定義了處理請求和響應的順序算法。
public void process(HttpServletRequest request,
                    HttpServletResponse response)
        throws IOException, ServletException {

    // Wrap multipart requests with a special wrapper
    request = processMultipart(request);

    // Identify the path component we will use to select a mapping
    String path = processPath(request, response);
    if (path == null) {
        return;
    }
        
    // Select a Locale for the current user if requested
    processLocale(request, response);

    // Set the content type and no-caching headers if requested
    processContent(request, response);
    processNoCache(request, response);

    // General purpose preprocessing hook
    if (!processPreprocess(request, response)) {
        return;
    }
        
    this.processCachedMessages(request, response);

    // Identify the mapping for this request
    ActionMapping mapping = processMapping(request, response, path);
    if (mapping == null) {
        return;
    }

    // Check for any role required to perform this action
    if (!processRoles(request, response, mapping)) {
        return;
    }

    // Process any ActionForm bean related to this request
    ActionForm form = processActionForm(request, response, mapping);
    processPopulate(request, response, form, mapping);
    if (!processValidate(request, response, form, mapping)) {
        return;
    }

    // Process a forward or include specified by this mapping
    if (!processForward(request, response, mapping)) {
        return;
    }
        
    if (!processInclude(request, response, mapping)) {
        return;
    }

    // Create or acquire the Action instance to process this request
    Action action = processActionCreate(request, response, mapping);
    if (action == null) {
        return;
    }

    // Call the Action instance itself
    ActionForward forward =
            processActionPerform(request, response,
                                 action, form, mapping);

    // Process the returned ActionForward instance
    processForwardConfig(request, response, forward);

}


這個(gè)處理就是為Commons Chain定制的。(一些Struts的擁護者同時(shí)也是Chain的擁護者決不是巧合。)這個(gè)處理由一串順序的步驟組成,這些步驟是一些名為processFoo的方法。它們的輸入主要由request和response對象組成。其中一些方法會(huì )返回Struts的對象,如ActionMapping和ActionForm。如果這些對象為null就返回false,表示處理無(wú)法繼續;另一些方法直接返回true或false,false用于表示請求已被處理而且無(wú)法繼續執行。

Struts 1.3提供了一個(gè)新的請求處理類(lèi)(ComposableRequestProcessor)來(lái)使用Commons Chain,這個(gè)類(lèi)繼承RequestProcessor,覆蓋了init和process方法。ComposableRequestProcessor的init方法從鏈編目中載入請求處理鏈。默認情況下,這個(gè)編目名是struts,命令名是servlet-standard。
public void init(ActionServlet servlet,
                     ModuleConfig moduleConfig)
           throws ServletException {

    super.init(servlet, moduleConfig);

    ControllerConfig controllerConfig =
        moduleConfig.getControllerConfig();

    String catalogName = controllerConfig.getCatalog();
    catalog = CatalogFactory.getInstance().getCatalog(catalogName);
    if (catalog == null) {
        throw new ServletException("Cannot find catalog ‘" +
                                       catalogName + "‘");
    }

    String commandName = controllerConfig.getCommand();
    command = catalog.getCommand(commandName);
    if (command == null) {
        throw new ServletException("Cannot find command ‘" +
                                       commandName + "‘");
    }
}


為了運行鏈(也就是運行命令)ComposableRequestProcessor覆蓋了process方法:
public void process(HttpServletRequest request,
                        HttpServletResponse response)
        throws IOException, ServletException {

    // Wrap the request in the case of a multipart request
    request = processMultipart(request);
        
    // Create and populate a Context for this request
    ActionContext context = contextInstance(request, response);

    // Create and execute the command.
    try {
        command.execute(context);
    } catch (Exception e) {
        // Execute the exception processing chain??
        throw new ServletException(e);
    }

    // Release the context.
    context.release();
}


處理請求的步驟在一個(gè)名為chain-config.xml的XML文件中定義,這個(gè)文件里定義了一組需要順序執行的命令。(在這processMultipart方法是個(gè)例外。這個(gè)在ComposableRequestProcessor里實(shí)現的方法包裝了內容類(lèi)型是multipart/form-data的請求)。為了了解它是如何工作的,我們來(lái)仔細察看一下chain-config.xml的內容。首先,Struts使用了子鏈,Commons Chain中通過(guò)使用LookupCommand將整個(gè)鏈看成是一個(gè)命令。Struts使用了元素define使基于LookupCommand的子鏈定義更便捷。

<define name= "lookup" className="org.apache.commons.chain.generic.LookupCommand"/>
ComposableRequestProcessor執行了名為servlet-standard的鏈。這個(gè)鏈包含了3個(gè)命令:

servlet-exception        處理異常的Chain過(guò)濾器。過(guò)濾器是一種實(shí)現了postprocess方法的特殊命令。postprocess會(huì )在鏈中命令執行后調用(實(shí)際上是在那些在過(guò)濾器聲明之后的命令執行后調用)。
process-action        處理請求并執行恰當的action的主要流程。
process-view        處理到視圖的轉向(例如JSP頁(yè)面)。

<chain name="servlet-standard">

    <!-- Establish exception handling filter -->
    <command
          className="org.apache.struts.chain.commands.ExceptionCatcher"
        catalogName="struts"
   exceptionCommand="servlet-exception"/>

    <lookup
        catalogName="struts"
               name="process-action"
           optional="false"/>

    <lookup
        catalogName="struts"
               name="process-view"
           optional="false"/>

</chain>


process-action鏈定義了處理請求和調用你自己的action的命令組:
<chain name="process-action">
  <lookup catalogName="struts" name="servlet-standard-preprocess"
             optional="true"/>

  <command className=
    "org.apache.struts.chain.commands.servlet.SelectLocale"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.RequestNoCache"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.SetContentType"
  />        
  <command className=
    "org.apache.struts.chain.commands.servlet.SelectAction"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.AuthorizeAction"
  />    
  <command className=
    "org.apache.struts.chain.commands.servlet.CreateActionForm"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.PopulateActionForm"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.ValidateActionForm"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.SelectInput"
  />
  <command className=
    "org.apache.struts.chain.commands.ExecuteCommand"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.SelectForward"
  />
  <command className=
    "org.apache.struts.chain.commands.SelectInclude"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.PerformInclude"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.CreateAction"
  />
  <command className=
    "org.apache.struts.chain.commands.servlet.ExecuteAction"
  />
</chain>


原始的RequestProcessor中的方法processFoo被實(shí)現了Command接口類(lèi)重寫(xiě)了實(shí)現。在Struts里,每一個(gè)Command的實(shí)現都繼承了一個(gè)抽象的基類(lèi)。這個(gè)基類(lèi)實(shí)現了Command的execute方法。這個(gè)execute方法調用具體的子類(lèi)方法執行實(shí)際的操作。
我們來(lái)考察如何在HTTP請求中存取locale。首先,下面是原始的RequestProcessor中processLocale的實(shí)現:
protected void processLocale(HttpServletRequest request,
                             HttpServletResponse response) {

    // Are we configured to select the Locale automatically?
    if (!moduleConfig.getControllerConfig().getLocale()) {
        return;
    }

    // Has a Locale already been selected?
    HttpSession session = request.getSession();
    if (session.getAttribute(Globals.LOCALE_KEY) != null) {
        return;
    }

    // Use the Locale returned by the servlet container (if any)
    Locale locale = request.getLocale();
    if (locale != null) {
        session.setAttribute(Globals.LOCALE_KEY, locale);
    }
}


新的用鏈處理locale的實(shí)現使用了兩個(gè)類(lèi):AbstractSelectLocale和SelectLocale。抽象類(lèi)AbstractSelectLocale實(shí)現了execute方法:
public boolean execute(Context context) throws Exception {
    ActionContext actionCtx = (ActionContext) context;

    // Are we configured to select Locale automatically?
    ModuleConfig moduleConfig = actionCtx.getModuleConfig();
    if (!moduleConfig.getControllerConfig().getLocale()) {
        return (false);
    }

    // Retrieve and cache appropriate Locale for this request
    Locale locale = getLocale(actionCtx);
    actionCtx.setLocale(locale);

    return (false);
}


SelectLocale繼承了AbstractSelectLocale并實(shí)現了抽象方法getLocale:
protected Locale getLocale(ActionContext context) {

    ServletActionContext saContext = (ServletActionContext) context;

    // Has a Locale already been selected?
    HttpSession session = saContext.getRequest().getSession();
    Locale locale = (Locale) session.getAttribute(Globals.LOCALE_KEY);
    if (locale != null) {
        return (locale);
    }

    // Select and cache the Locale to be used
    locale = saContext.getRequest().getLocale();
    if (locale == null) {
        locale = Locale.getDefault();
    }
    session.setAttribute(Globals.LOCALE_KEY, locale);
    return (locale);

}


抽象類(lèi)和它的實(shí)現類(lèi)都充分使用了接收到的context對象。在Commons Chain里,Context對象作為鏈中的命令的共享存儲空間。與RequestProcessor直接操作HTTP請求和響應不同的是,命令需要做一些額外的工作來(lái)操作他們。上面的抽象命令將context向下轉型成ActionContext類(lèi)型。ActionContext可以顯式地操作Struts相關(guān)屬性,例如消息資源(message resource)、正在執行的Action以及請求(request)和會(huì )話(huà)(session)的資源和服務(wù)。但是,ActionContext并不依賴(lài)Servlet API。命令的具體實(shí)現類(lèi)進(jìn)一步將context向下轉型到ServletActionContext類(lèi)型。ServletActionContext實(shí)現了ActionContext接口,并且包裝了Commons Chain的ServletWebContext。ServletWebContext包含了一些servlet對象,例如HttpServletRequest、HttpServletResponse和ServletContext。

下面的類(lèi)圖展示了Struts是如何使用Chain提供的類(lèi)和接口的:


圖1.

Struts 1.3的開(kāi)發(fā)人員盡力降低了和Servlet API的耦合。通過(guò)構建上面顯示的使用Chain Context的結構,Struts將對Servlet API的依賴(lài)隔離到了最底層:具體的命令實(shí)現類(lèi)。事實(shí)上,你會(huì )發(fā)現Struts的命令遵循了一個(gè)及其一致的模式:
1.        一個(gè)抽象命令實(shí)現了Command的execute方法,它只對ActionContext做處理。
2.        在execute方法中,這個(gè)抽象的基類(lèi)調用一個(gè)自定義的抽象方法完成特定的servlet工作。
3.        具體的子類(lèi)實(shí)現了自定義的抽象方法,將ActionContext向下轉型到ServletActionContext,然后使用HttpServletRequest和HttpSession等執行特殊的工作。
4.        根據抽象方法返回的結果,抽象命令會(huì )返回false(鏈繼續執行)或true(鏈停止執行)。

如果你想自定義ComposableRequestProcessor的行為就需要了解ComposableRequestProcessor和鏈配置。Commons Chain為開(kāi)發(fā)人員提供了多種方法自定義Struts的請求處理。例如,假設你想自定義locale的處理,你可以使用下面任意一種技術(shù):
•        你自己繼承AbstractSelectLocale并實(shí)現getLocale方法。將chain-config.xml中的className改成你自己寫(xiě)的類(lèi)名。
•        自己實(shí)現Command接口,然后替換原來(lái)的類(lèi)。將chain-config.xml中的className改成你自己寫(xiě)的類(lèi)名。
•        最后一種:使用LookupCommand,你可以將處理locale的單一命令替換成一個(gè)子鏈。

如果你曾經(jīng)自定義過(guò)Struts的RequestProcessor,你可能覆蓋過(guò)processPreprocess方法來(lái)執行自定義的請求處理。Struts 1.3通過(guò)Chain來(lái)提供類(lèi)似的處理方法。process-action鏈中第一個(gè)命令的定義如下:
<!-- Look up optional preprocess command -->
<lookup catalogName="struts"
               name="servlet-standard-preprocess"
           optional="true"/>


這個(gè)元素聲明了一個(gè)子鏈作為process-action鏈的第一個(gè)命令。這的optional=true確保子鏈未定義時(shí)父鏈仍能繼續執行。在Jakarta Struts Cookbook中,我展示了如何通過(guò)覆蓋RequestProcessor的processPreprocess方法來(lái)檢查用戶(hù)是否登錄。作為例子,我們來(lái)看在Struts Mail Reader示例應用中如何加入這個(gè)行為。下面這個(gè)命令檢查了User對象是否已綁定到會(huì )話(huà)(session)上。參數checkUser用于指明是否要執行檢查。
package com.jadecove.chain.commands;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.apache.struts.apps.mailreader.Constants;
import org.apache.struts.chain.contexts.ActionContext;
import org.apache.struts.chain.contexts.ServletActionContext;

public class CheckUser implements Command {

  public boolean execute(Context ctx) throws Exception {
    ActionContext context = (ActionContext) ctx;
    Object user = context.getSessionScope().get(Constants.USER_KEY);
    if (user == null &&
        context.getParameterMap().containsKey("checkUser")) {
        HttpServletResponse response =
        ((ServletActionContext) ctx).getResponse();
        response.sendError(403, "User not logged in.");
        return true;
    }
    return false;
  }

}


現在我們需要聲明一個(gè)包含這個(gè)命令的鏈。但是我們把這個(gè)XML加在哪?有兩種方法可以解決這個(gè)問(wèn)題:第一種方法,你可以將這個(gè)鏈加入Struts提供的chain-config.xml文件中。這是最直接的辦法,但是當你更新Struts的時(shí)候,你需要保證在新的配置文件中加入這些修改。另外一個(gè)更好的方法是為你的子鏈單獨創(chuàng )建一個(gè)配置文件,然后告訴Struts將你的鏈定義文件和Struts自帶的一起使用。要使用這個(gè)方法,首先你要在你應用的WEB-INF文件夾下面建立一個(gè)名為costom-chain-config.xml的文件,添加下面的鏈聲明:
<?xml version="1.0" ?>
<catalog name="struts">
    <chain name="servlet-standard-preprocess">
        <command className="com.jadecove.chain.commands.CheckUser"/>
    </chain>
</catalog>


然后你需要修改struts-config.xml文件,讓ActionServlet在載入Struts自己的鏈配置時(shí)載入你的鏈配置文件
<!-- Action Servlet Configuration -->
<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>
      org.apache.struts.action.ActionServlet
    </servlet-class>
    <init-param>
        <param-name>config</param-name>
        <param-value>
            /WEB-INF/struts-config.xml,
            /WEB-INF/struts-config-registration.xml
        </param-value>
    </init-param>
    <init-param>
        <param-name>chainConfig</param-name>
        <param-value>
            /WEB-INF/chain-config.xml,
            /WEB-INF/custom-chain-config.xml
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>


當你訪(fǎng)問(wèn)Mail Reader的歡迎頁(yè)面時(shí),會(huì )顯示圖2所示的頁(yè)面:


圖2.

但是當你加上checkUser參數再次訪(fǎng)問(wèn)時(shí),CheckUser命令終止了鏈的執行并返回它產(chǎn)生的響應,如圖3所示:


圖3.

如果比起創(chuàng )建一個(gè)鏈你更愿意替換命令,那你只需要簡(jiǎn)單地修改chain-config.xml文件。
在我為Struts和Chain加上包裝前,讓我們看一下Struts是如何使用Chain過(guò)濾器處理異常的。Struts定義了一個(gè)捕捉異常的命令作為servlet-standart鏈的第一個(gè)元素:
<!-- Establish exception handling filter -->
<command  className="org.apache.struts.chain.commands.ExceptionCatcher"
        catalogName="struts"
   exceptionCommand="servlet-exception"/>


我們已經(jīng)討論過(guò)命令元素是如何使用屬性的;但在這catalogName和exceptionCommand是兩個(gè)新的屬性。實(shí)際上它們沒(méi)有什么不可思議的地方。它們在Chain中沒(méi)有任何內在的意義。當Commons Chain解析鏈配置時(shí)(使用Commons Digester),任何在Chain中沒(méi)有顯式處理的屬性都使用JavaBean的setter方法處理。換句話(huà)說(shuō),當Chain解析上面的命令時(shí),它會(huì )獲取一個(gè)ExceptionCatcher對象,然后象下面的代碼那樣設置JavaBean的屬性:
exceptionCatcher.setCatalogName("struts");
exceptionCatcher.setExceptionCommand("servlet-exception");


類(lèi)ExceptionCatcher實(shí)現了Filter。實(shí)現Filter的類(lèi)必須實(shí)現下面兩個(gè)方法:
// (From the Command interface) Called when the Filter is first
// processed in sequence
public boolean execute(Context context);

// Called after a chain command throws an exception
// or the chain reaches its end
public boolean postprocess(Context context, Exception exception);


類(lèi)ExceptionCatcher的execute方法只是簡(jiǎn)單的重置了命令,將ActionContext中的當前異常設置成null,然后返回false(告訴鏈繼續執行)。所有有趣的東西都在postprocess方法里。如果這個(gè)方法接收到的異常不是null,它會(huì )通過(guò)catalogName和exceptionCommand找到對應的命令(也可以是一個(gè)鏈)并執行。
public boolean postprocess(Context context, Exception exception) {
    // Do nothing if there was no exception thrown
    if (exception == null) {
        return (false);
    }

    // Store the exception in the context
    ActionContext actionCtx = (ActionContext) context;
    actionCtx.setException(exception);

    // Execute the specified command
    try {
        Command command = lookupExceptionCommand();
        if (command == null) {
            throw new IllegalStateException
                ("Cannot find exceptionCommand ‘" +
                     exceptionCommand + "‘");
        }
        command.execute(context);
    } catch (Exception e) {
        throw new IllegalStateException
           ("Exception chain threw exception");
    }
    return (true);
}


servlet-exception鏈中配置了Struts的異常處理流程:
<!-- ========== Servlet Exception Handler Chain ============= -->    
<chain     name="servlet-exception">
    <!-- Execute the configured exception handler (if any) -->
    <command className=
        "org.apache.struts.chain.commands.servlet.ExceptionHandler"
    />
    <!-- Follow the returned ForwardConfig (if any) -->
    <command className=
        "org.apache.struts.chain.commands.servlet.PerformForward"
    />
</chain>


這個(gè)鏈中使用的類(lèi)完成了和Struts 1.2的錯誤處理類(lèi)同樣的功能。ExceptionHandler是AbstractExceptionHandler的子類(lèi),這里的第一個(gè)命令會(huì )定位已經(jīng)聲明的Struts異常處理程序(如果存在的話(huà))并執行它的execute方法。返回的ActionForward被存儲在A(yíng)ctionContext中由通用的PerformForward命令處理。

我希望我已將Struts如何使用鏈解釋清楚了?,F在Commons Chain和Struts 1.3仍在不斷變化中,所以上面說(shuō)的可能會(huì )有變化。你最好下載最新的Struts的源碼,仔細看看它是如何使用Chain的。我想你會(huì )發(fā)現這樣實(shí)現是經(jīng)過(guò)深思熟慮的;現在為Struts的請求處理加入自定義的行為要比以前更容易,更不受束縛。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Apache Click framework測試報告
解決struts多文件上傳出現的問(wèn)題
J2EE開(kāi)發(fā)之常用開(kāi)源項目介紹
Apache java項目全介紹
Struts ActionForm中自定義轉換器Converter(簡(jiǎn)單易懂)
Java文件上傳與下載【面試+工作】
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久