微社区项目开发笔记(后端篇)

  废话不说,先来张包结构的图片:

       

   很明显,采用了经典MVC三层架构。除了架构所需的包以外,还添加了一个工具包tool,里面有MD5加密和生成验证码的类,具体代码如下:

    

 1 package com.jiy.JcMiniSNS.tool;
 2 
 3 import java.security.MessageDigest;
 4 
 5 /**
 6  * MD5工具类
 7  * @author 来自网络
 8  *
 9  */
10 public class MD5Tool {
11     
12     //十六进制下数字到字符的映射数组    
13     private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};   
14       
15     /**  对字符串进行MD5加密     */    
16     private static String encodeByMD5(String originString){    
17         if (originString != null){    
18             try{    
19                 //创建具有指定算法名称的信息摘要    
20                 MessageDigest md = MessageDigest.getInstance("MD5");    
21                 //使用指定的字节数组对摘要进行最后更新,然后完成摘要计算    
22                 byte[] results = md.digest(originString.getBytes());    
23                 //将得到的字节数组变成字符串返回    
24                 String resultString = byteArrayToHexString(results);    
25                 //return resultString.toUpperCase();    
26                 return resultString;    
27             } catch(Exception ex){    
28                 ex.printStackTrace();    
29             }    
30         }    
31         return null;    
32     }   
33       
34     /** * 把inputString加密 */  
35     public static String generatePassword(String inputString) {  
36         return encodeByMD5(inputString);  
37     }  
38   
39     /** 
40      * 验证输入的密码是否正确 
41      * @param password 加密后的密码 
42      * @param inputString 输入的字符串 
43      * @return 验证结果,TRUE:正确 FALSE:错误 
44      */  
45     public static boolean validatePassword(String password, String inputString) {  
46         if (password.equals(encodeByMD5(inputString))) {  
47             return true;  
48         } else {  
49             return false;  
50         }  
51     }  
52       
53     /**   
54      * 转换字节数组为十六进制字符串  
55      * @param     字节数组  
56      * @return    十六进制字符串  
57      */    
58     private static String byteArrayToHexString(byte[] b){    
59         StringBuffer resultSb = new StringBuffer();    
60         for (int i = 0; i < b.length; i++){    
61             resultSb.append(byteToHexString(b[i]));    
62         }    
63         return resultSb.toString();    
64     }    
65         
66     /** 将一个字节转化成十六进制形式的字符串     */    
67     private static String byteToHexString(byte b){    
68         int n = b;    
69         if (n < 0)    
70             n = 256 + n;    
71         int d1 = n / 16;    
72         int d2 = n % 16;    
73         return hexDigits[d1] + hexDigits[d2];    
74     }    
75 }
MD5Tool.java

 

 1 package com.jiy.JcMiniSNS.tool;
 2 
 3 import java.awt.Color;
 4 import java.awt.Font;
 5 import java.awt.Graphics;
 6 import java.awt.image.BufferedImage;
 7 import java.io.IOException;
 8 import java.util.Random;
 9 
