超碰91资源站-超碰97豆花-超碰97人妻-超碰97人人干-超碰97人人香蕉-超碰97天天操-超碰97在线资源站-超碰97资源站共享-超碰97资源站总站-超碰aa在线91-超碰av操-超碰爱爱

半岛外围网上直营

Result機(jī)制——豐富您的視圖

轉(zhuǎn)帖|其它|編輯:郝浩|2009-02-09 10:59:33.000|閱讀 1238 次

概述:Result機(jī)制——豐富您的視圖

# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>

  Struts2將Result列為一個(gè)獨(dú)立的層次,可以說是整個(gè)Struts2的Action層架構(gòu)設(shè)計(jì)中的另外一個(gè)精華所在。Result之所以成為一個(gè)層次,其實(shí)是為了解決MVC框架中,如何從Control層轉(zhuǎn)向View層這樣一個(gè)問題而存在的。所以,接下來我們詳細(xì)討論一下Result的方方面面。

  Result的職責(zé) 

  Result作為一個(gè)獨(dú)立的層次存在,必然有其存在的價(jià)值,它也必須完成它所在的層次的職責(zé)。Result是為了解決如何從Control層轉(zhuǎn)向View層這樣一個(gè)問題而存在的,那么Result最大的職責(zé),就是架起Action到View的橋梁。具體來說,我把這些職責(zé)大概分成以下幾個(gè)方面:

  封裝跳轉(zhuǎn)邏輯

  Result的首要職責(zé),是封裝Action層到View層的跳轉(zhuǎn)邏輯。之前我們已經(jīng)反復(fù)提到,Struts2的Action是一個(gè)與Web容器無關(guān)的POJO。所以,在Action執(zhí)行完畢之后,框架需要把代碼的執(zhí)行權(quán)重新交還給Web容器,并轉(zhuǎn)向到相應(yīng)的頁面或者其他類型的View層。而這個(gè)跳轉(zhuǎn)邏輯,就由Result來完成。這樣,好處也是顯而易見的,對Action屏蔽任何Web容器的相關(guān)信息,使得每個(gè)層次更加清晰。

  View層的顯示類型非常多,有最常見的JSP、當(dāng)下非常流行的Freemarker/Velocity模板、Redirect到一個(gè)新的地址、文本流、圖片流、甚至是JSON對象等等。所以Result層的獨(dú)立存在,就能夠?qū)@些顯示類型進(jìn)行區(qū)分,并封裝合理的跳轉(zhuǎn)邏輯。

  以JSP轉(zhuǎn)向?yàn)槔赟truts2自帶的ServletDispatcherResult中就存在著核心的JSP跳轉(zhuǎn)邏輯:

Java代碼
HttpServletRequest request = ServletActionContext.getRequest();  
RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);  
 
....  
 
dispatcher.forward(request, response); 

HttpServletRequest request = ServletActionContext.getRequest();
 RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);

....

dispatcher.forward(request, response);

  再以Redirect重定向?yàn)槔?,在Struts2自帶的ServletRedirectResult中,也同樣存在著重定向的核心代碼:

Java代碼
HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);  
 
....  
 
response.sendRedirect(finalLocation); 

HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);

....

response.sendRedirect(finalLocation);

  由此可見,絕大多數(shù)的Result,都封裝了與Web容器相關(guān)的跳轉(zhuǎn)邏輯,由于這些邏輯往往需要和Servlet對象打交道,所以,遵循Struts2的基本原則,將它作為一個(gè)獨(dú)立的層次,從而將Action從Web容器中解放出來。

  準(zhǔn)備顯示數(shù)據(jù)

  之前提到,View層的展現(xiàn)方式很多,除了傳統(tǒng)的JSP以外,還有類似Freemarker/Velocity這樣的模板。根據(jù)模板顯示的基本原理,需要將預(yù)先定義好的模板(Template)和需要展示的數(shù)據(jù)(Model)組織起來,交給模板引擎,才能夠正確顯示。而這部分工作,就由Result層來完成。

  以Struts2自帶的FreemarkerResult為例,在Result中,就存在著為模板準(zhǔn)備數(shù)據(jù)的邏輯代碼:

