afunms

          My Software,My Dream—Forge a more perfect NMS product.

          #

          dao scenario 2

          /**
           * Second scenario:transaction is rare
           * we control connection inside service classes.
           */

          /**
           * -----ConnectionManager.class---------
           */

             public static Connection getConnection()
             {
              return getConnection(ModuleConfig.getDefaultJndi());
             }
            
             public static Connection getConnection(final String jndi)
             {
              Connection conn = null;
              try
              {       
               DataSource ds = dsMap.get(jndi);
                  if(ds==null) return null;
                 
                  conn = ds.getConnection();       
                  conn.setAutoCommit(true);
              }
              catch(SQLException sqle)
              {
               SysLogger.error("Database fail to get connection 1",sqle);
              }
              catch(Exception sqle)
              {
               SysLogger.error("Database fail to get connection 2",sqle);
              }
              return conn;
             }
               
             public static void rollback(Connection conn)
             {
              try
              {
               if(conn==null || conn.isClosed())
                return;
              
               if(!conn.getAutoCommit())         
                     conn.rollback();
              }
              catch(SQLException se)
              {
                  SysLogger.error("Can not do rollback operation.",se);        
              }
             }  
          }  

          /**
           * -----ActionServlet.class---------
           */

             private void processHttpRequest(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException
             {   
              response.setContentType("text/html;charset=GB2312");  
              request.setCharacterEncoding("GB2312");  
             
              String beanId = extractBeanID(request.getRequestURI());
              String methodName = request.getParameter("method");   
              String targetJsp = null;
             
              if(beanId==null || methodName==null)
              {
               request.setAttribute(EXCEPTION_MESSAGE,"請求URI錯誤.");
               forward(request,response,targetJsp);
               return;
              }   
              BaseAction ba = BeanFactory.newAction(beanId);
              BaseService bs = BeanFactory.newService(beanId);
              if(ba==null || bs == null)
              {
               request.setAttribute(EXCEPTION_MESSAGE,"沒有Bean為" + beanId + "的action或service");
               forward(request,response,targetJsp);
               return;
              }
               
              ActionAnnotation ann = AnnotationExtractor.getAnnotation(ba.getClass(), methodName);
              ba.setRequest(request);
              ba.setService(bs);              
              Method method = SysUtil.lookupMethod(ba.getClass().getMethods(),methodName);   

              Connection conn = null;
              if(ann.isNeedDB())
              {

               conn = ConnectionManager.getConnection();
               bs.setConnection(conn);
               bs.setDao(BeanFactory.newDao(beanId,conn));
              }
              if(method!=null)
              {
                  try
                  {         
                      targetJsp = (String)method.invoke(ba);
                  }
                  catch(Exception e)
                  {
                   SysLogger.error("Error:" + bs.getClass().getName() + "." + method.getName(),e);
               targetJsp = null;
                  }
                 }
              if(ann.isNeedDB())
               ConnectionManager.close(conn);
                 forward(request,response,targetJsp);
             } 
               
             /**
              * example:method in service class
              * operating conncetion in service
              */

           /**
            * 這是兩個dao實(shí)現(xiàn)一個事處的最好例子
            */
           public void addTop(MenuDto dto) throws Exception
           {
            Connection conn = getConnection();
            try
                          {   
             conn.setAutoCommit(false);
             
             MenuDao mDao = new MenuDao(conn);
             MenuRoleDao mrDao = new MenuRoleDao(conn);
             MenuDto menu = mDao.getNextMenu();
             menu.setTitle(dto.getTitle());
             mDao.save(menu);
             mrDao.saveMenu(menu.getId());
             
             conn.commit();
            }
            catch(Exception e)
            {    
             ConnectionManager.rollback(conn);
                                  throw e;        
            }  
           }

          posted @ 2007-05-14 14:18 afunms 閱讀(161) | 評論 (0)編輯 收藏

          dao scenario 1

          /**
           * First scenario:transaction is often used in the system
           * we control connection outside service classes.
           */

          /**
           * -----ConnectionManager.class---------
           */
             public static Connection getConnection()
             {
              return getConnection(ModuleConfig.getDefaultJndi(),true);
             }

             public static Connection getConnection(final boolean auto)
             {
              return getConnection(ModuleConfig.getDefaultJndi(),auto);
             }
            
             public static Connection getConnection(final String jndi,final boolean auto)
             {
              Connection conn = null;
              try
              {       
               DataSource ds = dsMap.get(jndi);
                  if(ds==null) return null;
                 
                  conn = ds.getConnection();       
                  conn.setAutoCommit(auto);
              }
              catch(SQLException sqle)
              {
               SysLogger.error("Database fail to get connection 1",sqle);
              }
              catch(Exception sqle)
              {
               SysLogger.error("Database fail to get connection 2",sqle);
              }
              return conn;
             }
               
             public static void rollback(Connection conn)
             {
              try
              {
               if(conn==null || conn.isClosed())
                return;
              
               if(!conn.getAutoCommit())         
                     conn.rollback();
              }
              catch(SQLException se)
              {
                  SysLogger.error("Can not do rollback operation.",se);        
              }
             }  
          }  

          /**
           * -----ActionServlet.class---------
           */

             private void processHttpRequest(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException
             {   
              response.setContentType("text/html;charset=GB2312");  
              request.setCharacterEncoding("GB2312");  
             
              String beanId = extractBeanID(request.getRequestURI());
              String methodName = request.getParameter("method");   
              String targetJsp = null;
             
              if(beanId==null || methodName==null)
              {
               request.setAttribute(EXCEPTION_MESSAGE,"請求URI錯誤.");
               forward(request,response,targetJsp);
               return;
              }   
              BaseAction ba = BeanFactory.newAction(beanId);
              BaseService bs = BeanFactory.newService(beanId);
              if(ba==null || bs == null)
              {
               request.setAttribute(EXCEPTION_MESSAGE,"沒有Bean為" + beanId + "的action或service");
               forward(request,response,targetJsp);
               return;
              }
               
              ActionAnnotation ann = AnnotationExtractor.getAnnotation(ba.getClass(), methodName);
              ba.setRequest(request);
              ba.setService(bs);              
              Method method = SysUtil.lookupMethod(ba.getClass().getMethods(),methodName);   

              Connection conn = null;
              if(ann.isNeedDB())
              {

             /**
              * -----get connection and set autoCommit to false---------
              */ 
              
          conn = ConnectionManager.getConnection(false);
               bs.setConnection(conn);
               bs.setDao(BeanFactory.newDao(beanId,conn));
              }
              if(method!=null)
              {
                  try
                  {         
                      targetJsp = (String)method.invoke(ba);
              /**
               * -----if method is executed successfully,commit connection---------
               */       

                if(ann.isNeedDB()) conn.commit();
                  }
                  catch(Exception e)
                  {
                   SysLogger.error("Error:" + bs.getClass().getName() + "." + method.getName(),e);
                /**
              * connection rollback when run into exception
              */
                  
          if(ann.isNeedDB()) ConnectionManager.rollback(conn);
                targetJsp = null;
                  }
                 }
              if(ann.isNeedDB())
               ConnectionManager.close(conn);
                 forward(request,response,targetJsp);
             }  
                
                /**
               * example:method in service
            * there has not code for operating conncetion
               */
           
          public void addTop(MenuDto dto) throws Exception
           {
            Connection conn = getConnection();
            MenuDao mDao = new MenuDao(conn);
            MenuRoleDao mrDao = new MenuRoleDao(conn);
            MenuDto menu = mDao.getNextMenu();
            menu.setTitle(dto.getTitle());
            mDao.save(menu);
            mrDao.saveMenu(menu.getId());
           }

          posted @ 2007-05-13 14:09 afunms 閱讀(189) | 評論 (0)編輯 收藏

          perfect DAO design - related classes

               摘要: package afu.framework; import java.sql.Connection; import java.lang.reflect.Constructor; import afu.framework.service.*; import afu.framework.action.*; import af...  閱讀全文

          posted @ 2007-05-12 12:37 afunms 閱讀(130) | 評論 (0)編輯 收藏

          perfect DAO design

          perfect DAO solution

          ------BaseDao------
          public abstract class BaseDao
          {  
             private static final int maxRow = 1000;
             protected Connection conn;
             protected String table;
             protected Class<? extends DtoInterface> dtoClass;
             protected JspPage jspPage;
             protected boolean insideConnection;
                     
             public BaseDao(Connection conn)
             { 
              init();
              if(conn==null)
              {
               this.conn = ConnectionManager.getConnection();
               insideConnection = true;        
              }
              else
              {
                  this.conn = conn;   
                  insideConnection = false;
              }
             }

             public BaseDao()
             { 
              init();
              this.conn = ConnectionManager.getConnection();
              insideConnection = true;   
             }

             public void close(Statement stmt,ResultSet rs)
             {
              try
                 {
                    if(rs!= null)
                       rs.close();
                    if(stmt!=null)
                       stmt.close();
                    /**
                     * if the connection is passed from outside
                     * do not close it.
                     */
                    if(insideConnection)
                    ConnectionManager.close(conn);
                 }
                 catch(SQLException se)
                 {   
                 }
             }

             protected abstract void init();
          }

          ------sub dao class example------
          public class ProducerDao extends BaseDao
          {
           public ProducerDao(Connection conn)
           {
            super(conn);
           } 
           
           protected void init()
              {
               super.dtoClass = ProducerDto.class;
               super.table = "nms_producer";
              } 

          ------client code-----
          For the first scenario

             ProducerDao dao = new ProducerDao(null);
          or ProducerDao dao = (ProducerDao)BeanFactory.newDao("producer");
             dao.method();

          For the second scenario
             Connection conn = ConnectionManager.createConnection();
             ProducerDao dao1 = new ProducerDao(conn);
             AnOtherDao dao2 = new AnOtherDao(conn);
             dao1.method1();
             dao2.method2();
             dao2.method3();
             ConnectionManager.close(conn);   

          or Connection conn = ConnectionManager.createConnection();
             ProducerDao dao = (ProducerDao)BeanFactory.newDao("producer",conn);
             AnOtherDao dao = (AnOtherDao)BeanFactory.newDao("another",conn);
             dao1.method1();
             dao2.method2();
             dao2.method3();
             ConnectionManager.close(conn);   

          posted @ 2007-05-11 10:35 afunms 閱讀(142) | 評論 (0)編輯 收藏

          new architecture(10)--NetFlow

               摘要:   閱讀全文

          posted @ 2007-05-10 21:27 afunms 閱讀(102) | 評論 (0)編輯 收藏

          new framework(9)--detach NMS from MVC


                在SourceView1.0中,采集層的對象和表現(xiàn)層的對象經(jīng)常會混在一起,搞得很
          亂。而且因?yàn)閷ο蟮牟淮_定性給系統(tǒng)維護(hù)帶來很大困難。
                所以在SourceView2.0的設(shè)計中,我特地把這兩部分分開,分別放在mvc和nms
          這兩個包中。
              雖然只是簡單地分為兩個package,但卻標(biāo)志著設(shè)計思想的一大進(jìn)步。

          posted @ 2007-05-09 20:21 afunms 閱讀(115) | 評論 (0)編輯 收藏

          new framework(8)--import static

          現(xiàn)在J2SE 5.0提供了靜態(tài)導(dǎo)入的功能,你只需要在import關(guān)鍵字后面寫一個static關(guān)鍵字就可以直接
          使用類中定義的常量了,例如

          import static afu.framework.util.Constant.CURRENT_USER;
          import static afu.framework.util.Constant.EXCEPTION_MESSAGE;

              public String login()
              
          {
                  String userId 
          = getParaValue("userid");
                  String password 
          = getParaValue("password");
                  String remoteIp 
          = request.getRemoteAddr();
                  UserDto dto 
          = ((SysService)service).login(userId, password, remoteIp);
                  
                  
          if(dto==null)
                  
          {
                      request.setAttribute(EXCEPTION_MESSAGE,
          "用戶名或密碼不對");
                      
          return null;
                  }

                  request.setAttribute(CURRENT_USER,dto);
                  
          return "/common/index.jsp";
              }


          而沒有這個功能之前,我們得這么寫
          request.setAttribute(Constant.EXCEPTION_MESSAGE,"用戶名或密碼不對");

          posted @ 2007-05-08 10:40 afunms 閱讀(114) | 評論 (0)編輯 收藏

          new framework(7)--build sql via reflect

          利用反射構(gòu)成SQL語句,這樣,對于一般表的CURD,都可快速實(shí)現(xiàn)。

             protected String buildInsertSQL(ResultSetMetaData rsm,DtoInterface dto)
             
          {
                 String insertSql 
          = null;
                 
          try
                 
          {
                     StringBuffer sqlBuf 
          = new StringBuffer(50);
                     StringBuffer valueBuf 
          = new StringBuffer(50);
                     sqlBuf.append(
          "insert into ").append(table).append("(");
                     
          for(int i=1;i<=rsm.getColumnCount();i++
                     
          {
                         String methodName 
          = "get" + rsm.getColumnName(i).replaceAll("_"""); 
                         Method method 
          = lookupMethod(dtoClass.getMethods(), methodName);
                         
          if(method==null
                         

                             SysLogger.debug(
          "get" + rsm.getColumnName(i) + " does not exist"); 
                             
          continue;
                         }
           
                         sqlBuf.append(rsm.getColumnName(i)).append(
          ",");
                         valueBuf.append(
          "'").append(method.invoke(dto)).append("',");               
                     }

                     sqlBuf.delete(sqlBuf.length() 
          - 1, sqlBuf.length());
                     valueBuf.delete(valueBuf.length() 
          - 1, valueBuf.length());
                     sqlBuf.append(
          ")values(").append(valueBuf.toString()).append(")");
                     insertSql 
          = sqlBuf.toString();
                     SysLogger.debug(insertSql);
                 }

                 
          catch(Exception e)
                 
          {
                     SysLogger.error(
          "BaseDao.buildInsertSQL()",e);           
                 }

                 
          return insertSql;
             }

             
             
          protected String buildUpdateSQL(ResultSetMetaData rsm,DtoInterface dto)
             
          {
                 String updateSql 
          = null;
                 
          try
                 
          {
                     Method getId 
          = lookupMethod(dtoClass.getMethods(),"getId");
                     
          if(getId==null)
                     
          {
                         SysLogger.error(dtoClass.getClass().getName() 
          + ":getId method does not exist");
                         
          return null;
                     }

                     StringBuffer sqlBuf 
          = new StringBuffer(100);
                     sqlBuf.append(
          "update ").append(table).append(" set ");
                     
          for(int i=1;i<=rsm.getColumnCount();i++
                     
          {
                         
          if(rsm.getColumnName(i).equals("id")) continue;
                         
                         String methodName 
          = "get" + rsm.getColumnName(i).replaceAll("_"""); 
                         Method method 
          = lookupMethod(dtoClass.getMethods(), methodName);
                         
          if(method==null
                         

                             SysLogger.debug(
          "get" + rsm.getColumnName(i) + " does not exist"); 
                             
          continue;
                         }
                          
                         sqlBuf.append(rsm.getColumnName(i)).append(
          "='");
                         sqlBuf.append(method.invoke(dto)).append(
          "',");               
                     }

                     sqlBuf.delete(sqlBuf.length() 
          - 1, sqlBuf.length());           
                     sqlBuf.append(
          " where id='").append(getId.invoke(dto)).append("'");
                     updateSql 
          = sqlBuf.toString();
                     SysLogger.debug(updateSql);
                 }

                 
          catch(Exception e)
                 
          {
                     SysLogger.error(
          "BaseDao.buildUpdateSQL()",e);           
                 }

                 
          return updateSql;   
             }


           

          posted @ 2007-05-07 22:33 afunms 閱讀(152) | 評論 (0)編輯 收藏

          new framework(6)--extract data from ResultSet via reflect

          今天試了一下用反射從ResultSet 提取數(shù)據(jù),然后調(diào)用相應(yīng)的dto的方法。
          這樣就不要每次都針對一個新表來寫一次extractData方法了,挺爽的。
          缺點(diǎn)就是數(shù)據(jù)表中的字段與dto的方法必須一一對應(yīng)。

             /**
              * extract data from ResultSet to dto
              
          */

             
          protected DtoInterface extractData(ResultSet rs) throws Exception
             
          {
                 
          if(dtoClass == null

                    
          throw new NullPointerException("dtoClass is not setted!"
          ); 
                 
                 DtoInterface dto 
          =
           dtoClass.newInstance();
                 ResultSetMetaData rsm 
          =
           rs.getMetaData(); 
                 
          for(int i=1;i<=rsm.getColumnCount();i++

                 

                     String methodName 
          = "set" + rsm.getColumnName(i).replaceAll("_"""
          ); 
                     SysLogger.debug(
          "[" + rsm.getColumnName(i) + "]=" + rsm.getColumnType(i) + ",method=" +
           methodName);
                     Method method 
          =
           lookupMethod(dtoClass.getMethods(), methodName);
                     
          if(method==null

                     

                         SysLogger.error(
          "set" + rsm.getColumnName(i) + " does not exist"
          ); 
                         
          continue
          ;
                     }
           
                     
          if(rsm.getColumnType(i)==
          Types.INTEGER) 
                        method.invoke(dto,rs.getInt(i)); 
                     
          else if(rsm.getColumnType(i)==
          Types.VARCHAR) 
                        method.invoke(dto,rs.getString(i)); 
                 }
           
                 
          return
           dto; 
             }

             
             
          protected Method lookupMethod(Method[] methods,String methodName) 
             

                 Method result 
          = null

                 
          for
          (Method method:methods) 
                 

                     
          if
          (method.getName().equalsIgnoreCase(methodName)) 
                     

                         result 
          =
           method; 
                         
          break

                     }
           
                 }

                 
          return result; 
              }
           

          posted @ 2007-05-06 22:33 afunms 閱讀(127) | 評論 (0)編輯 收藏

          new framework(5)--build selectBox via reflect

               摘要: html中的selectBox也是令我頭疼的東西,因?yàn)樗偤蛿?shù)據(jù)庫關(guān)聯(lián),但我們在jsp中又不能直接調(diào)用dao, 就算直接調(diào)用了dao,jsp中的代碼也是一團(tuán)亂。所以我專門寫了這個類來解決這個問題。 我們只要專一個list給它,并告訴哪個方法可以得到key,哪個方法可以得到value, 就能生成一個selectBox。 package afu.framework.util; ...  閱讀全文

          posted @ 2007-05-05 21:10 afunms 閱讀(155) | 評論 (0)編輯 收藏

          new framework(4)--fetch request parameters value via reflect

          最討厭就是寫一大堆request.getParameter,新架構(gòu)中利用反射自動提取request中的參數(shù)值,
          然后把它們封閉成一個dto,真是太爽了。

           

              protected DtoInterface extractData(Class<? extends DtoInterface> clazz)
              
          {
                  DtoInterface dto 
          = null;
                  
          try
                  
          {
                      dto 
          = clazz.newInstance();
                      Method[] methods 
          = clazz.getMethods();
                      
          for(Method method:methods)
                      
          {
                          
          if(!method.getName().startsWith("set")) continue;
                          
                          String paraValue 
          = getParaValueByMethodName(method.getName().substring(3));
                          
          if(paraValue==nullcontinue;
                          
                          Class
          <?>[] types = method.getParameterTypes();
                          
          if(types==null || types.length==0)
                              
          continue;
                          
          //                System.out.println("methodName=" + method.getName());
          //                System.out.println("para=" + method.getName().substring(3));
          //                System.out.println("paraValue=" + paraValue);
                          
                          
          if(types[0].getName().equals("int"))
                             method.invoke(dto,Integer.parseInt(paraValue));
                          
          else if(types[0].getName().equals("long"))    
                             method.invoke(dto,Long.parseLong(paraValue));
                          
          else if(types[0].getName().equals("double"))    
                              method.invoke(dto,Double.parseDouble(paraValue));
                          
          else if(types[0].getName().equals("float"))    
                               method.invoke(dto,Float.parseFloat(paraValue));
                          
          else
                             method.invoke(dto,paraValue); 
          //String    
                      }

                  }

                  
          catch(Exception e)
                  
          {
                      SysLogger.error(
          "BaseAction.extractData()",e);    
                  }

                  
          return dto;
              }

              
              
          private String getParaValueByMethodName(String para)
              
          {
                  String result 
          = null;
                  
          for (Enumeration em = request.getParameterNames() ; em.hasMoreElements() ;)
                  
          {
                      String name 
          = (String)(em.nextElement());
                      String temp 
          = name.replaceAll("_","");
                      
          if(para.equalsIgnoreCase(temp))
                      
          {
                          result 
          = request.getParameter(name);
                          
          break;
                      }

                  }

                  
          return result;
              }

           

          posted @ 2007-05-04 20:56 afunms 閱讀(133) | 評論 (0)編輯 收藏

          new framework(3)--why add service

           之前的架構(gòu)都沒有service這一層,jsp到manager(action),然后在manager中調(diào)用dao。
          Action其實(shí)屬于web這一層,在web層直接調(diào)用dao是不妥的,所以新架構(gòu)中多了一層

          Service。Service位于action和dao之間,action把從jsp中傳來的參數(shù)封裝好傳給dao。

          我覺得最大好處就是不會在調(diào)用dao的同時又看到一大堆request.getParameter代碼。

          posted @ 2007-05-03 13:34 afunms 閱讀(108) | 評論 (0)編輯 收藏

          new framework(2)--why put Statement inside dao method

          原來Statement stmt = conn.createStatement();都是在放在BaseDao中,
          子類dao的方法中就可以直接用這個stmt,而且方法最后都會用finally
          來close這個stmt以及rs。

          這個做不好,因?yàn)閚ew一個dao后,不能連續(xù)調(diào)用兩個方法,因?yàn)榍耙粋€方法
          已經(jīng)把stmt關(guān)閉掉了。

          因此新架構(gòu)中,在每個方法中都加入Statement stmt = conn.createStatement();
          這樣就不會有上述問題了,但以增加代碼量為代價。
             例子:

              public void addSub(MenuDto dto)
              
          {
                  Connection conn 
          = getConnection();
                  
          try
                  
          {            
                      MenuDao mDao 
          = new MenuDao(conn);
                      MenuRoleDao mrDao 
          = new MenuRoleDao(conn);
                      MenuDto menu 
          = mDao.getNextMenu(dto.getId().substring(0,2));
                      
                      dto.setId(menu.getId());
                      dto.setSort(menu.getSort());
                      
                      mDao.save(dto);
                      mrDao.saveMenu(menu.getId());
                  }

                  
          catch(Exception e)
                  
          {     
                      ConnectionManager.rollback(conn);
                      SysLogger.error(
          "MenuService.addSub()",e);            
                  }
                  
              }

          MenuDao連續(xù)調(diào)用了兩個方法getNextMenusave,如果不把

          Statement stmt = conn.createStatement()置于方法內(nèi),那么我們要這樣寫:

                     MenuDao mDao = new MenuDao(conn);

                     MenuDto menu = mDao.getNextMenu(dto.getId().substring(0,2));          

          MenuDao mDao2 = new MenuDao(conn);

                     mDao2.save(dto);

          new兩次,不是不可以,但讓人感覺很不爽。

          posted @ 2007-05-02 13:24 afunms 閱讀(121) | 評論 (0)編輯 收藏

          new framework(1)--why put Connection outside dao

              原來我們都是在new dao時,同時獲得一個Connection  
              DaoInterface dao = new XxxxDao();

              為什么新架構(gòu)把Connection放在dao之外呢?為了實(shí)現(xiàn)事務(wù)。
              當(dāng)一個事務(wù)需要調(diào)用兩個dao中兩個(以上)方向時,如果出錯,
          只有同一個Connection才能實(shí)現(xiàn)rollback。
              DaoInterface dao = new XxxxDao(connection);

              /**
               * 這是兩個dao實(shí)現(xiàn)一個事處的最好例子
               
          */

              
          public void addTop(MenuDto dto)
              
          {
                  Connection conn 
          = getConnection();
                  
          try
                  
          {            
                      MenuDao mDao 
          = new MenuDao(conn);
                      MenuRoleDao mrDao 
          = new MenuRoleDao(conn);
                      MenuDto menu 
          = mDao.getNextMenu();
                      menu.setTitle(dto.getTitle());
                      mDao.save(menu);
                      mrDao.saveMenu(menu.getId());
                  }

                  
          catch(Exception e)
                  
          {     
                      ConnectionManager.rollback(conn);
                      SysLogger.error(
          "MenuService.addTop()",e);            
                  }
                  
              }
              當(dāng)然,我們也可以把所有的SQL寫在個dao中,同樣能實(shí)現(xiàn)rollback,
          但這樣做違背了dao操作的“原子性”。

          posted @ 2007-05-01 13:10 afunms 閱讀(137) | 評論 (0)編輯 收藏

          2007讀書(3)

          平時編碼時不曾注意的問題,看完這本書后,改進(jìn)了不少。

          posted @ 2007-03-04 17:24 afunms 閱讀(100) | 評論 (0)編輯 收藏

          僅列出標(biāo)題
          共25頁: First 上一頁 17 18 19 20 21 22 23 24 25 下一頁 

          My Links

          News

          留言簿(18)

          隨筆檔案

          相冊

          搜索

          最新評論

          閱讀排行榜

          主站蜘蛛池模板: 于田县| 全椒县| 张家口市| 安康市| 巴林右旗| 吉安县| 阿坝| 岳池县| 临武县| 天气| 衡东县| 揭阳市| 辽中县| 宁津县| 乌审旗| 曲沃县| 伊金霍洛旗| 临泽县| 岳池县| 固始县| 鄄城县| 双城市| 西贡区| 清远市| 新蔡县| 中西区| 乐清市| 云林县| 永定县| 阿拉善盟| 陆川县| 齐河县| 中山市| 武乡县| 青川县| 梓潼县| SHOW| 平乡县| 石河子市| 辽宁省| 凤阳县|