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

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

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

    posts - 41,  comments - 8,  trackbacks - 0
      置頂隨筆
         摘要: * 此框架采用前后臺分開,前后臺都可以單獨(dú)部署,前端采用輕量級的扁平化設(shè)計(html+javascript+Bootstrap), 會自動針對不同的屏幕尺寸調(diào)整頁面,使其在各個尺寸的屏幕上表現(xiàn)良好。
    * 后端采用Spring boot,它使我們更容易去創(chuàng)建基于Spring的獨(dú)立和產(chǎn)品級的可以即時運(yùn)行的應(yīng)用和服務(wù)。直接嵌入Tomcat 或Jetty服務(wù)器,不需要部署WAR 文件,可直接運(yùn)行jar文件。
    * 系統(tǒng)權(quán)限框架采用Shiro,實(shí)現(xiàn)前后臺權(quán)限校驗(yàn) * 持久層采用JPA ,并實(shí)現(xiàn)類ibatis的查詢功能;數(shù)據(jù)響應(yīng)該采用json格式。
    * 服務(wù)采用REST形式,能夠方便的與手機(jī)app進(jìn)行對接,集成swagger能夠在線查看RESTAPI 文檔和在線測試服務(wù)接口
    * 支持單點(diǎn)登錄,可以多系統(tǒng)進(jìn)行菜單集成,形成一個portal
    * 支持高并發(fā)和水平擴(kuò)展,支持Session的統(tǒng)一存儲
    * 項目采用gradle構(gòu)建,能夠方便的將各項目進(jìn)行按需組裝  閱讀全文
    posted @ 2016-06-13 10:00 Loy Fu 閱讀(4036) | 評論 (0)編輯 收藏
      2016年6月13日
         摘要: * 此框架采用前后臺分開,前后臺都可以單獨(dú)部署,前端采用輕量級的扁平化設(shè)計(html+javascript+Bootstrap), 會自動針對不同的屏幕尺寸調(diào)整頁面,使其在各個尺寸的屏幕上表現(xiàn)良好。
    * 后端采用Spring boot,它使我們更容易去創(chuàng)建基于Spring的獨(dú)立和產(chǎn)品級的可以即時運(yùn)行的應(yīng)用和服務(wù)。直接嵌入Tomcat 或Jetty服務(wù)器,不需要部署WAR 文件,可直接運(yùn)行jar文件。
    * 系統(tǒng)權(quán)限框架采用Shiro,實(shí)現(xiàn)前后臺權(quán)限校驗(yàn) * 持久層采用JPA ,并實(shí)現(xiàn)類ibatis的查詢功能;數(shù)據(jù)響應(yīng)該采用json格式。
    * 服務(wù)采用REST形式,能夠方便的與手機(jī)app進(jìn)行對接,集成swagger能夠在線查看RESTAPI 文檔和在線測試服務(wù)接口
    * 支持單點(diǎn)登錄,可以多系統(tǒng)進(jìn)行菜單集成,形成一個portal
    * 支持高并發(fā)和水平擴(kuò)展,支持Session的統(tǒng)一存儲
    * 項目采用gradle構(gòu)建,能夠方便的將各項目進(jìn)行按需組裝  閱讀全文
    posted @ 2016-06-13 10:00 Loy Fu 閱讀(4036) | 評論 (0)編輯 收藏
      2008年10月21日
         摘要: java nio的全稱是java new I/O,即一個全新的I/O控制系統(tǒng),它的API的包名為java.nio,是在jdk1.4后引入的。 nio之所以為為新,在于它并沒在原來I/O的基礎(chǔ)上進(jìn)行開發(fā),而是提供了全新的類和接口,除了原來的基本功能之外,它還提供了以下新的特征:         ? 多路選擇的非封鎖式...  閱讀全文
    posted @ 2008-10-21 17:44 Loy Fu 閱讀(835) | 評論 (0)編輯 收藏
      2008年10月20日
     作者:羅代均 ldj_work#126.com,轉(zhuǎn)載請保持完整性
    環(huán)境說明

           Apache  :apache_2.0.55     1 個

           Tomcat:  apache-tomcat-5.5.17 (zip版) 2個

           mod_jk:: mod_jk-apache-2.0.55.so  1個

    第一部分:負(fù)載均衡

        負(fù)載均衡,就是apache將客戶請求均衡的分給tomcat1,tomcat2....去處理

       1.安裝apche,tomcat

       http://httpd.apache.org/ 下載Apache 2.0.55

        http://tomcat.apache.org/download-55.cgi 下載tomcat5.5 zip版本(解壓即可,綠色版)

       http://apache.justdn.org/tomcat/tomcat-connectors/jk/binaries/win32/jk-1.2.15/  下載mod_jk,注意和  apache版本匹配

       按照jdk,我的路徑為:E:\ide\apache\Apache2

       解壓兩份Tomcat, 路徑分別為 E:\ide\tomcat1,E:\ide\tomcat2

    下載mod_jk

    2.修改Apache配置文件http.conf

       在apache安裝目錄下conf目錄中找到http.conf

       在文件最后加上下面一句話就可以了

      include "E:\ide\apache\Apache2\conf\mod_jk.conf"

    2. http.conf 同目錄下新建mod_jk.conf文件,內(nèi)容如下
      
    #加載mod_jk Module
    LoadModule jk_module modules/mod_jk-apache-2.0.55.so
    #指定 workers.properties文件路徑
    JkWorkersFile conf/workers.properties
    #指定那些請求交給tomcat處理,"controller"為在workers.propertise里指定的負(fù)載分配控制器
    JkMount /*.jsp controller
    3.在http.conf同目錄下新建 workers.properties文件,內(nèi)容如下
     
    worker.list = controller,tomcat1,tomcat2  #server 列表
    #========tomcat1========
    worker.tomcat1.port=8009         #ajp13 端口號,在tomcat下server.xml配置,默認(rèn)8009
    worker.tomcat1.host=localhost  #tomcat的主機(jī)地址,如不為本機(jī),請?zhí)顚慽p地址
    worker.tomcat1.type=ajp13
    worker.tomcat1.lbfactor = 1   #server的加權(quán)比重,值越高,分得的請求越多
    #========tomcat2========
    worker.tomcat2.port=9009       #ajp13 端口號,在tomcat下server.xml配置,默認(rèn)8009
    worker.tomcat2.host=localhost  #tomcat的主機(jī)地址,如不為本機(jī),請?zhí)顚慽p地址
    worker.tomcat2.type=ajp13
    worker.tomcat2.lbfactor = 1   #server的加權(quán)比重,值越高,分得的請求越多

    #========controller,負(fù)載均衡控制器========
    worker.controller.type=lb
    worker.controller.balanced_workers=tomcat1,tomcat2   #指定分擔(dān)請求的tomcat
    worker.controller.sticky_session=1
    4.修改tomcat配置文件server.xml
    如果你在不同電腦上安裝tomcat,tomcat的安裝數(shù)量為一個,可以不必修改tomcat配置文件
    我這里是在同一臺電腦上安裝兩個tomcat,所以需要更改其中一個的設(shè)置
    打開tomcat2/conf/server.xml文件
    5.編寫一個測試jsp
    建立一個目錄test.里面新建一個test.jsp,內(nèi)容為
    <%
       System.out.println("===========================");
    %>
    把test放到tomcat1,tomcat2的webapps下
    6.啟動apache,tomcat1,tomcat2,進(jìn)行測試
    通過 http://localhost/test/test.jsp 訪問,查看tomcat1的窗口,可以看到打印了一行"=========="
    再刷新一次,tomcat2也打印了一條,再刷新,可以看到請求會被tomcat1,tomcat2輪流處理,實(shí)現(xiàn)了負(fù)載均衡
    第二部分,配置集群
       只配置負(fù)載均衡還不行,還要session復(fù)制,也就是說其中任何一個tomcat的添加的session,是要同步復(fù)制到其它tomcat, 集群內(nèi)的tomcat都有相同的session
    1. 修改tomcat1, tomcat2的server.xml,將集群部分配置的在注釋符刪掉,并將tomcat2的4001端口改為4002,以避免與tomcat沖突,當(dāng)然,如果是兩臺電腦,是不用改端口的,去掉注釋符即可
      
    2,修改測試項目test
    修改test.jsp,內(nèi)容如下
      <%@ page contentType="text/html; charset=GBK" %>
    <%@ page import="java.util.*" %>
    <html><head><title>Cluster App Test</title></head>
    <body>
    Server Info:
    <%
    out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
    <%
      out.println("<br> ID " + session.getId()+"<br>");
      // 如果有新的 Session 屬性設(shè)置
      String dataName = request.getParameter("dataName");
      if (dataName != null && dataName.length() > 0) {
         String dataValue = request.getParameter("dataValue");
         session.setAttribute(dataName, dataValue);
      }
      out.print("<b>Session 列表</b>");
      Enumeration e = session.getAttributeNames();
      while (e.hasMoreElements()) {
         String name = (String)e.nextElement();
         String value = session.getAttribute(name).toString();
         out.println( name + " = " + value+"<br>");
             System.out.println( name + " = " + value);
       }
    %>
      <form action="index.jsp" method="POST">
        名稱:<input type=text size=20 name="dataName">
         <br>
        值:<input type=text size=20 name="dataValue">
         <br>
        <input type=submit>
       </form>
    </body>
    </html>
    然后在test 新建WEB-INF目錄,WEB-INF下新建web.xml,內(nèi)容如下
    注意:在你的應(yīng)用的web.xml加入  <distributable/> 即可
    ok,講test復(fù)制到tomcat1,tomcat2的webapps下,重啟apache,tomcat1,tomcat2,
    新建一個 名稱為 xiaoluo  ,值為 cdut 的session,提交查詢,新開一個ie窗口,再提交查詢,如圖,可以看到,兩個tomcat 是負(fù)載均衡,并且session同步的
    posted @ 2008-10-20 08:49 Loy Fu 閱讀(527) | 評論 (0)編輯 收藏
      2008年10月15日

    在實(shí)際的網(wǎng)頁開發(fā)中,大部分時間都要涉及到Form表單的處理。在Ext框架中也提供了很多這方面的控件,而且還有一個專門的FormPanel布 局,該布局默認(rèn)為放在面板上面的所有控件都是換行放置,而在實(shí)際應(yīng)用中為了美觀,有些需要橫排,特別是Radio控件,這個時候就需要我們重新定制這些控 件的布局了,該例子中使用CSS來實(shí)現(xiàn)這些功能,先貼出一張效果圖。



    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Ext中FormPanel面板及Form控件橫排測試(CSS)</title>
    <link rel="stylesheet" type="text/css" media="all" href="../ext/resources/css/ext-all.css" />
    <style type="text/css" media="all">
    .allow-float {clear:none!important;} /* 允許該元素浮動 */
    .stop-float {clear:both!important;} /* 阻止該元素浮動 */
    .sex-male {float:left;}
    .sex-female {float:left;padding:0 0 0 20px;}
    .age-field {float:left;padding:0 0 0 58px;*padding:0 0 0 50px!important;*padding:0 0 0 50px;}
    </style>
    </head>
    <body>
    <script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
    <script type="text/javascript" src="../ext/ext-all.js"></script>
    <script type="text/javascript" src="../ext/build/locale/ext-lang-zh_CN.js"></script>
    <script type="text/javascript">Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';</script>
    <script type="text/javascript">
    Ext.onReady(function() {
    //創(chuàng)建Form面板
    var fp = new Ext.form.FormPanel({
    buttonAlign:'center',
    labelAlign:'right',
    labelWidth:40,
    frame:true,
    bodyStyle:'padding:8px 0 0 0;',
    items:[{
    xtype:'textfield',
    fieldLabel:'姓名',
    name:'n_username',
    id:'i_username',
    width:320
    },{
    xtype:'radio',
    fieldLabel:'性別',
    boxLabel:'男',
    name:'sex',
    id:'male',
    itemCls:'sex-male', //向左邊浮動,處理控件橫排
    clearCls:'allow-float', //允許兩邊浮動,在實(shí)際生成的HTML結(jié)構(gòu)中有專門的DIV阻斷浮動
    checked:true
    },{
    xtype:'radio',
    boxLabel:'女',
    name:'sex',
    id:'female',
    itemCls:'sex-female', //向左浮動,處理控件橫排
    clearCls:'allow-float', //允許兩邊浮動
    hideLabel:true //不顯示前面"性別"的標(biāo)簽
    },{
    xtype:'textfield',
    fieldLabel:'年齡',
    name:'n_age',
    id:'i_age',
    itemCls:'age-field', //向左浮動,處理控件橫排
    width:133
    },{
    xtype:'textfield',
    fieldLabel:'住址',
    name:'n_address',
    id:'i_address',
    itemCls:'stop-float', //不允許浮動,結(jié)束控件橫排
    width:320
    }],
    buttons:[{
    text:'確定',
    handler:onOK //實(shí)際應(yīng)用一般是處理fp.getForm.submit()事件
    }, {
    text:'重置',
    handler:function(){ fp.getForm().reset(); }
    }],
    keys:[{ //處理鍵盤回車事件
    key:Ext.EventObject.ENTER,
    fn:onOK,
    scope:this
    }]
    });

    //確定按鈕事件,這里只是簡單獲取各控件值,實(shí)際應(yīng)用一般和后臺腳本結(jié)合
    function onOK() {
    var strMsg;
    strMsg = ‘姓名:’ + fp.getComponent(’i_username’).getValue() + ‘,性別:’;
    if (fp.getComponent(’male’).checked) strMsg += ‘男’;
    if (fp.getComponent(’female’).checked) strMsg += ‘女’;
    strMsg += ‘,年齡:’ + fp.getComponent(’i_age’).getValue();
    strMsg += ‘,住址:’ + fp.getComponent(’i_address’).getValue();
    alert(strMsg);
    }

    //創(chuàng)建主窗口
    new Ext.Window({
    title:’Ext中FormPanel面板及Form控件橫排測試(CSS)’,
    width:400,
    closable:false,
    collapsible:true,
    draggable:false,
    resizable:false,
    modal:true,
    border:false,
    items:[fp],
    buttons:[]
    }).show();
    });
    </script>
    </body>
    </html>

    posted @ 2008-10-15 13:03 Loy Fu 閱讀(733) | 評論 (0)編輯 收藏
      2008年10月8日
    Java下的框架編程之cglib的應(yīng)用
     

    Proxy可以看作是微型的AOP,明白提供了在繼承和委托之外的第三個代碼封裝途徑,只要有足夠的想象力,可以做得非常好玩,Spring的源碼里用Proxy就用得很隨便,看得我非常眼紅。可惜Proxy必須基于接口。因此Spring的做法,基于接口的用proxy,否則就用cglib。AOP么,一般小事非compoent一級的就不麻煩AspectJ出手了。

    cglib的Enhancer說起來神奇,用起來一頁紙不到就講完了。

    它的原理就是用Enhancer生成一個原有類的子類,并且設(shè)置好callback到proxy, 則原有類的每個方法調(diào)用都會轉(zhuǎn)為調(diào)用實(shí)現(xiàn)了MethodInterceptor接口的proxy的intercept() 函數(shù):

                            

    public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy)

    在intercept()函數(shù)里,你可以在執(zhí)行Object result=proxy.invokeSuper(o,args);來執(zhí)行原有函數(shù),在執(zhí)行前后加入自己的東西,改變它的參數(shù)值,也可以瞞天過海,完全干別的。說白了,就是AOP中的around advice。

    AOP沒有出現(xiàn)以前,該領(lǐng)域經(jīng)典的設(shè)計模式是Decorator,像Java IO Stream的設(shè)計就是如此。不過,如果為每個DAO, 每個方法的寫Decorator函數(shù)會寫死人的,所以用上cglib的好處是一次過攔截所有方法。 

    另外,cglib除了Enhancer之外,還有BulkBean和Transform,都是Hibernate持久化的基礎(chǔ),但文檔貧乏,一時還沒去看怎么用。

    1.AOP里講了一百遍啊一百遍的log aspect在cglib是這樣做的:

                            

    public class LogDAOProxy implements MethodInterceptor
       {
           
    private Logger log=Logger.getLogger(LogDAOProxy.class);
           
    private Enhancer enhancer=new Enhancer();
            
    //返回DAO的子類
           public Object getDAO(Class clz)
           {
               enhancer.setSuperclass(clz);
               enhancer.setCallback(
    this);
               
    return enhancer.create();
           }
           
    //默認(rèn)的攔截方法
          public Object intercept(Object o,Method method,Object[] args,

    MethodProxy proxy) throws Throwable
          {
               log.info(
    "調(diào)用日志方法"+method.getName());
               Object result
    =proxy.invokeSuper(o,args);
               
    return result;
          }
       }


    應(yīng)用的代碼:

                            

    LogDAOProxy proxy = new LogDAOProxy();
      GoodsDAO  dao 
    = (GoodsDAO)proxy.getDAO(GoodsDAO.class);
      dao.insert(goods);


    2.而在Spring的管理下應(yīng)該略加修改的高級Decorator

    上面的例子用return enhancer.create();創(chuàng)建子類實(shí)例,但在Spring管理下,一些Bean的實(shí)例必須由Spring來創(chuàng)建和管理,而不由enhancer來創(chuàng)建的。所以我對上述用法略加修改,使它真正當(dāng)一個Proxy的角色,請對比黑體字的部分。

                            

    public class LogDAOProxy implements MethodInterceptor
      {
           
    private Logger log=Logger.getLogger(LogDAOProxy.class);
           
    private Object dao=null;
           
    private Enhancer enhancer=new Enhancer();
            
    //返回DAO的子類
           public Object getDAO(Class clz,Object dao)
           {
               
    this.dao = dao;
               enhancer.setSuperclass(clz);
               enhancer.setCallback(
    this);
               
    return enhancer.create();
           }      
           
    //默認(rèn)的攔截方法
          public Object intercept(Object o,Method method,Object[] args,

    MethodProxy proxy) throws Throwable
          {
               log.info(
    "調(diào)用日志方法"+method.getName());
               Object result
    =proxy.invoke(dao, args);
               
    return result;
          }
    }


    可見,原來模式里在getDao()時由enhancer創(chuàng)建dao,而 調(diào)用intercept時則將enhancer創(chuàng)建的dao以O(shè)bject o參數(shù)傳回。
    而新模式里,dao在getDao()時從外面?zhèn)魅耄琫nhancer.create()返回的是一個proxy. 而調(diào)用intercept時,實(shí)際會用之前傳入的dao進(jìn)行操作,而忽略O(shè)bject o參數(shù)傳入的proxy。

    有點(diǎn)遺憾, intercept函數(shù)里MethodProxy的Signature是固定的,即客戶如果調(diào)用foo(String),你不可以用proxy.invoke偷換成foo(String,String);

    posted @ 2008-10-08 10:38 Loy Fu 閱讀(403) | 評論 (0)編輯 收藏
      2008年10月4日

    前臺:

    Store:

    var resource = new Ext.data.Store({
          fields: ['imgpath','typeImage','title', 'type'],
          url: 'teaching/resource/resourceAction.evi?method=getResourceList',
          reader: new Ext.data.XmlReader(
            {
              record: "Item",
              totalRecords: "TotalCount"
            },
          [{name:'title',mapping: 'title'}, {name:'type',mapping: 'type'},{name:'imgpath',mapping: 'imgpath'},{name:'typeImage',mapping: 'typeImage'} ]
        )
    });

    resource.addListener('load', function(st, rds, opts) {
            // st 是當(dāng)前的store, rds是讀到的Record[], opts是store的配置
       for( var c=0; c<rds.length; c++ ) {
           rds[c].set('typeImage', "<img src='./images/33.gif' width='12' height='12' />");
           //待定類別,先定死類別圖片
          }
    });

    resource.load({params:{start:0,limit:10}});

    var resourceType = new Ext.data.Store({
    ,
          reader: new Ext.data.XmlReader({
          record: "Item"
         }, [
          {name: 'resourceTypeId', mapping: 'resourceTypeId'},
           {name: 'resourceType', mapping: 'resourceType'}
          ])
       });
    resourceType.load();
    var languageType = new Ext.data.Store({
    ,
          reader: new Ext.data.XmlReader({
          record: "Item"
         }, [
           {name: 'languageTypeId', mapping: 'languageTypeId'},
           {name: 'languageType', mapping: 'languageType'}
          ])
       });
    languageType.load();

    列表:

    resourcePanel = new Ext.grid.GridPanel({
    id: 'resources',
    frame: true,
    header: false,
    width: 288,
    autoWidth: true,
    autoHeight: true,
    loadMask:{msg:'正在加載數(shù)據(jù),請稍侯……'},
    iconCls:'icon-grid',
    viewConfig: { forceFit: true },
       columns:[
      {header: " ",dataIndex: 'typeImage' , width:20},
      {header: "資源標(biāo)題", width: 190, sortable: true, dataIndex: 'title'},
      {header: "類別", width: 80, sortable: true, dataIndex: 'type'}
       ],
      store: resource,
      selModel: new Ext.grid.RowSelectionModel({singleSelect:false}),
         bbar: new Ext.PagingToolbar({
      pageSize: 10,
      store: resource,
      displayInfo: false,
      //displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
      emptyMsg: "沒有記錄" 
          }),
      listeners: {
      rowclick:function(e) {
       try {
        window.parent.parent.Ext.ux.MyTips.msg("提示", "雙擊該行可預(yù)覽該資源");
        } catch(e) {}
        },
      rowdblclick:function(g, rIdx, e) {
       var rd = g.getStore().getAt(rIdx);
       var html = "<img src='./images/" + rd.get('imgpath') + "' />";
      window.parent.showWin({
          layout: 'fit',
          maximizable: true,
          title: rd.get('title'),
          width: 400,
          height: 400,
          //modal: true,
          //closeAction: 'hide',
          plain: true,
          items: [ {html: html} ]
        });
      }
    }
    });

    FormPanel:

    var rform = new Ext.form.FormPanel({
                  id:'rform',
               header: false,
               frame: true,
               hideBorders: false,
               items: [
                new Ext.form.TextField({
                 fieldLabel: '關(guān)鍵字',
                 name:'keyword'
                }),
                new Ext.form.ComboBox({
                 fieldLabel: '資源類別',
                 mode: 'local',
                 triggerAction: 'all',
                 store: resourceType,
                 typeAhead: true,
                 hiddenName:'resourceTypeId',
                 displayField: 'resourceType',
                 valueField: 'resourceTypeId',
                 readOnly: true,
                 selectOnFocus: true
                }),
                new Ext.form.ComboBox({
                 fieldLabel: '語言',
                 mode: 'local',
                 triggerAction: 'all',
                 typeAhead: true,
                 hiddenName:'languageTypeId',
                 displayField:'languageType',
                 valueField:'languageTypeId',
                 readOnly: true,
                 selectOnFocus: true,
                 store:languageType
                }),
                new Ext.Panel({
                 layout: 'table',
                 buttonAlign: 'center',
                 layoutConfig: { colspan: 3 },
                 buttons:[{text: '搜  尋',
                  handler: function() {
                                 var keyword = Ext.get('keyword').dom.value;
                                 var resourceTypeId = Ext.get('resourceTypeId').dom.value;
                                 var languageTypeId = Ext.get('languageTypeId').dom.value;
                          resource.reload({params:{start:0,limit:3,keyword:keyword,resourceTypeId:resourceTypeId,languageTypeId:languageTypeId}});
       //這里不用再寫ajax,Ext已經(jīng)封裝了ajax,只要把參數(shù)傳進(jìn)去就行了  
                  }},
                  {
                    text: '重  置',
                    handler: function() {
                       Ext.getCmp('rform').form.reset();
                   }
                   }
                  ]
                })
               ]
              })

    后臺:

    public ActionForward getResourceList(ActionMapping mapping,
       ActionForm form, HttpServletRequest request,
       HttpServletResponse response) throws IOException {

      Document document = DocumentHelper.createDocument();
      String start = request.getParameter("start");
      String limit = request.getParameter("limit");
      String keyword = request.getParameter("keyword");
      String resourceTypeId = request.getParameter("resourceTypeId");
      String languageTypeId = request.getParameter("languageTypeId");

      List<HqlCondition> hqlFilter = new LinkedList<HqlCondition>();
      if(keyword != null && keyword.length()>0){
       hqlFilter.add( new HqlCondition("and", "rs.title", "like", "%" + keyword + "%", HqlCondition.String) );
       hqlFilter.add( new HqlCondition("or", "rs.remarks", "like", "%" + keyword + "%", HqlCondition.String) );
      }
      if(resourceTypeId != null && resourceTypeId.length()>0){
       hqlFilter.add( new HqlCondition("and", "rs.resourceType.resourceTypeId", "=", new Long(resourceTypeId), HqlCondition.Long) );
      }
      if(languageTypeId != null && languageTypeId.length()>0){
       hqlFilter.add( new HqlCondition("and", "rs.languageType.languageTypeId", "=", new Integer(languageTypeId), HqlCondition.Integer) );
      }
      int pageno =1;
      int pagesize = 10;
      if(limit != null && limit.length()>0){
          pagesize = Integer.parseInt(limit);
      }

      if(!start.equalsIgnoreCase("0") && start != null && start.length()>0){
         int bpos = Integer.parseInt(start);
         pageno = (bpos + pagesize)/pagesize;
      }
      int total = this.rse.getResourceTotalCount(hqlFilter);
      Collection<BaseVO> coll = this.rse.getResourceList(hqlFilter,pageno,pagesize);
      Iterator<BaseVO> it = coll.iterator();
      while(it != null && it.hasNext()){
       BaseVO bv = it.next();
       ResourceType rt = this.rts.getResourceType(((ResourceType)bv.get("resourceType")).getResourceTypeId());
       bv.set("type", rt.getResourceType());
      }
      document.addElement("type");
      new OutputVOXml().writeXML(total,new LinkedList<BaseVO>(coll), response);
      return null;
    }

    查看更多精彩圖片
    posted @ 2008-10-04 22:43 Loy Fu 閱讀(1376) | 評論 (0)編輯 收藏
     Apache提供的一個插件包,可以把Action中的數(shù)據(jù)以JSON做個封裝然后返回。

    它會將整個action中的變量轉(zhuǎn)化為JSON數(shù)據(jù)(根對象在JSON中數(shù)據(jù)添加一個”root”標(biāo)識)。如果要使用它,Action必須遵循以下幾點(diǎn):

    1.       返回的頁面類型中”content-type”必須是”application/json”.(這個已經(jīng)Internet Community采用).

    2.       JSON內(nèi)容必須是符合格式要求的.

    3.       Actionfield必須有publicset方法.(是不是沒有set方法就不會將field添加到JSON數(shù)據(jù)中,有待驗(yàn)證).

    4.       它支持的類型有: 基本類型(int,long...String), Date, List, Map, Primitive Arrays, 其它class, 對象數(shù)組.

    5.       JSON中任何的Object會被封裝在listmap中,數(shù)據(jù)會被封裝程Long,如果是含有的數(shù)據(jù)則會被封裝程Double,數(shù)組會被封裝程List.

    下面給出JSON的數(shù)據(jù)格式:

    {

       "doubleValue": 10.10,

       "nestedBean": {

          "name": "Mr Bean"

       },

       "list": ["A", 10, 20.20, {

          "firstName": "El Zorro"

       }],

       "array": [10, 20]

    }

    說明:

    a.       這個插件支持以下幾個注釋:

    注釋名

    簡介

    默認(rèn)值

    序列化

    反序列化

    name

    配置JSONname

    empty

    yes

    no

    serialize

    serialization

    true

    yes

    no

    deserialize

    deserialization

    true

    no

    yes

    format

    格式化Date字段

    "yyyy-MM-dd'T'HH:mm:ss"

    yes

    yes

    可以通過配置來顯示指出要放在JSONfield,其中有個自己的驗(yàn)證規(guī)則需要研究.

    <!-- Result fragment -->

    <result type="json">

     <param name="excludeProperties">

        login.password,

        studentList.*".sin

     </param>

    </result>

    <!-- Interceptor fragment -->

    <interceptor-ref name="json">

     <param name="enableSMD">true</param>

     <param name="excludeProperties">

        login.password,

        studentList.*".sin

     </param>

    </interceptor-ref>

    b.       根對象

     <result type="json">

     <param name="root">

        person.job

     </param>

    </result>

    也可以使用攔截器配置操作父對象

    <interceptor-ref name="json">

     <param name="root">bean1.bean2</param>

    </interceptor-ref>

    c.       JSON數(shù)據(jù)用注釋封裝

    如果wrapWithComments設(shè)置為true(默認(rèn)值為false),則生成的JSON數(shù)據(jù)會變成這樣:

    /* {

       "doubleVal": 10.10,

       "nestedBean": {

          "name": "Mr Bean"

       },

       "list": ["A", 10, 20.20, {

          "firstName": "El Zorro"

       }],

       "array": [10, 20]

    } */

    這樣做可以避免js中一些潛在的風(fēng)險,使用時需要:

    Var responseObject = eval("("+data.substring(data.indexOf(""/"*")+2, data.lastIndexOf(""*"/"))+")");

    d.       父類

    “root”對象中父類的field不會默認(rèn)存放到JSON數(shù)據(jù)中,如果不想這樣做,需要在配置時指定ignoreHierarchyfalse:

    <result type="json">

     <param name="ignoreHierarchy">false</param>

    </result>

    e.       枚舉類型

    默認(rèn)處理枚舉類型時,會被處理成JSON數(shù)據(jù)中name等于枚舉中valuevalue等于枚舉中name.

    public enum AnEnum {

         ValueA,

         ValueB

     }

     JSON: "myEnum":"ValueA"

    如果在處理枚舉類型時,在xml中配置了enumAsBean,則會被當(dāng)作一個Bean處理,在JSON數(shù)據(jù)中會有一個特別的屬性”_name”值為name().這個枚舉中的所有屬性都會被處理.

    public enum AnEnum {

         ValueA("A"),

         ValueB("B");

         private String val;

         public AnEnum(val) {

            this.val = val;

         }

         public getVal() {

            return val;

         }

       }

     JSON: myEnum: { "_name": "ValueA", "val": "A" }

    Xml中配置:

    <result type="json">

     <param name="enumAsBean">true</param>

    </result>

    f.        例子

    a)         Action

    import java.util.HashMap;

    import java.util.Map;

    import com.opensymphony.xwork2.Action;

    public class JSONExample {

        private String field1 = "str";

        private int[] ints = {10, 20};

        private Map map = new HashMap();

        private String customName = "custom";

        //'transient' fields are not serialized

        private transient String field2;

        //fields without getter method are not serialized

        private String field3;

        public String execute() {

            map.put("John", "Galt");

            return Action.SUCCESS;

        }

        public String getField1() {

            return field1;

        }

        public void setField1(String field1) {

            this.field1 = field1;

        }

        public int[] getInts() {

            return ints;

        }

        public void setInts(int[] ints) {

            this.ints = ints;

        }

        public Map getMap() {

            return map;

        }

        public void setMap(Map map) {

            this.map = map;

        }

        @JSON(name="newName")

        public String getCustomName() {

            return this.customName;

        }

    }

    b)        Xml配置

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

    <!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

        "http://struts.apache.org/dtds/struts-2.0.dtd">

    <struts>

     <package name="example" extends="json-default">

         <action name="JSONExample" class="example.JSONExample">

            <result type="json"/>

         </action>

     </package>

    </struts>

    這里有兩個地方需要注意:

    1)      需要繼承json-default

    2)      <result>簽的定義

    c)         JSON數(shù)據(jù)

     { 

       "field1" : "str",

       "ints": [10, 20],

       "map": {

           "John":"Galt"

       },

       "newName": "custom"

    }

    d)        JSON RPC

    JSON插件可以在js中調(diào)用action方法,返回執(zhí)行結(jié)果。這個已經(jīng)在dojo中有了實(shí)現(xiàn),可以用Simple Method Definition調(diào)用遠(yuǎn)程服務(wù)。來一起看看下面的例子:

    首先寫一個Action

    package smd;

    import com.googlecode.jsonplugin.annotations.SMDMethod;

    import com.opensymphony.xwork2.Action;

    public class SMDAction {

        public String smd() {

            return Action.SUCCESS;

        }

        @SMDMethod

        public Bean doSomething(Bean bean, int quantity) {

            bean.setPrice(quantity * 10);

            return bean;

        }

    }

    e)         方法必須用SMDMethod加上注解,這樣才能被遠(yuǎn)程調(diào)用,為了安全因素。這個方法會產(chǎn)生一個bean對象,實(shí)現(xiàn)修改價格的功能。Action被添加上SMD注解會生成一個SMD,同時參數(shù)也會被加上SMDMethodParameter注解。像你所看到的,Action中定義了一個空方法:smd。這個方法是作為Simple Method Definition (定義class中提供的服務(wù)),在struts.xml配置<result>時使用type屬性值為”json”

    下面是bean的定義:

    package smd;

    public class Bean {

        private String type;

        private int price;

        public String getType() {

            return type;

        }

        public void setType(String type) {

            this.type = type;

        }

        public int getPrice() {

            return price;

        }

        public void setPrice(int price) {

            this.price = price;

        }

    }

    Xml文件:

    <package name="RPC" namespace="/nodecorate" extends="json-default">

        <action name="SMDAction" class="smd.SMDAction" method="smd">

            <interceptor-ref name="json">

                <param name="enableSMD">true</param>

            </interceptor-ref>

            <result type="json">

                 <param name="enableSMD">true</param>

            </result>

        </action>

    </package>

    這里需要注意一點(diǎn):” enableSMD”這個必須在interceptorresult都要配置.

    Js代碼:

    <s:url id="smdUrl" namespace="/nodecorate" action="SMDAction" />

    <script type="text/javascript">

        //load dojo RPC

        dojo.require("dojo.rpc.*");

        //create service object(proxy) using SMD (generated by the json result)

        var service = new dojo.rpc.JsonService("${smdUrl}");

        //function called when remote method returns

        var callback = function(bean) {

            alert("Price for " + bean.name + " is " + bean.price);

        };

        //parameter

        var bean = {name: "Mocca"};

        //execute remote method

        var defered = service.doSomething(bean, 5);

        //attach callback to defered object

        defered.addCallback(callback);

    </script>

    JsonService會發(fā)出一個請求到action加載SMD,同時遠(yuǎn)程方法會返回一個JSON對象,這個過程是Dojoaction中的方法創(chuàng)建了一個Proxy。因?yàn)檫@是異步調(diào)用過程,當(dāng)遠(yuǎn)程方法執(zhí)行的時候,它會返回一個對象到callback方法中。

    f)         代理的對象

    當(dāng)使用的注解不是繼承自Java,可能你使用代理會出現(xiàn)一些問題。比如:當(dāng)你使用aop攔截你的action的時候。在這種情況下,這個插件不會自動發(fā)現(xiàn)注解的方法。為了避免這種情況發(fā)生,你需要在xml中配置ignoreInterfacesfalse,這樣插件會自己查找注解的所有接口和父類。

    注意:這個參數(shù)只有在Action執(zhí)行的過程是通過注解來運(yùn)行的時候才應(yīng)該設(shè)為false

    <action name="contact" class="package.ContactAction" method="smd">

       <interceptor-ref name="json">

          <param name="enableSMD">true</param>

          <param name="ignoreInterfaces">false</param>

       </interceptor-ref>

       <result type="json">

          <param name="enableSMD">true</param>

          <param name="ignoreInterfaces">false</param>

       </result>

       <interceptor-ref name="default"/>

    </action>

    posted @ 2008-10-04 14:45 Loy Fu 閱讀(7743) | 評論 (2)編輯 收藏
    struts2json plugin的位置在:http://code.google.com/p/jsonplugin/
    下載json plugin的jar包,放到/WEB-INF/lib/目錄下就可以了

    Spring + Struts + JPA的項目結(jié)構(gòu)如其他例子中的一致
    首先是web.xml
    xml 代碼
     
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <web-app id="WebApp_ID" version="2.4"  
    3.     xmlns="http://java.sun.com/xml/ns/j2ee"  
    4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    5.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
    6.     <display-name>quickstart</display-name>  
    7.     <filter>  
    8.         <filter-name>struts2</filter-name>  
    9.         <filter-class>  
    10.             org.apache.struts2.dispatcher.FilterDispatcher  
    11.         </filter-class>  
    12.     </filter>  
    13.     <filter>  
    14.         <filter-name>jpaFilter</filter-name>  
    15.         <filter-class>  
    16.             org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter  
    17.         </filter-class>  
    18.         <init-param>  
    19.             <param-name>entityManagerFactory</param-name>  
    20.             <param-value>entityManagerFactory</param-value>  
    21.         </init-param>  
    22.     </filter>  
    23.     <filter-mapping>  
    24.         <filter-name>jpaFilter</filter-name>  
    25.         <url-pattern>*.action</url-pattern>  
    26.     </filter-mapping>  
    27.     <filter-mapping>  
    28.         <filter-name>struts2</filter-name>  
    29.         <url-pattern>/*</url-pattern>  
    30.     </filter-mapping>  
    31.     <welcome-file-list>  
    32.         <welcome-file>index.jsp</welcome-file>  
    33.     </welcome-file-list>  
    34.     <listener>  
    35.         <listener-class>  
    36.             org.springframework.web.context.ContextLoaderListener  
    37.         </listener-class>  
    38.     </listener>  
    39. </web-app>  

    加入jpaFilter,是為了不讓hibernate的session過早關(guān)閉,因?yàn)橛械腶ction會通過ajax動態(tài)調(diào)用。
    下面是struts.xml,注意struts.xml需要放在源代碼目錄下面:

    xml 代碼
     
    1. <?xml version="1.0" encoding="UTF-8" ?>  
    2. <!DOCTYPE struts PUBLIC  
    3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
    4.     "http://struts.apache.org/dtds/struts-2.0.dtd">  
    5. <struts>  
    6.     <constant name="struts.objectFactory" value="spring" />  
    7.     <constant name="struts.devMode" value="true" />  
    8.     <constant name="struts.i18n.encoding" value="UTF-8"/>  
    9.     <package name="person" extends="json-default">  
    10.         <action name="list" method="execute" class="personaction">  
    11.             <result type="json"/>  
    12.         </action>         
    13.     </package>  
    14. </struts>  

    這里注意,
    struts.objectFactory告訴struts所有的action都到spring的上下文里面去找,另外還需要注意,我們自己的包要繼承自json-default,這樣才可以在result的type屬性中使用json
    下面是spring的配置文件applicationContext.xml:
    xml 代碼
     
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans xmlns="http://www.springframework.org/schema/beans"  
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    4.     xmlns:aop="http://www.springframework.org/schema/aop"  
    5.     xmlns:tx="http://www.springframework.org/schema/tx"  
    6.     xsi:schemaLocation="  
    7.     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
    8.     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd  
    9.     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
    10.     <bean  
    11.         class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />  
    12.     <bean id="entityManagerFactory"  
    13.         class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">  
    14.         <property name="dataSource" ref="dataSource" />  
    15.         <property name="jpaVendorAdapter">  
    16.             <bean  
    17.                 class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">  
    18.                 <property name="database" value="MYSQL" />  
    19.                 <property name="showSql" value="true" />  
    20.             </bean>  
    21.         </property>  
    22.     </bean>  
    23.     <bean id="dataSource"  
    24.         class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    25.         <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
    26.         <property name="url" value="jdbc:mysql://localhost/extjs" />  
    27.         <property name="username" value="root" />  
    28.         <property name="password" value="" />  
    29.     </bean>  
    30.   
    31.       
    32.     <bean id="transactionManager"  
    33.         class="org.springframework.orm.jpa.JpaTransactionManager">  
    34.         <property name="entityManagerFactory"  
    35.             ref="entityManagerFactory" />  
    36.     </bean>  
    37.     <tx:annotation-driven transaction-manager="transactionManager" />  
    38.     <!--Service 開始 -->  
    39.     <bean id="personService" class="com.myext.service.impl.PersonServiceJpaImpl"/>  
    40.     <bean id="personaction" class="com.myext.action.PersonPageAction">  
    41.         <property name="person" ref="personService"/>  
    42.     </bean>  
    43. </beans>  

    這里的bean personaction和strutx.xml中的action class一致就可以了,下面是代碼:
    action:
    java 代碼
    1. package com.myext.action;
    2. import java.util.ArrayList;
    3. import java.util.List;
    4. import com.myext.service.PersonService;
    5. public class PersonPageAction {
    6. private int limit=10;
    7. private int start=0;
    8. private PersonService person;
    9. private int total=0;
    10. private List persons = new ArrayList();
    11. private boolean success=true;
    12. public boolean getSuccess(){
    13. return this.success;
    14. }
    15. public void setLimit(int limit) {
    16. this.limit = limit;
    17. }
    18. public void setStart(int start) {
    19. this.start = start;
    20. }
    21. public void setPerson(PersonService person) {
    22. this.person = person;
    23. }
    24. public int getTotal() {
    25. return total;
    26. }
    27. public void setTotal(int total) {
    28. this.total = total;
    29. }
    30. public List getPersons() {
    31. return persons;
    32. }
    33. public void setPersons(List persons) {
    34. this.persons = persons;
    35. }
    36. public String execute(){
    37. this.total = person.getTotal();
    38. this.persons = person.getPage(this.start, this.limit);
    39. return "success";
    40. }
    41. }
    service:
    java 代碼
    1. package com.myext.service.impl;
    2. import java.util.List;
    3. import javax.persistence.EntityManager;
    4. import javax.persistence.PersistenceContext;
    5. import javax.persistence.Query;
    6. import com.myext.model.Person;
    7. import com.myext.service.PersonService;
    8. public class PersonServiceJpaImpl implements PersonService {
    9. private EntityManager em;
    10. private static String poname = Person.class.getName();
    11. @PersistenceContext
    12. public void setEntityManager(EntityManager em){
    13. this.em = em;
    14. }
    15. @SuppressWarnings("unchecked")
    16. @Override
    17. public List getPage( int start, int limit) {
    18. Query q = this.em.createQuery("from " + poname );
    19. q.setFirstResult(start);
    20. q.setMaxResults(limit);
    21. return q.getResultList();
    22. }
    23. @Override
    24. public int getTotal() {
    25. return this.em.createQuery("from " + poname).getResultList().size();
    26. }
    27. }
    頁面的代碼:
    xml 代碼
    1. xml version="1.0" encoding="UTF-8" ?>
    2. <%@ page language="java" contentType="text/html; charset=UTF-8"
    3. pageEncoding="UTF-8"%>
    4. >
    5. <html xmlns="http://www.w3.org/1999/xhtml">
    6. <head>
    7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    8. <title>Grid3title>
    9. <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css" />
    10. <script type="text/javascript" src="extjs/adapter/ext/ext-base.js">script>
    11. <script type="text/javascript" src="extjs/ext-all.js">script>
    12. <script type="text/javascript" src="extjs/ext-lang-zh_CN.js">script>
    13. head>
    14. <body>
    15. <script type="text/javascript" src="grid3.js">script>
    16. <div id="grid3" >
    17. div>
    18. body>
    19. html>
    grid3.js代碼
    js 代碼
    1. /**
    2. * @author fox
    3. */
    4. Ext.onReady(function(){
    5. Ext.BLANK_IMAGE_URL = 'extjs/resources/images/default/s.gif';
    6. Ext.QuickTips.init();
    7. var sm = new Ext.grid.CheckboxSelectionModel(); //CheckBox選擇列
    8. var cm = new Ext.grid.ColumnModel([
    9. new Ext.grid.RowNumberer(), //行號列
    10. sm,
    11. {header:'編號',dataIndex:'id'},
    12. {header:'性別',dataIndex:'sex',renderer:function(value){
    13. if(value=='male'){
    14. return "";
    15. }else{
    16. return "";
    17. }
    18. }}, //增加性別,自定義renderer,即顯示的樣式,可以加html代碼,來顯示圖片等。
    19. {header:'名稱',dataIndex:'name'},
    20. {header:'描述',dataIndex:'descn'}
    21. ]);
    22. var ds = new Ext.data.Store({
    23. proxy: new Ext.data.HttpProxy({url:'list.action'}),//調(diào)用的動作
    24. reader: new Ext.data.JsonReader({
    25. totalProperty: 'total',
    26. root: 'persons',
    27. successProperty :'success'
    28. }, [
    29. {name: 'id',mapping:'id',type:'int'},
    30. {name: 'sex',mapping:'sex',type:'string'},
    31. {name: 'name',mapping:'name',type:'string'},
    32. {name: 'descn',mapping:'descn',type:'string'} //列的映射
    33. ])
    34. });
    35. var grid = new Ext.grid.GridPanel({
    36. el: 'grid3',
    37. ds: ds,
    38. sm: sm,
    39. cm: cm,
    40. width:700,
    41. height:280,
    42. bbar: new Ext.PagingToolbar({
    43. pageSize: 10,
    44. store: ds,
    45. displayInfo: true,
    46. displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
    47. emptyMsg: "沒有記錄"
    48. }) //頁腳顯示分頁
    49. });
    50. //el:指定html元素用于顯示grid
    51. grid.render();//渲染表格
    52. ds.load({params:{start:0, limit:10}}); //加載數(shù)據(jù)
    53. });
    注意,這里的gridpanel一定要設(shè)置高度,否則數(shù)據(jù)是顯示不出來的。
    最后啟動tomcat,在瀏覽器里輸入http://localhost:8080/extjs/grid3.jsp,就可以看到效果
    posted @ 2008-10-04 14:35 Loy Fu 閱讀(4532) | 評論 (2)編輯 收藏
         摘要: http://prototype.conio.net/dist/ 下載(對Ajax支持的prototype--js函數(shù)庫): prototype-1.4.0.js 或 prototype-1.4.0.tar.gz   http://code.google.com/p/jsonplugin/downloads/list 下載(Struts2...  閱讀全文
    posted @ 2008-10-04 14:19 Loy Fu 閱讀(2058) | 評論 (0)編輯 收藏
    關(guān)鍵字: Struts2 COC
    摘要:介紹Struts2中的零配置(Zero Configuration),以及如何用COC來更好地簡化Struts2的配置。在第一章,我使用Maven來創(chuàng)建一個起點(diǎn)項目;第二章,以該項目為例,講解如何使用Struts2的零配置;第三章,論述第二章中的實(shí)現(xiàn)方式的缺陷,然后講解如何使用COC來改進(jìn)這些缺陷,并進(jìn)一步簡化Struts2的配置。附件是這篇文章用到的示例代碼。

    一、從零開始

    這里,我將建立一個新的示例項目,作為講解的起點(diǎn)。我使用JDK 6、Maven 2、Eclipse 3.3來建立這個示例,如果讀者對Maven2不熟也沒關(guān)系,這只是個示例。
    首先,運(yùn)行下邊的命令:
                    mvn archetype:create -DgroupId=demo.struts -DartifactId=demo-struts-coc -DarchetypeArtifactId=maven-archetype-webapp
    這會建立如下的目錄結(jié)構(gòu):
     |- POM.xml
     |- src
         |- main
             |- resources
             |- webapp
                 |- index.jsp
                 |- WEB-INF
                     |- web.xml
    然后我們在src/main目錄下新建一個名為java的目錄,用來放置java代碼。在src下建立test目錄,并在test目錄下建立java目錄,用來放置測試代碼。另外,我這個示例不想使用JSP,所以我將src/main/webapp目錄下的index.jsp改為index.html。
    現(xiàn)在,需要配置該項目要用到哪些lib。在POM.xml中加入struts2-core:
    xml 代碼
     
    1. <dependency>  
    2.     <groupId>org.apache.struts</groupId>  
    3.     <artifactId>struts2-core</artifactId>  
    4.     <version>2.0.9</version>  
    5. </dependency>  

    另外,我想在Eclipse里使用jetty來啟動項目并進(jìn)行測試,所以在POM.xml中再加入jetty、jetty-util、servlet-api等的依賴,詳情見附件。
    我希望使用Eclipse來作為這個項目的IDE,所以,我在命令行狀態(tài)下,進(jìn)入這個項目所在的目錄,運(yùn)行:
                    mvn eclipse:eclipse
    然后使用Eclipse導(dǎo)入這個項目。如果你是第一次用Eclipse導(dǎo)入用Maven生成的項目,那你需要在Eclipse里配置一個名叫M2_REPO的Variable,指向你的Maven 2的repository目錄。缺省情況下,它應(yīng)該位于${user.home}/.m2/repository。
    OK!現(xiàn)在我們已經(jīng)可以在Eclipse中進(jìn)行工作了。
    修改src/main/webapp/WEB-INF/web.xml,加入struts2的FilterDispatcher并設(shè)置filter-mapping。在這個示例中我將url-pattern設(shè)為"/app/*",也就是說,url的匹配是基于路徑來做的。這只是我的個人喜好而已,你也可以將它設(shè)成"*"。
    既然是在講struts2的零配置,當(dāng)然是可以不要任何配置文件的。但是為了更好地進(jìn)行“配置”,我還是建立了struts.xml文件(在src/main/resources目錄下)。我不喜歡url最后都有個action后綴,現(xiàn)在,我在struts.xml中配置struts.action.extension,將這個后綴去掉:
    xml 代碼
     
    1. <struts>  
    2.     <constant name="struts.action.extension" value="" />  
    3. </struts>  

    然后我在src/test/java下建立demo/RunJetty.java文件,main方法如下:
    java 代碼
     
    1. public static void main(String[] args) throws Exception {  
    2.     Server server = new Server(8080); //也可以改成其它端口  
    3.     File rootDir = new File(RunJetty.class.getResource("/").getPath()).getParentFile().getParentFile();  
    4.     String webAppPath = new File(rootDir, "src/main/webapp").getPath();  
    5.     new WebAppContext(server, webAppPath, "/");  
    6.     server.start();  
    7. }  

    現(xiàn)在,在Eclipse里運(yùn)行或調(diào)試這個RunJetty.java,用瀏覽器打開http://localhost:8080/看看吧。如果不出問題,應(yīng)該可以訪問到webapp目錄下的index.html了。有了Jetty,你還在用MyEclipse或其它插件么?

    二、零配置

    首先要澄清一點(diǎn),這里說的零配置并不是一點(diǎn)配置都沒有,只是說配置很少而已。
    Struts2(我只用過Struts 2.0.6和2.0.9,不清楚其它版本是否支持零配置)引入了零配置的新特性,元數(shù)據(jù)可以通過規(guī)則和注解來表達(dá):A "Zero Configuration" Struts application or plugin uses no additional XML or properties files. Metadata is expressed through convention and annotation.
    目前,這個新特性還在測試階段,但經(jīng)過一段時間的使用,我覺得這個特性已經(jīng)可用。下面我講一下如何使用它。
    1. Actions的定位
    以前需要在xml配置文件中配置Action的name和class,如果使用零配置,所帶來的一個問題就是如何定位這些Action。我們需要在web.xml中找到struts2的filter的配置,增加一個名為actionPackages的init-param,它的值是一個以逗號分隔的Java包名列表,比如:demo.actions1,demo.actions2。struts2將會掃描這些包(包括這些包下邊的子包),在這些包下,所有實(shí)現(xiàn)了Action接口的或者是類名以“Action”結(jié)尾的類都會被檢查到,并被當(dāng)做Action。
    以前,我們寫Action必須要實(shí)現(xiàn)Action接口或者繼承ActionSupport。但是,上面提到的類名以"Action"結(jié)尾的類并不需要這樣做,它可以是一個POJO,Struts2支持POJO Action!
    下面是actionPackages的配置示例:
    xml 代碼
     
    1. <filter>  
    2.   <filter-name>struts2</filter-name>  
    3.   <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>  
    4.   <init-param>  
    5.     <param-name>actionPackages</param-name>  
    6.     <param-value>demo.actions1,demo.actions2</param-value>  
    7.   </init-param>  
    8. </filter>  

    2. 示例
    現(xiàn)在我們建立demo.actions1.app.person和demo.actions2.app.group兩個包,在demo.actions1.app.person包下建立ListPeopleAction.java,在demo.actions2.app.group下建立ListGroupAction.java。作為示例,這兩個類只是包含一個execute方法,返回"success"或"error",其它什么都不做:
    java 代碼
     
    1. public String execute() {  
    2.     return "success";  
    3. }  

    在Filter的配置中,我指定actionPackages為demo.actions1,demo.actions2,當(dāng)系統(tǒng)啟動時,Struts2就會在這兩個包下掃描到demo.actions1.app.person.ListPeopleAction和demo.actions2.app.group.ListGroupAction。

    3. Action and Package name
    Struts2掃描到Action后,從actionPackages指定的包開始,子包名會成為這個Action的namespace,而Action的name則由這個Action的類名決定。將類名首字母小寫,如果類名以Action結(jié)尾,則去掉"Action"后綴,形成的名字就是這個Action的名字。在如上所述的示例中,actionPackages指定為demo.actions1,demo.actions2,那么你可以這樣訪問demo.actions1.app.person.ListPeopleAction:
                    http://localhost:8080/app/person/listPeople

    4. Results
    Struts2是通過"Result"和"Results"兩個類級別的annotations來指定Results的。
    作為示例,我們在webapp目錄下建兩個html文件:success.html和error.html,隨便寫點(diǎn)什么內(nèi)容都可以。現(xiàn)在假設(shè)我們訪問/app/person/listPeople時,或Action返回success就轉(zhuǎn)到success.html頁面,若是error就轉(zhuǎn)到error.html頁面,這只需要在ListPeopleAction類上加上一段注解就可以了:
    java 代碼
     
    1. @Results({  
    2.     @Result(name="success", type=NullResult.class, value = "/success.html", params = {}),  
    3.     @Result(name="error", type=NullResult.class, value = "/error.html", params = {})  
    4. })  
    5. public class ListPeopleAction {  
    6.     public String execute() {  
    7.         return "success";  
    8.     }  
    9. }  

    同上,我們給ListGroupAction也加上注解。
    現(xiàn)在,我們已經(jīng)完成了一個零配置的示例。我們并沒有在xml文件里配置ListPeopleAction和ListGroupAction,但它們已經(jīng)可以工作了!
    用Eclipse運(yùn)行RunJetty,然后用瀏覽器訪問http://localhost:8080/app/person/listPeople和http://localhost:8080/app/group/listGroup看看,是不是正是success.html(或error.html)的內(nèi)容?

    5. Namespaces
    如上所述,namespace由包名所形成,但我們可以使用"Namespace"注解來自己指定namespace。

    6. Parent Package
    這個配置用得較少。Struts2提供一個"ParentPackage"注解來標(biāo)識Action應(yīng)該是屬于哪個package。

    三、使用COC

    如上所述,Struts2用注解來實(shí)現(xiàn)零配置。然而,這不是我喜歡的方式。在我看來,這不過是將配置從XML格式換成了注解方式,并不是真的零配置。而且,這種方式也未必比XML形式的配置更好。另外,對元數(shù)據(jù)的修改必然會導(dǎo)致項目的重新編譯和部署。還有,現(xiàn)在的Struts2版本似乎對Result注解中的params的處理有些問題。
    其實(shí),Struts2的actionPackages配置已經(jīng)使用了COC,那為什么不能為Results也實(shí)現(xiàn)COC,從而去除這些每個Action都要寫的注解?
    在嚴(yán)謹(jǐn)?shù)捻椖恐校琾ackage、action的名稱和頁面的路徑、名稱一定存在著某種關(guān)系。比如,頁面的路徑可能和package是對應(yīng)的,頁面的名稱可能和action的名稱是對應(yīng)的,或是根據(jù)某種法則運(yùn)算得到。我們知道webwork2和struts2有個配置叫g(shù)lobal-results。我們?yōu)槭裁床荒芨鶕?jù)這些對應(yīng)規(guī)則寫個Result,將它配到global-results中,從而真正免去result的配置?
    事實(shí)上,我推薦Struts2的使用者只用Struts2輸出XML或JSON,放棄UI,頁面這層還是使用標(biāo)準(zhǔn)的HTML、CSS和一些JS組件來展現(xiàn)。許多人反映Struts2慢,確實(shí),Struts2是慢,很慢!慢在哪兒?很大一部分因素是UI這層引起的,特別是使用了過多的Struts2的tag,并使用了ajax theme。但是,如果我們放棄了Struts2的笨拙的UI,Result只輸出XML或JSON,UI則使用標(biāo)準(zhǔn)的HTML+CSS,使用JS組件(DOJO、Adobe Spry Framework、YUI-Ext等)來操作Struts2的輸出數(shù)據(jù),情況將會如何?我們會得到一個高性能、高可配的、UI和應(yīng)用服務(wù)器的職責(zé)分割更為明確、合理的、更易于靜態(tài)化部署的開發(fā)組合。
    這似乎是閹割了Struts2,但是這樣閹割過的Struts2擺脫了性能低下的包袱,更輕、更現(xiàn)代化。
    有些扯遠(yuǎn)了,言歸正傳,不管是讓Struts2輸出XML或JSON,還是輸出頁面,我們都有辦法根據(jù)項目的規(guī)則寫一個Result,將它配到global-results中,從而大大減少Result的配置。
    假設(shè)我們讓Struts2只輸出JSON,有個jsonplugin可以做這件事。使用JsonResult時,不再需要知道頁面的位置、名稱等信息,它僅僅是數(shù)據(jù)輸出,那么我們就可以將這個Result配成全局的,大部分Action將不再需要Result的配置。
    作為示例,我假設(shè)我的例子中輸出的兩個html頁面(success.html和error.html)是JSON,我們看看怎么免去我例子中的兩個Action的Result注解。
    首先,我們刪去ListPeopleAction和ListGroupAction兩個Action的注解,并修改struts.xml文件,加入:
    xml 代碼
     
    1. <package name="demo-default" extends="struts-default">  
    2. <global-results>  
    3. <result name="success">/success.html</result>  
    4. </global-results>  
    5. </package>  

    請記住這只是一個示例,為了方便,我沒在項目中加入jsonplugin來作真實(shí)的演示,我只是假設(shè)這個success是json輸出,讀者可以自行使用jsonplugin來作實(shí)驗(yàn)。

    現(xiàn)在,離成功不遠(yuǎn)了,但是項目仍然不能正常運(yùn)行。我們的Action返回success,但并不會匹配到global-results中配置。為什么呢?因?yàn)椋覀冞@里是把global-results配置到"demo-default"這個package下的,而Struts2根據(jù)actionPackages找到的Action不會匹配到這個package上。解決辦法也很簡單,還記得上面講到的Parent Package吧?給Action加個注解,指定ParentPackage為"demo-default"。但這樣可不是我喜歡的,其實(shí)有更好的辦法,我們在struts.xml中加個constant就好了:
    xml 代碼
     
    1. <constant name="struts.configuration.classpath.defaultParentPackage" value="demo-default" />  

    現(xiàn)在,大功告成!運(yùn)行RunJetty來測試下吧!你可以訪問/app/person/listPeople,可以訪問/app/group/listGroup,而所有的配置僅僅是web.xml和struts.xml中的幾行,我們的Java代碼中也沒有加注解。如果再加上幾百個Action呢?配置仍然就這幾行。
    可是,某些Action確實(shí)需要配置怎么辦?對這些Action,你可以加注解,也可以針對這些Action來寫些XML配置。一個項目中,大部分Action的配置是可以遵從一定規(guī)則的,可以使用規(guī)則來簡化配置,只有少部分需要配置,這就是COC。

    posted @ 2008-10-04 14:08 Loy Fu 閱讀(1036) | 評論 (0)編輯 收藏
    僅列出標(biāo)題  下一頁
    主站蜘蛛池模板: 亚洲AV无码一区二区乱子伦| 亚洲天堂一区在线| 亚洲国产片在线观看| 美国毛片亚洲社区在线观看| 成人黄网站片免费视频| 成人在线免费观看| 亚洲国产精品无码久久一线| 日本亚洲色大成网站www久久| 久久久久免费视频| 国语成本人片免费av无码 | 国产又大又粗又长免费视频| 亚洲 无码 在线 专区| 亚洲精品亚洲人成在线麻豆| 日本中文字幕免费看| 人成午夜免费视频在线观看| 中文字幕在线亚洲精品| 亚洲自偷自偷在线成人网站传媒| 中文成人久久久久影院免费观看| 午夜小视频免费观看| 亚洲视频一区调教| 人妖系列免费网站观看| 最近免费中文字幕视频高清在线看 | 7777久久亚洲中文字幕蜜桃| 综合一区自拍亚洲综合图区| 亚洲精品在线免费观看视频 | 久久久综合亚洲色一区二区三区| 亚洲av色香蕉一区二区三区| 永久黄色免费网站| 亚洲精品高清国产一线久久| 国产亚洲精品第一综合| 亚洲国产精品免费观看| 亚洲AV日韩AV永久无码绿巨人| 色网站在线免费观看| 色婷婷7777免费视频在线观看| 亚洲va无码va在线va天堂| 色婷婷综合缴情综免费观看| 成在人线AV无码免费| 亚洲精品在线播放| 久久久久久影院久久久久免费精品国产小说 | 国产精品亚洲va在线观看| 性做久久久久久久免费看|