Java代碼
protected TemplateModel createModel() throws TemplateModelException {  
    ServletContext servletContext = ServletActionContext.getServletContext();  
    HttpServletRequest request = ServletActionContext.getRequest();  
    HttpServletResponse response = ServletActionContext.getResponse();  
    ValueStack stack = ServletActionContext.getContext().getValueStack();  
 
    Object action = null;  
    if(invocation!= null ) action = invocation.getAction(); //Added for NullPointException  
    return freemarkerManager.buildTemplateModel(stack, action, servletContext, request, response, wrapper);  

protected TemplateModel createModel() throws TemplateModelException {
    ServletContext servletContext = ServletActionContext.getServletContext();
    HttpServletRequest request = ServletActionContext.getRequest();
    HttpServletResponse response = ServletActionContext.getResponse();
     ValueStack stack = ServletActionContext.getContext().getValueStack();

    Object action = null;
    if(invocation!= null ) action = invocation.getAction(); //Added for NullPointException
    return freemarkerManager.buildTemplateModel(stack, action, servletContext, request, response, wrapper);
}

  有興趣的讀者可以順著思路去看源碼,看看這些Result到底是如何獲取各種對象的值的。

  控制輸出行為

  有的時(shí)候,針對同一種類型的View展示,我們可能會有不同的輸出行為。具體來說,可能有時(shí)候,我們需要對輸出流指定特定的BufferSize、Encoding等等。Result層,作為一個(gè)獨(dú)立的層次,可以提供極大的擴(kuò)展性,從而保證我們能夠定義自己期望的輸出類型。

  以Struts2自帶的HttpHeaderResult為例:

Java代碼
public void execute(ActionInvocation invocation) throws Exception {  
    HttpServletResponse response = ServletActionContext.getResponse();  
 
    if (status != -1) {  
        response.setStatus(status);  
    }  
 
    if (headers != null) {  
        ValueStack stack = ActionContext.getContext().getValueStack();  
 
        for (Iterator iterator = headers.entrySet().iterator();  
             iterator.hasNext();) {  
            Map.Entry entry = (Map.Entry) iterator.next();  
            String value = (String) entry.getValue();  
            String finalValue = parse ? TextParseUtil.translateVariables(value, stack) : value;  
            response.addHeader((String) entry.getKey(), finalValue);  
        }  
    }  

public void execute(ActionInvocation invocation) throws Exception {
     HttpServletResponse response = ServletActionContext.getResponse();

    if (status != -1) {
        response.setStatus(status);
    }

    if (headers != null) {
         ValueStack stack = ActionContext.getContext().getValueStack();

        for (Iterator iterator = headers.entrySet().iterator();
             iterator.hasNext();) {
            Map.Entry entry = (Map.Entry) iterator.next();
            String value = (String) entry.getValue();
            String finalValue = parse ? TextParseUtil.translateVariables(value, stack) : value;
            response.addHeader((String) entry.getKey(), finalValue);
        }
    }
}

  我們可以在這里添加我們自定義的內(nèi)容到HttpHeader中去,從而控制Http的輸出。 [SPAN]

  Result的定義 

  讓我們來看看Result的接口定義:

Java代碼
public interface Result extends Serializable {  
 
    /** 
     * Represents a generic interface for all action execution results, whether that be displaying a webpage, generating 
     * an email, sending a JMS message, etc. 
     */ 
    public void execute(ActionInvocation invocation) throws Exception;  

public interface Result extends Serializable {

    /**
     * Represents a generic interface for all action execution results, whether that be displaying a webpage, generating
     * an email, sending a JMS message, etc.
     */
    public void execute(ActionInvocation invocation) throws Exception;
}

  這個(gè)接口定義非常簡單,通過傳入ActionInvocation,執(zhí)行一段邏輯。我們來看看Struts2針對這個(gè)接口實(shí)現(xiàn)的一個(gè)抽象類,它規(guī)定了許多默認(rèn)實(shí)現(xiàn):

Java代碼
public abstract class StrutsResultSupport implements Result, StrutsStatics {  
 
    private static final Log _log = LogFactory.getLog(StrutsResultSupport.class);  
 
    /** The default parameter */ 
    public static final String DEFAULT_PARAM = "location";  
 
    private boolean parse;  
    private boolean encode;  
    private String location;  
    private String lastFinalLocation;  
 
    public StrutsResultSupport() {  
        this(null, true, false);  
    }  
 
    public StrutsResultSupport(String location) {  
        this(location, true, false);  
    }  
 
    public StrutsResultSupport(String location, boolean parse, boolean encode) {  
        this.location = location;  
        this.parse = parse;  
        this.encode = encode;  
    }  
 
    // setter method 省略  
   
    /** 
     * Implementation of the <tt>execute</tt> method from the <tt>Result</tt> interface. This will call 
     * the abstract method {@link #doExecute(String, ActionInvocation)} after optionally evaluating the 
     * location as an OGNL evaluation. 
     * 
     * @param invocation the execution state of the action. 
     * @throws Exception if an error occurs while executing the result. 
     */ 
    public void execute(ActionInvocation invocation) throws Exception {  
        lastFinalLocation = conditionalParse(location, invocation);  
        doExecute(lastFinalLocation, invocation);  
    }  
 
    /** 
     * Parses the parameter for OGNL expressions against the valuestack 
     * 
     * @param param The parameter value 
     * @param invocation The action invocation instance 
     * @return The resulting string 
     */ 
    protected String conditionalParse(String param, ActionInvocation invocation) {  
        if (parse && param != null && invocation != null) {  
            return TextParseUtil.translateVariables(param, invocation.getStack(),  
                    new TextParseUtil.ParsedValueEvaluator() {  
                        public Object evaluate(Object parsedValue) {  
                            if (encode) {  
                                if (parsedValue != null) {  
                                    try {  
                                        // use UTF-8 as this is the recommended encoding by W3C to  
                                        // avoid incompatibilities.  
                                        return URLEncoder.encode(parsedValue.toString(), "UTF-8");  
                                    }  
                                    catch(UnsupportedEncodingException e) {  
                                        _log.warn("error while trying to encode ["+parsedValue+"]", e);  
                                    }  
                                }  
                            }  
                            return parsedValue;  
                        }  
            });  
        } else {  
            return param;  
        }  
    }  
 
    /** 
     * Executes the result given a final location (jsp page, action, etc) and the action invocation 
     * (the state in which the action was executed). Subclasses must implement this class to handle 
     * custom logic for result handling. 
     * 
     * @param finalLocation the location (jsp page, action, etc) to go to. 
     * @param invocation    the execution state of the action. 
     * @throws Exception if an error occurs while executing the result. 
     */ 
    protected abstract void doExecute(String finalLocation, ActionInvocation invocation) throws Exception;  

public abstract class StrutsResultSupport implements Result, StrutsStatics {

    private static final Log _log = LogFactory.getLog(StrutsResultSupport.class);

    /** The default parameter */
     public static final String DEFAULT_PARAM = "location";

    private boolean parse;
    private boolean encode;
    private String location;
     private String lastFinalLocation;

    public StrutsResultSupport() {
        this(null, true, false);
    }

    public StrutsResultSupport(String location) {
        this(location, true, false);
    }

    public StrutsResultSupport(String location, boolean parse, boolean encode) {
        this.location = location;
        this.parse = parse;
        this.encode = encode;
    }

    // setter method 省略
 
    /**
     * Implementation of the <tt>execute</tt> method from the <tt>Result</tt> interface. This will call
     * the abstract method {@link #doExecute(String, ActionInvocation)} after optionally evaluating the
     * location as an OGNL evaluation.
     *
     * @param invocation the execution state of the action.
     * @throws Exception if an error occurs while executing the result.
     */
    public void execute(ActionInvocation invocation) throws Exception {
        lastFinalLocation = conditionalParse(location, invocation);
        doExecute(lastFinalLocation, invocation);
    }

    /**
     * Parses the parameter for OGNL expressions against the valuestack
     *
     * @param param The parameter value
     * @param invocation The action invocation instance
     * @return The resulting string
     */
    protected String conditionalParse(String param, ActionInvocation invocation) {
        if (parse && param != null && invocation != null) {
            return TextParseUtil.translateVariables(param, invocation.getStack(),
                    new TextParseUtil.ParsedValueEvaluator() {
                        public Object evaluate(Object parsedValue) {
                            if (encode) {
                                if (parsedValue != null) {
                                    try {
                                        // use UTF-8 as this is the recommended encoding by W3C to
                                        // avoid incompatibilities.
                                        return URLEncoder.encode(parsedValue.toString(), "UTF-8");
                                    }
                                    catch(UnsupportedEncodingException e) {
                                        _log.warn("error while trying to encode ["+parsedValue+"]", e);
                                    }
                                }
                            }
                            return parsedValue;
                        }
            });
        } else {
            return param;
        }
    }

    /**
     * Executes the result given a final location (jsp page, action, etc) and the action invocation
     * (the state in which the action was executed). Subclasses must implement this class to handle
     * custom logic for result handling.
     *
     * @param finalLocation the location (jsp page, action, etc) to go to.
     * @param invocation    the execution state of the action.
     * @throws Exception if an error occurs while executing the result.
     */
    protected abstract void doExecute(String finalLocation, ActionInvocation invocation) throws Exception;
}

  很顯然,這個(gè)默認(rèn)實(shí)現(xiàn)是為那些類似JSP,F(xiàn)reemarker或者Redirect這樣的頁面跳轉(zhuǎn)的Result而準(zhǔn)備的一個(gè)基類,它規(guī)定了Result將要跳轉(zhuǎn)到的具體頁面的位置、是否需要解析參數(shù),等等。 [SPAN]

  如果我們試圖編寫自定義的Result,我們可以實(shí)現(xiàn)Result接口,并在struts.xml中進(jìn)行聲明:

Java代碼
public class CustomerResult implements Result {  
 
    public void execute(ActionInvocation invocation) throws Exception {  
    // write your code here  
}  

public class CustomerResult implements Result {

    public void execute(ActionInvocation invocation) throws Exception {
    // write your code here
}
}

Xml代碼
 <result-type name="customerResult" class="com.javaeye.struts2.CustomerResult"/> 

<result-type name="customerResult" class="com.javaeye.struts2.CustomerResult"/>


  常用的Result 

  接下來,大致介紹一下Struts2內(nèi)部已經(jīng)實(shí)現(xiàn)的Result,并看看他們是如何工作的。

  dispatcher

Xml代碼
 <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> 

<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>

  dispatcher主要用于返回JSP,HTML等以頁面為基礎(chǔ)View視圖,這個(gè)也是Struts2默認(rèn)的Result類型。在使用dispatcher時(shí),唯一需要指定的,是JSP或者HTML頁面的位置,這個(gè)位置將被用于定位返回的頁面:

Xml代碼
 <result name="success">/index.jsp</result> 

<result name="success">/index.jsp</result>

  而Struts2本身也沒有對dispatcher做出什么特殊的處理,只是簡單的使用Servlet API進(jìn)行forward。

  freemarker / velocity

Xml代碼
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/> 
 <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/> 

<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
 <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>

  隨著模板技術(shù)的越來越流行,使用Freemarker或者Velocity模板進(jìn)行View層展示的開發(fā)者越來越多。Struts2同樣為模板作為Result做出了支持。由于模板的顯示需要模板(Template)與數(shù)據(jù)(Model)的緊密配合,所以在Struts2中,這兩個(gè)Result的主要工作是為模板準(zhǔn)備數(shù)據(jù)。

  以Freemarker為例,我們來看看它是如何為模板準(zhǔn)備數(shù)據(jù)的:

Java代碼
public void doExecute(String location, ActionInvocation invocation) throws IOException, TemplateException {  
    this.location = location;  
    this.invocation = invocation;  
    this.configuration = getConfiguration();  
    this.wrapper = getObjectWrapper();  
 
    // 獲取模板的位置  
    if (!location.startsWith("/")) {  
        ActionContext ctx = invocation.getInvocationContext();  
        HttpServletRequest req = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);  
        String base = ResourceUtil.getResourceBase(req);  
        location = base + "/" + location;  
    }  
 
    // 得到模板  
    Template template = configuration.getTemplate(location, deduceLocale());  
    // 為模板準(zhǔn)備數(shù)據(jù)  
    TemplateModel model = createModel();  
 
    // 根據(jù)模板和數(shù)據(jù)進(jìn)行輸出  
    // Give subclasses a chance to hook into preprocessing  
    if (preTemplateProcess(template, model)) {  
        try {  
            // Process the template  
            template.process(model, getWriter());  
        } finally {  
            // Give subclasses a chance to hook into postprocessing  
            postTemplateProcess(template, model);  
        }  
    }  

public void doExecute(String location, ActionInvocation invocation) throws IOException, TemplateException {
    this.location = location;
    this.invocation = invocation;
    this.configuration = getConfiguration();
     this.wrapper = getObjectWrapper();

    // 獲取模板的位置
    if (!location.startsWith("/")) {
        ActionContext ctx = invocation.getInvocationContext();
        HttpServletRequest req = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
        String base = ResourceUtil.getResourceBase(req);
        location = base + "/" + location;
    }

    // 得到模板
    Template template = configuration.getTemplate(location, deduceLocale());
    // 為模板準(zhǔn)備數(shù)據(jù)
     TemplateModel model = createModel();

    // 根據(jù)模板和數(shù)據(jù)進(jìn)行輸出
    // Give subclasses a chance to hook into preprocessing
    if (preTemplateProcess(template, model)) {
        try {
            // Process the template
            template.process(model, getWriter());
        } finally {
            // Give subclasses a chance to hook into postprocessing
            postTemplateProcess(template, model);
        }
    }
}

  從源碼中,我們可以看到,createModel()方法真正為模板準(zhǔn)備需要顯示的數(shù)據(jù)。而之前,我們已經(jīng)看到過這個(gè)方法的源碼,這個(gè)方法所準(zhǔn)備的數(shù)據(jù)不僅包含ValueStack中的數(shù)據(jù),還包含了被封裝過的HttpServletRequest,HttpSession等對象的數(shù)據(jù)。從而使得模板能夠以它特定的語法輸出這些數(shù)據(jù)。 [SPAN]

  Velocity的Result也是類似,有興趣的讀者可以順著思路繼續(xù)深究源碼。

  redirect

Xml代碼
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> 
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> 
 <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/> 

<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
 <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>

  如果你在Action執(zhí)行完畢后,希望執(zhí)行另一個(gè)Action,有2種方式可供選擇。一種是forward,另外一種是redirect。有關(guān)forward和redirect的區(qū)別,這里我就不再展開,這應(yīng)該屬于Java程序員的基本知識。在Struts2中,分別對應(yīng)這兩種方式的Result,就是chain和redirect。

  先來談?wù)剅edirect,既然是重定向,那么源地址與目標(biāo)地址之間是2個(gè)不同的HttpServletRequest。所以目標(biāo)地址將無法通過ValueStack等Struts2的特性來獲取源Action中的數(shù)據(jù)。如果你需要對目標(biāo)地址傳遞參數(shù),那么需要在目標(biāo)地址url或者配置文件中指出:

Xml代碼
<!--  
   The redirect-action url generated will be :  
   /genReport/generateReport.jsp?reportType=pie&width=100&height=100 
   --> 
   <action name="gatherReportInfo" class="..."> 
      <result name="showReportResult" type="redirect"> 
         <param name="location">generateReport.jsp</param> 
         <param name="namespace">/genReport</param> 
         <param name="reportType">pie</param> 
         <param name="width">${width}</param> 
         <param name="height">${height}</param> 
      </result> 
   </action> 

<!--
   The redirect-action url generated will be :
   /genReport/generateReport.jsp?reportType=pie&width=100&height=100
   -->
   <action name="gatherReportInfo" class="...">
      <result name="showReportResult" type="redirect">
         <param name="location">generateReport.jsp</param>
         <param name="namespace">/genReport</param>
         <param name="reportType">pie</param>
         <param name="width">${width}</param>
         <param name="height">${height}</param>
      </result>
   </action>

  同時(shí),Redirect的Result支持在配置文件中,讀取并解析源Action中ValueStack的值,并成為參數(shù)傳遞到Redirect的地址中。上面給出的例子中,width和height就是ValueStack中的值。

  chain

Xml代碼
 <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> 

<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>

  再來談?wù)刢hain,之前提到,chain其實(shí)只是在一個(gè)action執(zhí)行完畢之后,forward到另外一個(gè)action,所以他們之間是共享HttpServletRequest的。在使用chain作為Result時(shí),往往會配合使用ChainingInterceptor。有關(guān)ChainingInterceptor,Struts2的Reference說明了其作用:

  Struts2 Reference 寫道:If you need to copy the properties from your previous Actions in the chain to the current action, you should apply the ChainingInterceptor. The Interceptor will copy the original parameters from the request, and the ValueStack is passed in to the target Action. The source Action is remembered by the ValueStack, allowing the target Action to access the properties of the preceding Action(s) using the ValueStack, and also makes these properties available to the final result of the chain, such as the JSP or Velocity page.

  也就是說,ChainingInterceptor的作用是在Action直接傳遞數(shù)據(jù)。事實(shí)上,源Action中ValueStack的數(shù)據(jù)會被做一次Copy,這樣,2個(gè)Action中的數(shù)據(jù)都在ValueStack中,使得對于前臺來說,通過ValueStack來取數(shù)據(jù),是透明而共享的。chain這個(gè)Result有一些常用的使用情景,這點(diǎn)在Struts2的Reference中也有說明:

  Struts2 Reference 寫道:One common use of Action chaining is to provide lookup lists (like for a dropdown list of states). Since these Actions get put on the ValueStack, their properties will be available in the view. This functionality can also be done using the ActionTag to execute an Action from the display page.

  比如說,一張頁面中,你可能有許多數(shù)據(jù)要顯示,而某些數(shù)據(jù)的獲取方式可能被很多不同的頁面共享(典型來說,“推薦文章”這個(gè)小欄目的數(shù)據(jù)獲取,可能會被很多頁面所共享)。這種情況下,可以把這部分邏輯抽取到一個(gè)獨(dú)立Action中,并使用chain,將這個(gè)Action與主Action串聯(lián)起來。這樣,最后到達(dá)頁面的時(shí)候,頁面始終可以得到每個(gè)Action中的數(shù)據(jù)。

  不過chain這種Result,是在使用時(shí)需要慎重考慮的一種Result:

  Struts2 Reference 寫道:As a rule, Action Chaining is not recommended. First explore other options, such as the Redirect After Post technique.

  而Struts2也做出了理由上的說明:

  Struts2 Reference 寫道:Experience shows that chaining should be used with care. If chaining is overused, an application can turn into "spaghetti code". Actions should be treated as a Transaction Script, rather than as methods in a Business Facade. Be sure to ask yourself why you need to chain from one Action to another. Is a navigational issue, or could the logic in Action2 be pushed back to a support class or business facade so that Action1 can call it too?

Ideally, Action classes should be as short as possible. All the core logic should be pushed back to a support class or a business facade, so that Actions only call methods. Actions are best used as adapters, rather than as a class where coding logic is defined.

  從實(shí)戰(zhàn)上將,使用chain作為Result也的確存在著上面所說的許多問題,我個(gè)人也是非常不推崇濫用這種Result。尤其是,對于使用Spring和Hibernate的朋友來說,如果你開啟OpenSessionInView模式,那么Hibernate的session是跟隨HttpServletRequest的,所以session在整個(gè)action鏈中共享。這會為我們的編程帶來極大的麻煩。因?yàn)槲覀冎繦ibernate的session會保留一份一級緩存,在action鏈中,共享一級緩存無疑會為你的調(diào)試工作帶來很大的不方便。

  所以,謹(jǐn)慎使用chain作為你的Result,應(yīng)該成為一條最佳實(shí)踐。

  stream

Xml代碼
 <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> 

<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>

  StreamResult等價(jià)于在Servlet中直接輸出Stream流。這種Result被經(jīng)常使用于輸出圖片、文檔等二進(jìn)制流到客戶端。通過使用StreamResult,我們只需要在Action中準(zhǔn)備好需要輸出的InputStream即可。

Xml代碼
<result name="success" type="stream"> 
  <param name="contentType">image/jpeg</param> 
  <param name="inputName">imageStream</param> 
  <param name="contentDisposition">filename="document.pdf"</param> 
  <param name="bufferSize">1024</param> 
</result> 

<result name="success" type="stream">
  <param name="contentType">image/jpeg</param>
  <param name="inputName">imageStream</param>
  <param name="contentDisposition">filename="document.pdf"</param>
  <param name="bufferSize">1024</param>
</result>

  同時(shí),StreamResult支持許多參數(shù),對輸出的Stream流進(jìn)行參數(shù)控制。具體每個(gè)參數(shù)的作用,可以參考://struts.apache.org/2.0.14/docs/stream-result.html

  其他

  Struts2的高度可擴(kuò)展性保證了許多自定義的Result可以通過插件的形式發(fā)布出來。比較著名的有JSONResult,JFreeChartResult等等。有興趣的讀者可以在Struts2的官方網(wǎng)站上找到它們,并選擇合適的加入到你的項(xiàng)目中去。

  關(guān)于Result配置簡化的思考 

  Struts2的Result,解決了“如何從Control層轉(zhuǎn)向View層”的問題。不過看了上面介紹的這些由框架本身實(shí)現(xiàn)的Result,我們可以發(fā)現(xiàn)Result所涉及到的,基本上還停留在為Control層到View層搭建橋梁。

  傳統(tǒng)的,我們需要通過配置文件,來指定Action執(zhí)行完畢之后,到底執(zhí)行什么樣的Result。不過在這樣一個(gè)到處呼吁簡化配置的年代,存在著許多方式,可以省略配置:

  1. 使用Annotation

  Struts2的一些插件提供了@Result和@Results的Annotation,可以通過Annotation來省略XML配置。具體請參考相關(guān)的文檔。

  2. Codebehind插件

  Struts2自帶了一個(gè)Codebehind插件(Struts2.1以后被合并到了其他的插件中)。Codebehind的基本思想是通過CoC的方式,使用命名約定來確定JSP等資源文件的位置。它通過實(shí)現(xiàn)了XWork的UnknownHandler接口,來實(shí)現(xiàn)當(dāng)Struts2框架無法找到相應(yīng)的Result時(shí),如何進(jìn)行處理的邏輯。具體文檔可以參考://struts.apache.org/2.0.14/docs/codebehind-plugin.html

  大家可以在上面這兩種方式中任意選擇,國內(nèi)著名的開源倡導(dǎo)者Springside也是采用了上述2種方法。在多數(shù)情況下,使用Codebehind,針對其他的一些Result使用Annotation進(jìn)行配置,這樣可以在一定程度上簡化配置。

  不過我本人對使用Annotation簡化配置的評價(jià)不高。因?yàn)閷?shí)際上使用Annotation,只是將原本就非常簡單的配置,從xml文件中移動到j(luò)ava代碼中而已。就代碼量而言,本身并沒有減少。

  在這里,我也在經(jīng)常在思考,如何進(jìn)行配置簡化,可以不寫Annotation,完全使用CoC的方式來指定Result。Codebehind在CoC方面已經(jīng)做出了榜樣,只是Codebehind無法判別Result的類型,所以它只能支持dispatcher / freemarker / velocity這三種Result。所以Result的類型的判別,成為了阻礙簡化其配置CoC化的攔路虎。

  前一段時(shí)間,曾經(jīng)熱播一部電視劇《暗算》,其中的《看風(fēng)》篇中數(shù)學(xué)家黃依依的一段話給了我靈感:

  黃依依 寫道:開啟密鎖鑰匙的復(fù)雜化,是現(xiàn)代密碼發(fā)展的趨勢。但這種復(fù)雜化卻受到無線通訊本身的限制,尤其是距離遠(yuǎn)、布點(diǎn)多的呈放射性的無線通訊,一般的密鑰總是要藏在報(bào)文中。

  密鑰既然可以藏在報(bào)文中,那么Result的類型當(dāng)然也能夠藏在ResultCode中。

