zoukankan      html  css  js  c++  java
  • 微社区项目开发笔记(后端篇)

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

           

       很明显,采用了经典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,欢迎指教不足之处!

  • 相关阅读:
    递归的初步应用
    最大公约数与最小公倍数(低效)
    进制转换
    凸多边形的面积问题
    单词替换
    DNA排序
    字符串排序
    倒三角形
    韩信点兵
    oracle
  • 原文地址:https://www.cnblogs.com/hyhk-jiy/p/5017140.html
Copyright © 2011-2022 走看看