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

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

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

    京山游俠

    專注技術,拒絕扯淡
    posts - 50, comments - 868, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理
    使用SpringSide 3.1.4.3開發Web項目的全過程(上)

    第七步、編寫Action和JSP。在SpringSide 3.1.4.3中,使用的是Struts 2及其Convention插件,已經不是前面使用的CodeBehind插件了,關于Convention插件,這里要再說幾句,該插件的大部分功能和CodeBehind相同,唯一讓人有點迷惑的就是該插件到哪里尋找Action類的問題,它會根據struts.convention.package.locators屬性的值來決定,在該項目中,其值為“web”,之需要查閱一下struts.xml文件即可知。這說明,Convention會尋找所有包含“web”這個單詞的包,并在該包及其子包中尋找Action類。這也正是Action層的包名為personal.youxia.web的原因。

    關于SpringSide 3種的Struts的探討,大家可以看看我之前寫的一篇文章SpringSide 3 中的 Struts 2

    ArticleAction的實現思路如下,修改index.jsp,使其重定向到article.action,該Action默認調用其list方法顯示所有文章,并返回article.jsp作為其視圖。在該視圖上,有添加文章的連接,點擊該連接則訪問article!input.action,這時會調用ArticleAction的input方法,并返回article-input.jsp作為其視圖,在該視圖中輸入文章的內容,點擊保存,調用article!save.action,這時會調用ArticleAction的save方法以保存數據,如果要刪除文章,則調用article!delete.action,這時會調用ArticleAction的delete方法。在調用以上方法的過程中,會自動調用prepare系列的方法。

    因此,該步驟涉及到三個JSP文件和一個Action類,它們分別是
    index.jsp
    article.jsp
    article-input.jsp
    ArticleAction.java

    index.jsp的修改很簡單,只是讓項目一啟動后就去訪問ArticleAction,而不是默認的UserAction。index.jsp的代碼如下:
    <% response.sendRedirect("article.action"); %>

    這時,重點進入到ArticleAction中,創建該Action,其代碼的框架如下:
    package personal.youxia.web;

    import personal.youxia.entity.entities.Article;

    public class ArticleAction extends CrudActionSupport<Article> {

        @Override
        
    public String delete() throws Exception {
            
    // TODO Auto-generated method stub
            return null;
        }


        @Override
        
    public String list() throws Exception {
            
    // TODO Auto-generated method stub
            return null;
        }


        @Override
        
    protected void prepareModel() throws Exception {
            
    // TODO Auto-generated method stub

        }


        @Override
        
    public String save() throws Exception {
            
    // TODO Auto-generated method stub
            return null;
        }


        
    public Article getModel() {
            
    // TODO Auto-generated method stub
            return null;
        }


    }

    可以看到,該Action從CrudActionSupport類繼承,而CrudActionSupport又繼承自ActionSupport,并實現了ModelDriven和Preparable接口,這樣Struts 2的ModelDriven攔截器和Preparable攔截器就會對我們自己的Action發生作用。CrudActionSupport中的excute方法默認的實現是調用list方法,所以訪問article.action就等于訪問ArticleAction的list方法,該方法的目的是為了列出所有的文章,所以在該方法中使用了ArticleDao的分頁查詢,查詢結果放在一個page對象中。在Struts 2中,已經沒有了ActionForm的概念,可以直接把Action對象傳遞到視圖中,為了能夠在視圖中訪問page對象,只需要把page對象作為ArticleAction的一個屬性即可。先在ArticleAction.java中加入幾行代碼:
        @Autowired
        
    private ArticleManager articleManager;

        
    public void setArticleManager(ArticleManager articleManager) {
            
    this.articleManager = articleManager;
        }
        
        
    private Page<Article> page = new Page<Article>(10);
        
        
    public Page<Article> getPage() {
            
    return page;
        }

    可以看到該代碼的作用是為了注入ArticleManager和初始化Page對象,此時list方法的代碼就非常簡單,如下:
    @Override
        
    public String list() throws Exception {
            page 
    = articleManager.getAll(page);
            
    return SUCCESS;
        }

    由于該方法只是簡單獲取一個頁面的Acticle,所以代碼很簡單,使用articleManager.getAll方法即可。如果要實現復雜的條件查詢,就需要創建一個包含PropertyFilter對象的列表,然后使用articleManager.search方法進行查詢,為了簡化PropertyFilter對象列表的創建,白衣提供了HibernateWebUtils.buildPropertyFilters()靜態方法供大家使用。

    list方法返回的是SUCCESS,因此返回給用戶的視圖頁面為article.jsp,該頁面應該存放在WEB-INF目錄的content目錄中,這也是Convention插件的一個特性,這樣用戶就沒有辦法直接訪問到視圖頁面了。在該頁面中,可以通過訪問page對象來顯示數據,如下:
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding
    ="UTF-8"%>
    <%@ include file="/common/taglibs.jsp"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <table>
        
    <tr><td><href="article!input.action">添加文章</a></td></tr>
        
    <s:iterator value="page.result">
            
    <tr>
                
    <td>${subject}</td>
                
    <td><href="article!delete.action?id=${id}">刪除</a></td>
            
    </tr>
            
    <tr>
                
    <td>${content}</td>
            
    </tr>
        
    </s:iterator>
    </table>
    </body>
    </html>

    如果數據庫中有初始數據的話,該項目運行效果如下圖:


    到目前為止,還沒有涉及到getModel()、prepareModel()、以及prepare系列的方法,但是,一旦需要添加或者刪除文章,這一系列的方法就有作用了。在Struts 2中,由于沒有了ActionForm的概念,所有的頁面傳入參數都會被注入到Action中,如果不想在Action中搞太多的getter和setter,最有效的方法就是提供一個Model對象,這時候攔截器會把頁面參數注入到Model中,而在目前的項目中,沒有比Entity類更適合做Model對象的了。通過觀察CrudActionSupport基類,可以發現只有在執行save和input方法之前,才會執行prepareModel方法,該方法可以保證getModel方法返回的對象不是一個空指針,而調用delete方法之前Model對象沒有初始化,但是delete方法只需要一個id作為參數,因此,可以在Action中增加一個id屬性來滿足要求。這時候,有改動的幾行代碼如下:
        private Long id;
        
    private Article article;

        
    public void setId(Long id) {
            
    this.id = id;
        }

        @Override
        
    protected void prepareModel() throws Exception {
            
    if (id != null) {
                article 
    = articleManager.get(id);
            } 
    else {
                article 
    = new Article();
            }
        }
        
    public Article getModel() {
            
    return article;
        }

        @Override
        
    public String delete() throws Exception {
            articleManager.delete(id);
            
    return RELOAD;
        }

    這里需要特別關注的是delete方法返回的值,為RELOAD,這是一個在基類中定義好了的字符串。返回該字符串的目的,是為了在delete方法執行完之后,不返回任何視圖頁面,而是以redirect的方式再次調用article.action,以便顯示刪除文章后的結果。因此,需要在ArticleAction中使用@Result注解,如下:
    @Results( { @Result(name = CrudActionSupport.RELOAD, location = "article.action", type = "redirect") })

    經過如上修改,這時候再運行應用,就發現能夠刪除文章了。

    再來實現添加文章的功能,從上面的article.jsp中可以看出,添加文章的鏈接為article!input.action,此時,會運行ArticleAction的input方法,該方法只是簡單返回article-input.jsp視圖文件作為用戶輸入文章的接口,article-input.jsp的代碼如下:
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding
    ="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <form id="inputForm" action="article!save.action" method="post">
    <table class="inputView">
        
    <tr>
            
    <td>主題:</td>
            
    <td><input type="text" name="subject" size="40" id="subject" /></td>
        
    </tr>
        
    <tr>
            
    <td>內容:</td>
            
    <td><textarea name="content" id="subject"></textarea></td>
        
    </tr>
        
    <tr>
            
    <td colspan="2">
                
    <input type="submit" value="提交" />&nbsp; 
                
    <input type="button" value="取消" onclick="history.back()"/>
            
    </td>
        
    </tr>
    </table>
    </form>
    </body>
    </html>

    而ArticleAction中只需要修改如下幾行,由于ModelDriven攔截器已經把網頁中傳入的數據注入到了article對象中,所以save方法中只需要執行簡單的保存操作即可:
        @Override
        
    public String input() throws Exception {
            
    return INPUT;
        }
        
        @Override
        
    public String save() throws Exception {
            articleManager.save(article);
            
    return RELOAD;
        }

    至于實現文章的修改功能,那也是通過input方法和save方法實現的,只不過此時網頁參數中會包含一個有效的id,而prepare系列的方法會根據該id先從數據庫中提取數據,然后顯示在article-input.jsp中,用戶修改后,再調用save方法保存到數據庫中。為減少本博文長度,該功能此處不做示范。

    通過上面的步驟可以發現,使用SpringSide 3中推薦的CRUD一體的模式,可以有效減少Action的數量和JSP文件的數量,每實現一個增刪查改功能,只需要一個Action和兩個JSP,但是,程序員一定要對其中的數據流向有充足的認識,才能理清它們之間的關系,不至于暈頭轉向。

    到這里大家會發現,ArticleAction誰都可以訪問,一點都不安全,所以第八步我會探討如何讓ArticleAction和SpringSecurity一起工作,至于第九步,當然是把項目從單數據庫環境更改到多數據庫環境了。具體內容,且看下回分解!

    評論

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)  回復  更多評論   

    2009-07-20 09:28 by YangL
    中寫的有點少了,呵呵

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)[未登錄]  回復  更多評論   

    2009-07-20 17:27 by Eric
    這個中確實是寫得太少了點...

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)  回復  更多評論   

    2009-07-20 20:29 by 個性藝術簽名
    中確實是寫得太少了點

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)  回復  更多評論   

    2009-07-21 16:29 by 虎嘯龍吟
    感覺這塊寫的不夠,比方說:prepare這塊。

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)  回復  更多評論   

    2009-07-21 18:06 by 海邊沫沫
    樓上幾位別心急,我還沒收工呢。

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)  回復  更多評論   

    2009-07-23 22:57 by zhj
    我在調用article!save.action時候報錯
    2009-07-23 22:50:16,937 [http-8080-2] ERROR [500.jsp] - The save() is not defined in action class com.opensymphony.xwork2.ActionSupport
    java.lang.IllegalArgumentException: The save() is not defined in action class com.opensymphony.xwork2.ActionSupport
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:453)
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:279)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
    at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:468)
    at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:378)
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:99)
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.SessionFixationProtectionFilter.doFilterHttp(SessionFixationProtectionFilter.java:67)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(ExceptionTranslationFilter.java:101)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.providers.anonymous.AnonymousProcessingFilter.doFilterHttp(AnonymousProcessingFilter.java:105)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.rememberme.RememberMeProcessingFilter.doFilterHttp(RememberMeProcessingFilter.java:109)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter.doFilterHttp(SecurityContextHolderAwareRequestFilter.java:91)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.basicauth.BasicProcessingFilter.doFilterHttp(BasicProcessingFilter.java:174)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:277)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Unknown Source)

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)  回復  更多評論   

    2009-07-25 12:55 by 海邊沫沫
    @zhj
    不要老在我的博客中發這么長的錯誤代碼呀,影響別人閱讀的。一般來說發前幾行就足夠了。

    這里的錯誤說的是你的ArticleAction中沒有定義save方法,你再檢查檢查。

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)[未登錄]  回復  更多評論   

    2009-08-04 17:17 by lx
    頂了,感謝樓主

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)  回復  更多評論   

    2009-11-04 21:32 by sina
    最近在用springside3做manytoone的時候遇到了很大麻煩,就是在修改many一方對象里的對應one方的外鍵的時候會報錯,與http://www.javaeye.com/problems/11098這個帖子里的狀況類似,還請海邊沫沫幫忙研究一下
    其間會報
    [com.opensymphony.xwork2.ognl.OgnlValueStack] - Error setting expression 'useType.id' with value '[Ljava.lang.String;@8fff06'
    ognl.OgnlException: target is null for setProperty(null, "id", [Ljava.lang.String;@8fff06)
    以及
    identifier of an instance of pplove.entity.entities.Status was altered from 5 to 2; nested exception is org.hibernate.HibernateException: identifier of an instance of pplove.entity.entities.Status was altered from 5 to 2
    的錯誤

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)  回復  更多評論   

    2009-11-27 10:27 by skyrocket
    aused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'databaseDefinitionSource': FactoryBean threw exception on object creation; nested exception is org.hibernate.hql.ast.QuerySyntaxException: Resource is not mapped [from Resource r left join fetch r.authorityList WHERE r.resourceType=? ORDER BY r.position ASC] 請問博主我在啟動Tomcat時候為什么報這個錯誤啊

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)[未登錄]  回復  更多評論   

    2009-11-27 11:08 by zhj
    經常報找不到action里的某方法。。。,明明有此方法 不知道為啥

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)[未登錄]  回復  更多評論   

    2009-12-24 14:17 by aaa
    啥時候出下

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)  回復  更多評論   

    2011-12-04 15:07 by plume
    session.delete()刪除的時候未刪除成功,并且后臺也沒有報錯。

    # re: 使用SpringSide 3.1.4.3開發Web項目的全過程(中)  回復  更多評論   

    2012-04-28 15:17 by 十四
    勁啊
    主站蜘蛛池模板: 亚洲一区AV无码少妇电影☆| 九九99热免费最新版| 日韩精品人妻系列无码专区免费| 亚洲精品国产自在久久| 免费人妻精品一区二区三区| 免费一级毛片在级播放| 特级做a爰片毛片免费看| 亚洲精品国产精品乱码不卞| eeuss影院免费直达入口| 亚洲日韩中文无码久久| 十八禁无码免费网站| 亚洲视频国产精品| 18禁成年无码免费网站无遮挡| 亚洲精品色播一区二区| 免费v片视频在线观看视频| 国产黄在线观看免费观看不卡| 久久综合图区亚洲综合图区| 真人做人试看60分钟免费视频| 亚洲人成人网毛片在线播放| 国产成人精品高清免费| 一区二区三区免费电影| 亚洲精品福利视频| 好男人视频在线观看免费看片| 国产天堂亚洲精品| 亚洲国产精华液网站w| AV大片在线无码永久免费| 日韩国产精品亚洲а∨天堂免| 亚洲精品动漫人成3d在线 | 久久精品国产亚洲AV麻豆不卡| 精品无码人妻一区二区免费蜜桃 | 亚洲变态另类一区二区三区| 中文字幕视频免费在线观看 | 免费无码又爽又刺激高潮 | 在线观看免费亚洲| 国产特黄特色的大片观看免费视频| 亚洲日韩区在线电影| 99无码人妻一区二区三区免费| 免费播放国产性色生活片| 亚洲日本在线看片| 亚洲国模精品一区| 国产无人区码卡二卡三卡免费|