Java代碼
return "success"; 

return "success";

  這樣一個(gè)簡單的success作為ResultCode,是無法識別成復(fù)雜的Result類型的,我們需要設(shè)計(jì)一套更加有效的ResultCode,同時(shí),Struts2能夠識別這些ResultCode,并得到相應(yīng)的Result類型和Result實(shí)例。這樣,我們就可以借用Codebehind的實(shí)現(xiàn)方式,實(shí)現(xiàn)XWork的UnknownHandler接口,從而達(dá)到我們的目的。例如,我們規(guī)定ResultCode的解析規(guī)則:

  success —— 使用codebehind的規(guī)則進(jìn)行JSP,F(xiàn)reemarker模板的尋址

  r:/user/list  —— 返回一個(gè)redirect的Result,地址為/user/list

  c:/user/list —— 返回一個(gè)chain的Result,地址為/user/list

  j:user —— 返回一個(gè)JSON的Result,JSONResult的Root對象為user

  s:inputStream-text/html —— 返回一個(gè)StreamResult,使用inputStream,并將contentType設(shè)置成text/html

  以此類推,大家可以定義自己喜歡的ResultCode的格式,從而簡化配置。有了這樣的規(guī)則,也就有了后來的實(shí)現(xiàn)。具體解析這些ResultCode,并為他們構(gòu)建Result實(shí)例的源碼,大家可以參考我的一個(gè)插件項(xiàng)目LightURL。


