#
		
			
			
			/**
 * 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实现一个事处的最好例子
  */
 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;        
  }  
 }
 
			
			
		 
	
		
			
			
			/**
 * 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());
 }
			
			
		 
	
		
			
			
			     摘要: package afu.framework;
import java.sql.Connection;
import java.lang.reflect.Constructor;
import afu.framework.service.*;
import afu.framework.action.*;
import af...  
阅读全文
			
			
		 
	
		
			
			
			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);    
 
			
			
		 
	
		
	
		
			
			
			
      在SourceView1.0中,采集层的对象和表现层的对象经常会混在一起,搞得很
乱。而且因为对象的不确定性给系统维护带来很大困难。
      所以在SourceView2.0的设计中,我特地把这两部分分开,分别放在mvc和nms
这两个包中。
    虽然只是简单地分为两个package,但却标志着设计思想的一大进步。 
			
			
		 
	
		
			
			
			现在J2SE 5.0提供了静态导入的功能,你只需要在import关键字后面写一个static关键字就可以直接
使用类中定义的常量了,例如
import static afu.framework.util.Constant.CURRENT_USER;
import static afu.framework.util.Constant.EXCEPTION_MESSAGE;
 public String login()
    public String login()

 
     {
{
 String userId = getParaValue("userid");
        String userId = getParaValue("userid");
 String password = getParaValue("password");
        String password = getParaValue("password");
 String remoteIp = request.getRemoteAddr();
        String remoteIp = request.getRemoteAddr();
 UserDto dto = ((SysService)service).login(userId, password, remoteIp);
        UserDto dto = ((SysService)service).login(userId, password, remoteIp);
 
        
 if(dto==null)
        if(dto==null)

 
         {
{
 request.setAttribute(EXCEPTION_MESSAGE,"用户名或密码不对");
            request.setAttribute(EXCEPTION_MESSAGE,"用户名或密码不对");
 return null;
            return null;
 }
        }
 request.setAttribute(CURRENT_USER,dto);
        request.setAttribute(CURRENT_USER,dto);
 return "/common/index.jsp";
        return "/common/index.jsp";
 }
    }

而没有这个功能之前,我们得这么写
request.setAttribute(Constant.EXCEPTION_MESSAGE,"用户名或密码不对");
 
			
			
		 
	
		
			
			
			利用反射构成SQL语句,这样,对于一般表的CURD,都可快速实现。
 protected String buildInsertSQL(ResultSetMetaData rsm,DtoInterface dto)
   protected String buildInsertSQL(ResultSetMetaData rsm,DtoInterface dto)

 
    {
{
 String insertSql = null;
       String insertSql = null;
 try
       try

 
        {
{
 StringBuffer sqlBuf = new StringBuffer(50);
           StringBuffer sqlBuf = new StringBuffer(50);
 StringBuffer valueBuf = new StringBuffer(50);
           StringBuffer valueBuf = new StringBuffer(50);
 sqlBuf.append("insert into ").append(table).append("(");
           sqlBuf.append("insert into ").append(table).append("(");
 for(int i=1;i<=rsm.getColumnCount();i++)
           for(int i=1;i<=rsm.getColumnCount();i++) 

 
            {
{
 String methodName = "get" + rsm.getColumnName(i).replaceAll("_", "");
               String methodName = "get" + rsm.getColumnName(i).replaceAll("_", ""); 
 Method method = lookupMethod(dtoClass.getMethods(), methodName);
               Method method = lookupMethod(dtoClass.getMethods(), methodName);
 if(method==null)
               if(method==null) 

 
                {
{ 
 SysLogger.debug("get" + rsm.getColumnName(i) + " does not exist");
                   SysLogger.debug("get" + rsm.getColumnName(i) + " does not exist"); 
 continue;
                   continue;
 }
               } 
 sqlBuf.append(rsm.getColumnName(i)).append(",");
               sqlBuf.append(rsm.getColumnName(i)).append(",");
 valueBuf.append("'").append(method.invoke(dto)).append("',");
               valueBuf.append("'").append(method.invoke(dto)).append("',");               
 }
           }
 sqlBuf.delete(sqlBuf.length() - 1, sqlBuf.length());
           sqlBuf.delete(sqlBuf.length() - 1, sqlBuf.length());
 valueBuf.delete(valueBuf.length() - 1, valueBuf.length());
           valueBuf.delete(valueBuf.length() - 1, valueBuf.length());
 sqlBuf.append(")values(").append(valueBuf.toString()).append(")");
           sqlBuf.append(")values(").append(valueBuf.toString()).append(")");
 insertSql = sqlBuf.toString();
           insertSql = sqlBuf.toString();
 SysLogger.debug(insertSql);
           SysLogger.debug(insertSql);
 }
       }
 catch(Exception e)
       catch(Exception e)

 
        {
{
 SysLogger.error("BaseDao.buildInsertSQL()",e);
           SysLogger.error("BaseDao.buildInsertSQL()",e);           
 }
       }
 return insertSql;
       return insertSql;
 }
   }
 
   
 protected String buildUpdateSQL(ResultSetMetaData rsm,DtoInterface dto)
   protected String buildUpdateSQL(ResultSetMetaData rsm,DtoInterface dto)

 
    {
{
 String updateSql = null;
       String updateSql = null;
 try
       try

 
        {
{
 Method getId = lookupMethod(dtoClass.getMethods(),"getId");
           Method getId = lookupMethod(dtoClass.getMethods(),"getId");
 if(getId==null)
           if(getId==null)

 
            {
{
 SysLogger.error(dtoClass.getClass().getName() + ":getId method does not exist");
               SysLogger.error(dtoClass.getClass().getName() + ":getId method does not exist");
 return null;
               return null;
 }
           }
 StringBuffer sqlBuf = new StringBuffer(100);
           StringBuffer sqlBuf = new StringBuffer(100);
 sqlBuf.append("update ").append(table).append(" set ");
           sqlBuf.append("update ").append(table).append(" set ");
 for(int i=1;i<=rsm.getColumnCount();i++)
           for(int i=1;i<=rsm.getColumnCount();i++) 

 
            {
{
 if(rsm.getColumnName(i).equals("id")) continue;
               if(rsm.getColumnName(i).equals("id")) continue;
 
               
 String methodName = "get" + rsm.getColumnName(i).replaceAll("_", "");
               String methodName = "get" + rsm.getColumnName(i).replaceAll("_", ""); 
 Method method = lookupMethod(dtoClass.getMethods(), methodName);
               Method method = lookupMethod(dtoClass.getMethods(), methodName);
 if(method==null)
               if(method==null) 

 
                {
{ 
 SysLogger.debug("get" + rsm.getColumnName(i) + " does not exist");
                   SysLogger.debug("get" + rsm.getColumnName(i) + " does not exist"); 
 continue;
                   continue;
 }
               }                
 sqlBuf.append(rsm.getColumnName(i)).append("='");
               sqlBuf.append(rsm.getColumnName(i)).append("='");
 sqlBuf.append(method.invoke(dto)).append("',");
               sqlBuf.append(method.invoke(dto)).append("',");               
 }
           }
 sqlBuf.delete(sqlBuf.length() - 1, sqlBuf.length());
           sqlBuf.delete(sqlBuf.length() - 1, sqlBuf.length());           
 sqlBuf.append(" where id='").append(getId.invoke(dto)).append("'");
           sqlBuf.append(" where id='").append(getId.invoke(dto)).append("'");
 updateSql = sqlBuf.toString();
           updateSql = sqlBuf.toString();
 SysLogger.debug(updateSql);
           SysLogger.debug(updateSql);
 }
       }
 catch(Exception e)
       catch(Exception e)

 
        {
{
 SysLogger.error("BaseDao.buildUpdateSQL()",e);
           SysLogger.error("BaseDao.buildUpdateSQL()",e);           
 }
       }
 return updateSql;
       return updateSql;   
 }
   }
 
 
			
			
		 
	
		
			
			
			今天试了一下用反射从ResultSet 提取数据,然后调用相应的dto的方法。 
这样就不要每次都针对一个新表来写一次extractData方法了,挺爽的。 
缺点就是数据表中的字段与dto的方法必须一一对应。 

 /** *//**
   /** *//**
 * extract data from ResultSet to dto
    * extract data from ResultSet to dto
 */
    */
 protected DtoInterface extractData(ResultSet rs) throws Exception
   protected DtoInterface extractData(ResultSet rs) throws Exception

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

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

 
            {
{ 
 SysLogger.error("set" + rsm.getColumnName(i) + " does not exist");
               SysLogger.error("set" + rsm.getColumnName(i) + " does not exist"); 
 continue;
               continue;
 }
           } 
 if(rsm.getColumnType(i)==Types.INTEGER)
           if(rsm.getColumnType(i)==Types.INTEGER) 
 method.invoke(dto,rs.getInt(i));
              method.invoke(dto,rs.getInt(i)); 
 else if(rsm.getColumnType(i)==Types.VARCHAR)
           else if(rsm.getColumnType(i)==Types.VARCHAR) 
 method.invoke(dto,rs.getString(i));
              method.invoke(dto,rs.getString(i)); 
 }
       } 
 return dto;
       return dto; 
 }
   }
 
   
 protected Method lookupMethod(Method[] methods,String methodName)
   protected Method lookupMethod(Method[] methods,String methodName) 

 
    {
{ 
 Method result = null;
       Method result = null; 
 for(Method method:methods)
       for(Method method:methods) 

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

 
            {
{ 
 result = method;
               result = method; 
 break;
               break; 
 }
           } 
 }
       }
 return result;
       return result; 
 }
    }  
	
		
			
			
			     摘要: html中的selectBox也是令我头疼的东西,因为它总和数据库关联,但我们在jsp中又不能直接调用dao,
就算直接调用了dao,jsp中的代码也是一团乱。所以我专门写了这个类来解决这个问题。
我们只要专一个list给它,并告诉哪个方法可以得到key,哪个方法可以得到value,
就能生成一个selectBox。
package afu.framework.util;
...  
阅读全文
			
			
		 
	
		
	
		
			
			
			 之前的架构都没有service这一层,jsp到manager(action),然后在manager中调用dao。
Action其实属于web这一层,在web层直接调用dao是不妥的,所以新架构中多了一层
Service。Service位于action和dao之间,action把从jsp中传来的参数封装好传给dao。
我觉得最大好处就是不会在调用dao的同时又看到一大堆request.getParameter代码。
 
			
			
		 
	
		
	
		
	
		
			
			
			
平时编码时不曾注意的问题,看完这本书后,改进了不少。