10 import javax.imageio.ImageIO;
11 import javax.servlet.http.HttpServletRequest;
12 import javax.servlet.http.HttpServletResponse;
13 
14 /**
15  * 验证码生成类
16  * @author jiy
17  *
18  */
19 public class VerificationCode {
20     
21     private static final int WIDTH=60;
22     private static final int HEIGHT=30;
23     
24     private BufferedImage img;
25     private Graphics g;
26     
27     public VerificationCode(HttpServletRequest request,HttpServletResponse response) throws IOException
28     {
29         init();
30         drawCode(request);
31         drawLine();
32         ImageIO.write(img, "gif", response.getOutputStream());
33     }
34     
35     private void init()
36     {
37         img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
38         g  = img.getGraphics();
39         g.setColor(Color.WHITE);
40         g.fillRect(0, 0, WIDTH, HEIGHT);
41         g.setColor(Color.RED);
42         g.drawRect(0, 0, WIDTH-1, HEIGHT-1);
43     }
44     
45     /**
46      * 画干扰线条
47      */
48     private void drawLine()
49     {
50         g.setColor(Color.BLUE);
51         Random r = new Random();
52         for(int i=0; i<3; i++){
53             g.drawLine(r.nextInt(WIDTH), r.nextInt(HEIGHT), r.nextInt(WIDTH), r.nextInt(HEIGHT));
54         }
55     }
56     
57     /**
58      * 画验证码并存入session
59      * @param request
60      */
61     private void drawCode(HttpServletRequest request)
62     {
63         Random r = new Random();
64         String checkCode = r.nextInt(9000)+1000+"";//1000-9999
65         g.setColor(Color.red);
66         g.setFont(new Font("微软雅黑",2,16));
67         g.drawString(checkCode, 10, 20);
68         //在Session中添加属性"checkCode"=验证码
69         request.getSession().setAttribute("checkCode", checkCode);
70         //System.out.println(checkCode);
71     }
72 }
VerificationCode

 

   在程序开发的过程中,我发现了以前经常用的BaseDao的不合理的地方:为了更好地封装数据库操作,大家通常会在BaseDao里面写一个叫做getQuery(String sql,Object...paras)的方法,并且把常用的Connection、PreparedStatement、ResultSet作为BaseDao的成员,然后让dao层的代码继承BaseDao。这样的做法明显提高了dao层代码的开发效率,但我发现在实际运用的时候出现了问题:

 

 1 /**
 2      * 执行查询操作
 3      * @param sql sql语句
 4      * @param paras 参数数组
 5      * @return 查询结果的ResultSet对象
 6      */
 7     public ResultSet getQuery(String sql,Object...paras)
 8     {
 9         try {
10             pstmt = conn.prepareStatement(sql);
11             if(paras != null && paras.length != 0)
12             {                
13                 for(int i = 0;i < paras.length;i++)
14                 {
15                     pstmt.setObject(i+1, paras[i]);
16                 }
17             }
18             res = pstmt.executeQuery();
19         } catch (SQLException e) {
20             throw new RuntimeException("执行查询失败!"+e.getMessage());
21         }
22         return res;
23     }

    如果在动态消息管理的实现类里面有一个找动态的方法叫做findDynamics()调用了getQuery(String sql,Object...paras)方法,同时在同一个类中也有一个叫做findTells()用于寻找相关动态的评论的方法调用了getQuery(String sql,Object...paras)这个方法,在findDynamics()遍历所查询到的ResultSet用于初始化相关对象的时候调用了findTells()方法,findTells()方法在调用getQuery(String sql,Object...paras)的过程中执行到了 res = pstmt.executeQuery(); 这行代码,由于是在同一个类中,所以他们的res对象是共享的,于是在findDynamics()遍历res对象第一遍的时候,res已经被重新赋值了。这样就导致无论怎么样只能得到一条dynamics的记录。

    所以,getQuery(String sql,Object...paras)方法中最好不要使用成员变量中的结果集。改进后完整的BaseDao类如下:

  1 package com.jiy.JcMiniSNS.dao;
  2 
  3 import java.sql.Connection;
  4 import java.sql.DriverManager;
  5 import java.sql.PreparedStatement;
  6 import java.sql.ResultSet;
  7 import java.sql.SQLException;
  8 
  9 
 10 /**
 11  * JDBC连接基本类
 12  * @author jiy
 13  *
 14  */
 15 public class BaseDao {
 16     
 17     
 18 //    private static final String DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
 19 //    private static final String URL = "jdbc:sqlserver://localhost:1433;DatabaseName=db_miniSNS";
 20     
 21     private static final String DRIVER = "com.mysql.jdbc.Driver";
 22     private static final String URL = "jdbc:mysql://localhost:3306/db_minisns";
 23     private static final String USER = "root";
 24     private static final String PWD = "root";
 25     
 26     public Connection conn = null;
 27     public PreparedStatement pstmt = null;
 28     public ResultSet res = null;
 29     
 30     static{
 31         try {
 32             Class.forName(DRIVER);
 33         } catch (ClassNotFoundException e) {
 34             throw new RuntimeException("数据库驱动加载失败!");
 35         }
 36     }
 37     
 38     /**
 39      * 获取jdbc连接
 40      */
 41     public void getConnection()
 42     {
 43         try {
 44             conn = DriverManager.getConnection(URL,USER,PWD);
 45             
 46         } catch (SQLException e) {
 47             throw new RuntimeException("获取数据库连接失败!" + e.getMessage());
 48         }
 49     }
 50     
 51     /**
 52      * 执行查询操作
 53      * @param sql sql语句
 54      * @param paras 参数数组
 55      * @return 查询结果的ResultSet对象
 56      */
 57     public ResultSet getQuery(String sql,Object...paras)
 58     {
 59         ResultSet queryRes = null;
 60         try {
 61             pstmt = conn.prepareStatement(sql);
 62             if(paras != null && paras.length != 0)
 63             {                
 64                 for(int i = 0;i < paras.length;i++)
 65                 {
 66                     pstmt.setObject(i+1, paras[i]);
 67                 }
 68             }
 69             queryRes = pstmt.executeQuery();
 70         } catch (SQLException e) {
 71             throw new RuntimeException("执行查询失败!"+e.getMessage());
 72         }
 73         return queryRes;
 74     }
 75     
 76     
 77     /**
 78      * 执行更新操作
 79      * @param sql sql语句
 80      * @param paras 参数列表
 81      * @return 受影响的行数
 82      */
 83     public int getUpdate(String sql,Object...paras)
 84     {
 85         int result = 0;
 86         try {
 87             pstmt = conn.prepareStatement(sql);
 88             if(paras != null && paras.length != 0)
 89             {                
 90                 for(int i = 0;i < paras.length;i++)
 91                 {
 92                     pstmt.setObject(i+1, paras[i]);
 93                 }
 94             }
 95             result = pstmt.executeUpdate();
 96         } catch (SQLException e) {
 97             throw new RuntimeException("执行更新失败!" +e.getMessage());
 98         }
 99         return result;
100     }
101     
102     /**
103      * 关闭资源
104      * 关闭ResultSet、PreparedStatement、Connection对象
105      */
106     public void closeAll()
107     {
108         if(res != null)
109         {
110             try {
111                 res.close();
112             } catch (SQLException e) {
113                 throw new RuntimeException("关闭ResultSet失败!");
114             }
115         }
116         if(pstmt != null)
117         {
118             try {
119                 pstmt.close();
120             } catch (SQLException e) {
121                 throw new RuntimeException("关闭PreparedStatement失败!");
122             }
123         }
124         if(conn != null)
125         {
126             try {
127                 conn.close();
128             } catch (SQLException e) {
129                 throw new RuntimeException("关闭Connection失败!");
130             }
131         }
132     }
133 }
BaseDao

    

     在访问网站首页的时候,需要加载数据库的数据怎么办呢?除了使用ajax,还可以在jsp里面加入如下代码:

    

<%
    try{
        if(request.getAttribute("dynamicList") == null)
            request.getRequestDispatcher("initDynamicForIndexServlet").forward(request, response);
    }catch(Exception e){
        
    }
%>

    

 

 

  到此,整个项目的笔记就结束了,由于刚开始写博客所以写的不是很好,请见谅!本人QQ:2632790902,欢迎指教不足之处!

posted @ 2015-12-03 19:20  无痕、  阅读(229)  评论(0编辑  收藏  举报

每天进步一点!