標(biāo)簽:

本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@ke049m.cn

文章轉(zhuǎn)載自:JavaEye

為你推薦

  • 推薦視頻
  • 推薦活動
  • 推薦產(chǎn)品
  • 推薦文章
  • 慧都慧問
掃碼咨詢


添加微信 立即咨詢

電話咨詢

客服熱線
023-68661681

TOP
利記足球官網(wǎng)(官方)網(wǎng)站/網(wǎng)頁版登錄入口/手機(jī)版登錄入口-最新版(已更新) 真人boyu·博魚滾球網(wǎng)(官方)網(wǎng)站/網(wǎng)頁版登錄入口/手機(jī)版登錄入口-最新版(已更新) 最大網(wǎng)上PM娛樂城盤口(官方)網(wǎng)站/網(wǎng)頁版登錄入口/手機(jī)版登錄入口-最新版(已更新) 正規(guī)雷火競技官方買球(官方)網(wǎng)站/網(wǎng)頁版登錄入口/手機(jī)版登錄入口-最新版(已更新) 雷火競技權(quán)威十大網(wǎng)(官方)網(wǎng)站/網(wǎng)頁版登錄入口/手機(jī)版登錄入口-最新版(已更新) boyu·博魚信譽(yù)足球官網(wǎng)(官方)網(wǎng)站/網(wǎng)頁版登錄入口/手機(jī)版登錄入口-最新版(已更新) 權(quán)威188BET足球網(wǎng)(官方)網(wǎng)站/網(wǎng)頁版登錄入口/手機(jī)版登錄入口-最新版(已更新) 正規(guī)188BET足球大全(官方)網(wǎng)站/網(wǎng)頁版登錄入口/手機(jī)版登錄入口-最新版(已更新) 91精品国产福利在线 | 国产精品成人午夜电影 | 成人国产一区二区精品小说 | heyzo无码中文字幕人妻 | 国产精品三级久久久久久电影 | 国产综合在线视频一区二区 | 97人妻天| 国产综合久久精品综合v无码 | 国产成人免费大电影 | 国产精品欧美一区二区三区四区 | 国产成人无码av | 国产成人久久精品二区三区 | 69久久国产精品视频 | 国产女同一区二区三区五区 | 国产成人尤物精品一区 | 国产99久久九九精品黑人 | 变态调教一区二区三区男同 | 精品国产免费一区二区 | 国产成人精品一区 | 动漫精品一区二 | 丰满人妻熟妇乱偷人无码 | 国产毛片午夜无码专区喷水 | 国产三级在线免费观看 | 国产精品亚洲片在 | 国产精品v毛片免费视频 | 国产91在线精品国自产在线 | 国产美女牲交视频无弹窗 | 国产精品三级在线观看 | 3d肉蒲完整版种子 | 国自产拍亚洲免费视频 | 国产欧美日韩亚洲αv | 精品国产品对白在线 | 91久久国产高清 | 国产v亚洲v天堂 | 91欧美在线视频 | 精品蜜臀国产aⅴ一区二区三区 | 国产综合亚洲欧美日韩一区二区 | 成人欧美网日韩青椒网 | 变态另类清纯唯美中文 | 国产无码毛片一区二区三区 | 国产超清无码视频 | 国产精品无码一区二区三区毛 | 国产精品无码dvd在线观看 | 国产成人av大片大片在线 | 国产人妻精品一区二区三区不卡 | 国产一区二区高清无码 | 国产妇女乱码一区二区三区 | 91麻豆精品在线观看 | 高清无码精品视频 | 国产精品va尤物在线观看 | 精品亚洲一区二区三区在 | 91精品啪国产在线观看免费 | 国产美女嘘嘘嘘嘘嘘视频 | 18禁裸乳无遮挡免费观看 | 国产裸体免费无遮挡香港特辑 | 精品爆乳一区二区三区无码av | 91精品国产综合视频 | 国产av秘一区二区三区 | 成人免费播放网站 | 91精品国产成人综合 | av无码国产在线观看免费软件 | 91丝袜视频 | 成人无码中文av天堂 | 国产产在线精品亚洲aavv | 国产精品一区二区国模私拍 | 国产成人精品在线 | 国产午夜福利综合区 | 国产精品亚洲美女 | 丰满美女冒白浆久久久久久久 | 高清av一级大片 | 国产丝袜肉丝视频 | 91免费无码国产在线观看 | 国产精品va在线观看无码不卡 | 国产三级a三级三级天天 | 极品丝袜写真大尺度无内 | av无码专区亚洲avl在线观看 | 丰满少妇三级全黄 | 国产最爽视频在线观看 | 国产精品午| 国产巨作麻豆欧美亚洲综合久久 | 国产成人免费影片在线观看 | 91精品国产高清久久福利 | 91在线软件 | 精品无码欧美日本 | 91精品国产免费久久久久久 | 国产午夜精品一 | 国产无码中文字幕 | 国产精品美乳在线观看 | 91理论片午午伦夜理片久久 | 国产萝裸体视频福利 | 国产短视频精品一区二区三区 | 国产成人亚洲精品无码青青草 | 国产成人综合日韩精品无码 | 二区三区四 | 果冻传媒一二三产区 | 97无码免费人妻超级碰碰夜夜 | 国产欧美日韩在线视综合网频 | 3d成人动漫在线观看 | 高潮湖久久久久久久久 | 高h短篇辣肉各种姿势自慰h | 国产精品成人一区二区三区视频 | 国产精品自产拍在线观看网站 | 国产成人a视频高 | 国产一区二区视频在线 | 成人精品人成网站 | 国产美女视频 | 国产偷窥盗摄一区二区 | 成人区人妻精品一区二区不卡视频 | av香港三级级在线播放 | 动漫成人无码精品一区二区三区 | 不卡中文字幕 | 国产成人亚洲精品91专区高清 | 国产麻豆一区二区三区v视界 | 国产成人综合野草 | 丰满无码人妻束缚无码区 | 91精品国产免费久久久久 | 91精品国产白丝在线观看 | 国产日韩欧美成人免费观看 | 成人涩涩屋福利视频 | 爆乳熟女av一区 | 国产人妻熟女txt | 激情人妻制服丝袜 | 国产精品毛片无码一区二区 | 国产精品无码专区 | av无码一区二区三区 | av无码精品一区二区三区三级 | 国产麻豆精品福利在线观看 | 成午夜精品一区二区三区 | 丰满老熟妇好大bbbbb | 国产精品毛片a∨一区二区三区 | 国产在线无码播放不卡视频 | 国产一级a精品免费高清欧美一 | 18禁男女无遮挡啪啪网站 | 成人无码区免费a片在线软件 | 国产精品白浆大屁股一区二区三 | 国产女人乱人伦精品一区二区 | 91精品国久久久久久无码 | 国产极品嫩模一区二区 | 国产精品午夜视频 | 国产精品午夜电影 | 韩国日本国产无套白浆一区二区 | 国产三a级日本三级日产三级 | 国产欧美久久精品不戴乳罩 | 国产精品亚洲香蕉第五区 | 韩国精品一区二区三区无码视 | 3p撑开菊眼h | 国产尤物精品不卡 | 国产av综合精品色区 | 精品久久久久久天美传媒 | 国产精品久久久久久久下载 | 国产精品人妻一区二区三区a | 国产精品高潮在线 | 国产午夜精品一区理论片水蜜桃 | 国产一区二区三区 | 精品国产亚洲av麻豆尤物 | 大尺度毛片免费看 | 国产免费毛卡片 | 国产精品香蕉在线的人 | 国产毛片毛多水多的特级毛片 | av视频| 变态另类重口特级 | 国产成人无码aa精品一区91 | 国产成人av综合色 | 国产精品无码国模私拍视频 | 国产91av视频 | 国产精品va一级二级三级电影 | 国产精品国产三级国产av品爱网 | 国产高清吃奶成免费视频网站 | 国产专区一区 | 国产韩国欧美在线 | 国产真人无码作爱视频免费 | 精品国产一区二区三区不卡蜜臂 | 国色天香久久精品国产一区 | 精品国产精品国产偷麻豆 | 91九色国产社 | 成人色网站欧美大片在线观看 | 国产精品一区二区三区四区 | 爆乳少妇在办公室在线观看 | 国产偷抇久久精品水蜜桃 | 国产精品无码午夜免费麻豆 | 99精品人妻少妇一区二区 | 国产精品国产精品国产专区 | 国产精品毛片久久久久久久 | 18禁无遮挡无码啪啪网站 | 国产av一区不卡麻豆 | 精品人妻午夜一区二区三区 | 国产精品成人综合网 | 国产成人精品久久在线 | 精品高清美女精 | 国产一区国产二区国产三区 | 国产成人无码av一区二区在 | 精品少妇ay一区二区三区 | 动漫av纯肉无码av电影网 | 国产成人精品影院狼色在线 | 国产精品拍天天在线 | 国产不卡理论片在线观看 | 国产成人高清精品免费软件 | 丰满少妇呻吟高潮经历 | 国产午夜福利在线观看红一片 | 高清无码一级片在线观看 | 国产在线观看免费av站 | 国产无套粉嫩白浆在线观看 | 国产午夜精品久久久久免费视 | 91高清国内自产精品无码 | 国产爆乳无玛av在线播放 | 精品国产在天天线2025 | 国产精品成人小电影在线观看 | 18禁白丝喷水视频w 18禁白丝喷水视频www | 国产高潮流白浆 | 91se在线观看一区二区 | 国产女主播喷水视频 | 国产麻豆精品福利在线观看 | 国产丝袜品牌、图片、排行榜 | 高潮喷水波多野结衣在线观看 | 东京热毛片无码dvd 东京热毛片无码dvd一二三区 | 91精品人妻一区二区 | 99国产精成人午夜视频一区二 | 2025国产麻豆剧传媒免费 | 18禁高潮出水呻吟娇喘mp3 | 91精品自在拍 | 国产熟女高潮一区二区三区 | 丰满多毛少妇做爰视频 | 高潮呻吟在线观看 | 激情都市综亚洲精品综合 | 国产精品成人综合网 | 国产视频一区二区在线 | 精品福利在线观看 | 精品无码av不卡久久久久 | 成人精品视频成人影院 | 国产一区二区久久久 | 国产成人精品一区二区 | 国产精品福利久久 | 成人午夜视频在线观看 | 国产精品亚洲欧美一区二区 | 91精品视频在线看 | 国产成人av在线影院无毒 | 国产91精品看黄网站 | 国产av无码 | 东京热一区二区免费高清av | 国产美女嘘嘘嘘嘘嘘 | 国精品一区二区三区免费观看 | 国产无码一区二区在线观看 | 国产精品欧美在线不卡 | 精品麻豆一二三区 | 国产精品三级a | 国产在线精品一区二区三区直 | 国产不卡视频一区二区在线观看 | 精品国产v无码大片在线观看视色 | 国产欧美日韩综合在线一区二区 | 国产亚洲欧美日韩一区午夜电影 | 国产91精选在线观看网站 | 国产国语系列在线观看 | 国产高清在线看av片重查 | 国产成人久久av免费高清 | 精品国产一区二区三区av麻豆 | 国产a级精品一级毛片 | 国产成人无码精品一区在线观看 | 韩国激情高潮无遮挡hd | 国产精品亚洲一区二区三区欲 | 国产精品va无码 | 国产成人av在线播放不卡 | 成人综合午夜精品视频 | 国产日韩另类视频一区爱 | 2025国产午夜福利久久 | 精品偷自拍另类 | 91亚洲欧美一区二区三区 | 国产精品无码无卡在线播放 | 国产日韩av在线播放 | 国产精品女人呻吟在线观看 | 国产三级欧美三级日产三级99 | 成人国产精品高清在线观看 | 国产内射在线激情一区 | 91人妻国产麻豆88 | 国产欧美日产一区二区三区 | a级国产乱理伦片免费观看 a级国产乱理伦片野外 | 国产成人美女在线播放 | 精品蜜臀国产aⅴ一区二区三区 | 国产对白国语对白 | 国产在线观看午夜电影视频网站 | ts清晰版在线观看 | 韩国三级大胸女高清视频 | 国产一区二区内射最近更新 | 国产精品亚洲lv粉色 | 国产狂喷潮在 | 国产高清无码久久 | 国产凹凸在线一区二区 | www.尤物在线 | 国产成人一区二区三区免费3 | 国产三级重口味视频在线观看 | 91精选国产大片 | 国产丝袜肉丝视频在线 | 精品久久久久久久无码人妻 | 国自产拍在线视频天天更新 | 国产精品一区二区在线观 | 妓女日韩一区二区三区 | 99久久久无码国产精品古装 | 国产午夜专区在线观看 | av日韩欧美高清在线观看 | 国产一区二区草草影 | 国产精品秘一区二区三区高潮 | 国产精品伦视频 | 国产高清美女一级a毛片www | 动漫精品啪啪一区二区免费 | 白嫩少妇高潮喷水av | 国偷自产av一区二区三区不卡 | 精品人妻无码一区二 | 国产麻花豆剧传媒 | 国产91精品高潮白浆喷水 | 精品一区二区高清免费观看 | 国产麻豆媒一区一区二区三区 | 东京热无码人妻一区二区三av | 国产在线观看一区 | 国产精品国产三级国产av中文 | 国产一级毛片 | 精品无码av一区二区三区 | 国产无码在线看免费 | 国产成人av大片在线观看 | 国产极品高颜值美女在线 | 国产精品无码专区av免费播放 | 91精品国产一区二区三区香蕉 | 国产激情娇妻在线 | 国产精品社区在线观看 | 国产自产一线在线视频 | 精品国产sm最大网站 | 91大片淫黄大片.在线天堂 | 99精品国产免费久久国语 | 国产精品国产三级厂七 | 99久久精品日本一区二区免费 | 国产激情无码视频在线播放性色 | www亚洲无码在线观看 | 国产精品视频高清在线播放 | 国产亚洲日韩欧美另类丝瓜app | 国产精品无码一级毛片app下载 | 国产欧美日韩综合一区在线观 | av毛片在线永久免 | 国产欧美日韩在线视频重口味 | 国产精品精华液网站 | 国产+高潮+喷浆 | 成人一区专区在线观看 | 精品3d卡通动漫h在线观看 | 国产一区二区三区四区二区 | 国产成人夜色高潮福利院91 | 国产91精品 | 91视频下载免费高清在线观看 | 国产精品一级无码视频播放 | 国产福利视频在线 | 国产91尤物中文在线 | 国产精品后入内射日本在线观 | 精品偷拍日韩第一页 | av毛片在线播放免费 | 91精品资源在线观看 | 国产自产在线最新 | 精品国欧美一区二区三区 | 成人在线观看完整版 | 国产精品一区二区av片 | 国产精品成人啪精品视频免费观看 | 国产sm调教在线观看 | 国产妇少水多毛多高潮a片小说 | 国产1区在线 | 国产高清在线观看视 | 国产91对白在线观看 | 成人午夜大片免费看爽爽爽 | 国产偷伦视频中文精品免费 | 国产精品青草久久久久影视福利 | 国产精品午夜男女大片免费看 | 2025天堂在线亚洲精品专区 | 国产精品毛片av一区二区三区 | 国产成人免费高 | 精品久久久无码人妻中文字幕麻豆 | 国产日韩久久久久无码精品 | 91久久偷偷鲁偷偷鲁综合 | 高清视频一区二区三区 | 国产成人无码的免费视频播放 | 国产毛片一区二区三区视频 | 国产成人精品亚洲高清在线 | 成人午夜精品无码区久久 | 国产成人涩涩涩视频在线观看 | 18处破外女出血在线在线观看 | 国产桃色无码视频在线观看 | 国产精品一区二区在线播放 | 精品国产免费第一区二区三区日 | 国产成人av一区二区三区不卡 | 国产刺激对白国产情侣 | 精品国产免费人成在线观看 | 国内免费视频一区二区三区 | 国产精品玖玖资 | 国产欧美日韩综合视频专 | 福利国产微拍广场一区视频在 | 成人一区二区三区视频 | 精品国产一区二区三区香蕉p | 国产成人精品高清国产三级 | 国产精品国语刺激对白在线观看 | 91丝袜在线观看亚 | 成人涩涩屋福利视频 | 国产国拍亚洲精品无码 | 国产在线精品一区免费香蕉 | 18禁黄黄美女网站在线看 | 国产成人免费无庶挡视频在线观看 | 国产免费午夜在线观看 | 国产亚洲色婷婷久久99精品91 | 激情亚洲av无码日韩av | 国产成人高清亚洲黄片大全 | 国产成人无码一区二区三区在线 | 国产a级作爱视频 | 国产高潮好爽好大好紧受不了了 | 国产综合久久久 | 风流少妇按摩来高潮 | 国产成人手机在线视频在线观看 | 精品日韩专区 | 精品麻豆一二三区 | 国产自愉自愉第三区 | 国产午夜免费一区二区三区 | 国产精品一区不卡在 | 国产在线精品二区 | 丰满人妻一区二区三区av猛交 | 成人无码免费一区二区三区 | 国产麻豆老师在线观看 | 国产a无码专区亚洲av | 国产91熟女高潮一区二区 | 91偷拍一区二区三区精品 | 国产精品无码久久久久久蜜臀a | 精品特色国产自在自线拍 | 91麻豆视频| 国产三级黄色录像 | 国产偷窥盗拍丰满老熟女 | 91在线精品| 国产精品一区二区公司 | 高清精品一区二 | 国产黄在观线免费 | 国产精品中文字幕日韩精品 | 精品久久久久久中文字幕无码vr | 国产ol丝袜高跟在线观看不卡 | 99精品视频九九精品视频 | 国产91高清在线 | 国产精品无码a∨麻豆 | 国产自在现偷国产精品一区二区 | 国产亚洲中文日本不卡 | 国产精品午夜福利在线观看地址 | 国产成人精品一区二三区 | 国产麻豆入在线观看 | 国产日韩免费一区二区三区 | 2025国精品产露脸偷拍视频 | 国产一区二区三区欧美亚洲 | 91热国内精品永久免费观看 | 91精品国产福利在线观看性色 | 1000部未满十八禁止观看 | 国产高级桑拿在线播放 | 国产不卡一区二区免费视 | 国产黄色片免费看 | 国产a级毛片免费视频一区二区 | 91国语精品自产拍在线观看一 | 福利一区二区三区微拍视频 | 国产精品一区二区久久 | 国产福利91精品 | 国产激情一区二区三区在线hd | 91精品啪在线观看国产色 | 国产一区二区三区在线电影 | 国产毛片女人高潮叫声 | 国产91香蕉在线精品 | 国产精品十八禁一区二区三区 | 精品美女一级一区二区三 | 岛国毛片在线观看亚洲 | 国产精品午夜福利在线观看地址 | 国产无码精品免费视频免费 | 国产精品妇女一二三区 | 91视频亚洲电影 | 99精品人妻无码专区在线视 | 91天堂一区二区在线播放 | av无码不卡在线观看免费 | 国产高清成人av片 | 91成人午夜精品福利院在线观看 | 国产综合久久久久久鬼色 | 精品日韩av一区无码 | 国产精品成人一区二区三区电影 | 国产精品午夜视频 | 变态另类欧美大码日韩 | www.深夜成人网站在线观看 | 国产一区二区在线日韩 | 国产一区二区在线免费观看 | 国产精品白浆无码流出系列视频 | 国产做无码视频在线 | 国产成本人三级在线观看网站 | 岛国一区二区在线观看蜜 | 丰满白嫩人妻中出无码 | 18禁裸体动漫美女无遮挡网 | 精品一区二区高清在线 | 国产精品导航一区二区 | 国产精品丝袜一区二区三区 | 国产成人综合日韩精品无码 | 国产精品午夜电影 | 国产成人h在线观看网站站 国产成人mv毛毛a片 | 国产午夜亚洲精品理论片久久 | 成年在线观 | 国产无套在线观看视频 | 东京热一区二区三区无码视频 | 国产美女嘘嘘嘘嘘嘘 | 国产精品厕所电影 | 91精品国产全国免费观看蜜桃 | 91大神在线精品视频一区 | 岛国毛片一级一级特 | 国精品人妻无码一区二区三区蜜 | 国产精品视频一区二区三区四 | 91亚洲午夜精品久久久久久一区 | 国产极品ts人妖在线观看 | 国产精品久草在线观看 | 国产中文字幕在线观看 | 国产v亚洲v天堂无码果冻传媒 | 国产成人精品久久久 | 国产黄色片一级a级特级 | 国产福利不卡在线观看 | 国产一区在线观看 | 10000部拍拍拍免费视频 | 国产在线精品一区在线观 | 国产交换配乱婬视频偷 | 国产最新精品一区二区三区 | 97精品人妻一区二区三区在线 | 东京热加勒比无码少妇 | 国产精品探花一区在线观看 | 成人黄色av播放 | 国产午夜男女无遮挡拍拍视频 | 国产在线高清精品二区 | 国产麻豆精选av精彩内容大揭秘 | 国产高潮美女出白浆在线观看 | 99久久无码免费国产 | 韩国精品视频在线观看 | 精品国产免费久久无码 | 国产极品嫩模 | 精品人妻一区二区三区蜜桃 | 精品国产一区二区三区久久久蜜臀 | 国产欧美另类精品又又久久 | 国产私密网站入口 | 国产高清无码在线 | 精品一区二区三区免费 | 国产精品日韩精品久久密挑 | 国产精品人妻一 | 1024国产你懂的在线视频 | 国产办公室秘 | 国产白白视频在 | 国产精品福利区一区二区三区四 | 91网站中国电影av欧美 | 加勒比东京热无码中文字幕 | 国产黑色丝袜在线观看片不卡顿 | 高潮抽搐潮喷毛片在线播放 | 成人欧美日韩 | 国产高清免费av片在线观看不卡 | 99久久精品国产一区二区蜜芽 | 国产成人无码a区在线 | 国产日韩av毛片 | 国产av无码片毛片一级流奶水 | 国产在线观看超清无码视频一区二区 | 国产精品美女久久久网站动漫 | 国产精品对白刺激久久 | 黄色视频亚洲一区二区无码真爽 | 国产在线观看精品一区二区三 | 911青草亚洲精品 | av人摸人人人澡人人超碰妓女 | 国产精品美女一区二区三区 | 国产成年网站v片在线观看 国产成年无码aⅴ片 | 国产av巨作丝袜秘书 | 国产麻豆流白浆在线观看 | 91高清视频一二三区 | 二三区好的精华液 | 二区不卡网站 | 国产精品三级手机在线观看 | 97精品人妻一区二区三区香蕉 | 国产麻豆精品一区二区三 | 国产超污精品a级毛片 | www夜片内射视频日韩 | 国产sm主人调教女m视频 | 国产高级会所按摩技师在线看 | 成人亚洲午夜国产精品区在线观看 | 91在线精品国产丝袜超清 | 精品无码91久久精品无码一区 | 国产一区二区三区精品在线观看 | 国产精品视频二区不卡 | 国产精品麻豆三级一区视频 | 成人欧美在线视频 | 91精品国产肉丝高跟在线观 | 91大神大战高跟丝袜 | 国产成人一区二区三区动漫 | 成人亚洲国产精品无码久久一线 | 国产极品尤物va在线精品 | 2025亚洲综合一| 99精品热在 | 国产精品一区二区在线观看 | 国产精品福利午夜在线观看 | 国产成人综合精品日韩 | 国产一区二区波多野结衣 | 91精品国产91热久久p | 国产精品无码在线观看 | 国产成品精品午夜视频 | 国产av国片 | 国产盗摄精品一二区 | 国产精品欧美在线另类小说 | 国产精品无码aⅴ在线观看播放 | 精品国产亚洲一区二 | 果冻国产传媒61国产免费 | 99精品一级欧美片免费播放 | 精品国产午夜福利在线观看蜜月 | 国产成人精品久久久久精品日日 | 国产午夜福利片在线观看尤物 | 91无码人妻丰满熟妇区五十路 | 91大神精品网站在线观看 | 另类欧美亚洲 | 91麻精品国产91久久久 | 国产午夜在线视频观看 | 国产av午夜网站 | 18禁无遮挡国产免费观看 | 国产精品成人午夜电影 | 国产黄片软件在线观看 | 成人日韩无码动漫秘一区二区 | 成人片无码中文字幕免费 | 国产黄a级三级三级看三级 国产黄a三级三级三级 | 99精品视频在线观看免费播放 | 国产成人69午夜视频观看 | 丰满熟妇乱又伦精品 | 国自产拍高清精品 | 动漫av永久无码精品每日更新 | 国产av无码专区亚洲a∨毛片 | 国产一区二区三区在线精品专区 | 东京热制服丝袜无码专区 | 18禁美女黄网站色大片免费 | 国产一级a爱做片免费观看 国产一级a爱做片免费看 | 精品国产专区不卡 | 国产精品va在线播放 | 国产无码av不卡免费在线观看 | 精品午夜福利在线观看 | 国产美女精品视频 | 91丝袜精品久久久久久无码人 | 国产在线一区二区视频 | 不卡午夜中文字幕 | 岛国精品三级视频 | 成人综合国产成人亚洲 | 国产av一区二区最 | 91精品国产午 | 91精品无码国产在线观看一区 | 国产人妻久久精品二区三区特黄 | 成人无码精品一区二区三区 | 国产成人免费av在线播放 | 国产v综合v亚洲欧美久久 | 国产内射一级一片内射精品视频 | 国模无码视频 | 精品国产福利在线观看网址 | 国产美女精品人人做人人爽 | 国产蜜桃tv| 18禁激情床震无遮挡污污污 | 国产一区二区三区免费看视频 | 国产av果冻传媒在线观看 | 18禁男女无遮挡啪啪网站 | 国产丰满老熟妇乱xxx1区 | 国产成人一区二区在线观看 | 岛国一区二区三区在线观看视频 | 国产精品一区二区av不卡 | 东京日韩人妻无码专区一本亚州最新 | 国产91丰满老 | 成人一区在线观看 | 韩国免费a级毛片 | 精品国偷自产在线不卡短视频 | 精品国产一区 | 国产成人综合亚洲av网站 | 国产精品丝袜久久久久久不 | 2025国产微拍精品一区 | 国产高清无码一区二区久久 | 国产午夜无码区在线观看 | 国产精品一区二区白浆 | 国产日韩久久久久精品影视 | 国偷自产av一区二区三区接 | 精品一区二区三区高清免费观看 | 国产a精品 | 2025国精品产露脸偷拍视频 | 国产av导航大全精品 | 国产呦精品一区二区三区下载 | av无码a一在线观看 av无码a在线观看 | 国产成人麻豆亚洲综合无码精品 | 成人国产日本亚洲精品 | 国产成人综合亚洲欧 | 国产av无码片毛片一级 | 国产无码资源在线观看 | 国产av无码专区 | 成人无码精品一区二区三区 | 国产白丝美腿娇喘高潮的视频 | 国产成人久久精品二三区无码 | 国产女人爽到高潮精品久久 | 国产精品精品在线看 | 国产一在线精品一区 | 国产欧洲日韩一区二区三区在 | 国产精品亚洲第一视频 | 国产无码视频一区在线观看 | 国产操逼视频 | 91久久精品无码一级毛片 | 国产精品秘入口18禁麻豆免会员 | 国产成人亚洲欧美日韩精品 | av日韩欧美视频在线 | 国产成人精品免费午夜av | 国产a级毛片不收费 | 国产毛片一级不卡 | 国产精品爆乳奶水无码视频免費 | 国产精品日韩综合无码 | 国产美女裸舞久久福利 | 国产一本到最新视频直播在线 | 国产熟女高潮精选 | 精品久久久无码人妻中文 | 国产成人久视频免费 | 国产日韩欧美一区二区东京 | 国产精品成人a片在线播放 国产精品成人a区在线观看 | 国产在线樱桃视频一区 | 国产二级一片内射视频播 | 国产精品福利在线观看免费不卡 | 成人一级视频毛片 | 91亚洲自偷手机在线观看 | 国产亚洲精品久久无亚洲 | 国产一区二区精品高清在线观看 | 国产三级欧美三级日产三级99 | 国产av剧情md精品麻豆 | 东京热一精品无码一二三 | 国产一区二区三区高清视频在线 | 国产综合第一页在线视频 | 91探花在线播放 | 91嫩草国产在线无码观看 | 国产91香蕉 | av一级在线观 | 国产美女被遭强高 | 国产a级毛片毛片 | 国产福利一区二区麻豆 | 国产高清精品一区 | 国产精品四虎在线观看免费 | 91精品人妻一区二区三区蜜桃 | 国产午夜精品福利一区久久久 | 2025国内精品久久久久 | 99久久亚洲精品日 | 国产一区二区久久精品 | 国产微拍国内精品自线一区二区 | 99久久久国产免费观看精品 | 国产一区二在线观看 | 国色天香精品一卡2卡3卡 | 91精品成| 国产成人亚洲精品无码不卡 | 精品国产高清在线拍 | 国产超级大爆乳美女在线播放 | 国产成人亚洲精品影院 | 97人妻碰碰视频免费上线 | 丰满少妇人妻久久久久久4 丰满少妇人妻无码专区 | 国产极品粉嫩馒头一线天图片 | 风韵少妇性饥渴推油按摩视频 | 国产精品出租屋系列 | 国产精品丝袜久久久久久聚色 | 国产二三区 | 国产成人无码精 | 国产一区亚洲一区 | 国产精品对白清晰受不了了 | 国产精品人成a片一区二区 国产精品人成a片一区二区下载 | 国产午夜激无码av毛片不卡 | 国产午夜精品理论在线观看 | 爆乳少妇在办公室在线观看 | 国产麻豆精品久 | 成人午夜福利a片在线观看 成人午夜福利电影 | 国产成人av一区二区三区在线 | 国产精品特级毛片一区二区三区 | 国产成人精品123区免费视频 | 成人情趣用品 | 精品美女网站在线观看av污 | 调教美女久久国产 | 成人综合网站一区二区三区四区 | 国产成人精品实拍在线 | 国产原创在线观看播放 | 91av网址| 国产成人福利毛片 | 91久久精品国产91久久 | 波多野结衣在线观看一区二区三区 | 高清国产无码乱伦 | 国产精品视频一区二区三区无码 | 91视频精品安全吗 | 精品亚洲一区二区三区在线 | 国产微拍视频手机在线播放 | 国产精品精品二区 | 国外精品视频在线观看免费 | 成人午夜毛片一区二区 | 国产精品一级毛片无码视频 | 国产免费高清视频在线观看不卡 | 国产福利酱在线观看萌白酱j | 国产精品一级爱 | 国产精品日韩亚洲一区二区 | 成人精品在线免费观看 | 国产成人啪精品视频免费a 国产成人啪精品视频免费软件 | 国产精品欧美一区二区三区 | 国产成人综合亚洲av小说 | 国产自愉自愉 | 精品视频一区二区三区中文字 | 成人国内精品久久久久影 | 国产成成视频在线观看 | 精品无码免费在线 | 成人精品永久免费视频 | 黑人巨茎精品欧美一区二区 | 国产爆乳无码av一区二区 | 国产肥熟女视频一区二区三区 | 成人精品av一区二区三区 | 国产高潮 | 国产麻花豆剧传媒 | 高清精品亚洲日韩 |